July 3rd, 2007

SQLException: Charset cp850/Cp850 is not supported by the JVM.

I recently had to reinstall Tomcat on my development server at work, because my previous installation was having major issues for unknown reasons. When I finished installing it, and deploying my webapps to it, I ran into this annoying character set issue (which I was not getting with the previous installation).

I could swear I’d seen this message before, and several of my co-workers thought they recognized it, too, but nobody knew what to do about it. Every time I started the tomcat service, it was spitting out these three stack traces, for every webapp, in my exception log:

Class: net.sourceforge.jtds.jdbc.ConnectionJDBC2
Method: loadCharset
SQL STATE: 2C000
SQL ERROR CODE: 0
STACKTRACE:
java.sql.SQLException: Charset cp850/Cp850 is not supported by the JVM.
[...]

Class: org.apache.catalina.valves.JDBCAccessLogValve
Method: start
EXCEPTION WRAPPER MESSAGE:
[ERROR] ContainerBase.addChild: start:
STACKTRACE:
LifecycleException:
java.sql.SQLException: Charset cp850/Cp850 is not supported by the JVM.
[...]

Class: org.apache.catalina.core.ContainerBase
Method: addChildInternal
EXCEPTION WRAPPER MESSAGE:
[ERROR] Error deploying web application archive [foo].war
STACKTRACE:
java.lang.IllegalStateException: ContainerBase.addChild: start:
LifecycleException: java.sql.SQLException:
Charset cp850/Cp850 is not supported by the JVM.
[...]

NOTE: These stack traces only show the top line and context info, to avoid cluttering up the blog post too much. [View full stack traces here]

To troubleshoot this, I first tried cleaning out all the already-compiled classes/jars from my source code tree, and rebuilding/redeploying all the webapps, but the same behavior continued. Next, I wiped out my whole source code tree, checked it all out from CVS again, and rebuilt/redeployed all the webapps. Still got the stupid cp850 exceptions.

Before, during, and after all of that rebuilding stuff, I spent hours doing web searches on various search engines, tweaking my queries, and not turning up much of anything.

At one point, it seemed like it had to be a problem with my Sybase ASE 12.5 database configuration. I didn’t like the sound of that, though, because it’s much easier to reinstall an app server and redeploy my webapps, than it is to rebuild my database and recreate the necessary test data.

I thought maybe our build script wasn’t deploying the right versions of all the jars that needed to be deployed, so I slowly started copying the jars from my backup of my previous tomcat installation, and copying all the configuration files, and so forth. Eventually, my entire tomcat directory tree had been replaced with the backed-up tomcat installation, but the evil cp850 exceptions still lingered!

Now it was *really* looking like a database issue! I searched all the files on the machine for ‘cp850′ (case-insensitive search), and turned up nothing useful. When I searched the windows registry, I found one thing that was intriguing:

KEY: HKEY_LOCAL_MACHINE\
SOFTWARE\SYBASE\Server\
[MyServerName]_BS\Parameters\
VALUE NAME: Arg5
VALUE TYPE: REG_SZ
VALUE DATA: -Jcp850

I asked my co-workers to check their registries, but they had the same thing, and their servers were behaving just fine. Besides, this was just the backup server (BCKServer), not the actual SQLServer. So that was a dead end.

I poked around for a while longer, and *finally* figured out that it was the JVM that the Tomcat service was configured to use. When installing it, I had chosen the default JVM that it had selected, because it looked right.

The installer defaulted to the JVM that was installed with the Java plugin for web browsers and such:
C:\Program Files\Java\jre1.5.0_06\bin\server\jvm.dll

But I needed to use the one that was installed with the JDK I compiled with:
C:\Program Files\Java\jdk1.5.0_06\jre\bin\server\jvm.dll

I believe the reason for this is because when I downloaded the JDK, it either only came in one package, which included international support, or I happened to choose the package that included international support. For the Java plugin download, though, I must have selected the US/English-only package, because it was smaller or something.

That was a nightmare to track down, and I hope that by posting this, I can save someone else the time and trouble!

March 30th, 2007

The difference between introspection and reflection in Java

I haven’t used any of the fun introspection/reflection stuff in Java for quite some time, so I got confused about terminology, recently. I kept using the words introspection and reflection interchangeably, but it sounded wrong/made me feel stupid every time I did. A quick Google search provided me with a concise explanation of the differences.

From Java Tip 71 on javaworld.com:

One question that is asked often is, What’s the difference between introspection and reflection? The answer: Reflection allows you to find out which members an object has; and introspection allows you to identify which (JavaBean) properties an object has. That’s why the java.lang.reflect lives in a separate package, and the Introspector object is in the java.beans package. Links to these packages on Sun’s Java site, as well as further information on JavaBeans, are available in the Resources section below.

The key things to recognize are:

  • reflection can be done on any class
  • introspection provides additional info about JavaBeans

June 28th, 2006

Making System.out.println() return a String

At some point, recently, I needed to do both of these things in one little Java expression:
- output a String to stdout
- return the same String

System.out.println() returns ‘void’, and you can’t cast void to String, so I struggled with this for a little while. Here’s what I came up with (download here if it looks ugly in the blog):

public class VoidToString
{
public static void main(String[] args)
{
System.out.println(”returned value: [” +
new Object()
{
public String q(String p)
{
System.out.println(”stdout: [” + p + “]”);
return p;
}
}.q(”blah”) + “]”);
}
}


It ended up not working in the context I was trying to use it in, because the 3rd-party API I was using did not appreciate the inner class, but I still thought it was a neat little trick.

April 28th, 2006

Talking over SSL from Java

For the first time in this blog, I’m pleased to present to you a
guest post from my good friend, Jeff Scanlon:


Talking over SSL from Java
————————–When using SSLFactory to talk SSL with a server, or using
the URL class to open an https connection, an error you
might encounter is:

sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target

One solution that worked for me is to add the server certificate
to the cacerts file in the appropriate Java runtime.

Steps:

  1. You must have the server certificate. If you don’t have this
    handy, navigate to the secure website, click on the lock icon
    (in Internet Explorer). Click on “Details” tab and then click
    the “Copy to File…” button. Export the certificate to a DER
    encoded binary X.509 (.CER) file. Let’s say you chose the
    filename example.cer
  2. Copy example.cer to the jre/lib/security directory in the Java
    runtime you are using. If you’re on Windows and the JDK/JRE
    is in C:\jdk1.5.0_04, then the full path is:
    C:\jdk1.5.0_04\jre\lib\security
  3. Import the certificate into the cacerts file by using the
    following command [editor’s note: this is all one command, broken
    into multiple lines for blogging
    ]:

    keytool -import -storepass changeit -file
    example.cer -keystore cacerts
    -alias example

    ‘changeit’ is the default password to the cacerts keystore
    ‘example.cer’ is the filename you used in step #1
    ‘example’ is an arbitrary alias you choose for the certificate
  4. Now try your code and see if it can establish the SSL
    connection. If you get an error like ‘HTTPS hostname
    wrong: should be ____’, then add this code:

    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLSession; // ————————————————-

    HostnameVerifier hv = new HostnameVerifier() {
    public boolean verify(String hostName,
    SSLSession session)
    {
    System.out.println(
    “hostName is [” + hostName +
    “] and session peer host is [” +
    session.getPeerHost() + “]”);
    return(true);
    }
    };

    HttpsURLConnection.setDefaultHostnameVerifier(hv);


    The above code provides a hostname verifier replacement that
    will cause hostname verification to succeed (by always
    returning true). Be aware that using this code does have
    security implications. However, this simplistic verify
    replacement should solve SSL communication problems and
    provide a starting point for implementing a custom verify
    that maintains security.


Jeff has been a good friend of mine for about 16 years, now.
He has been published several times (such as here,
here, and here), and is usually the first person I turn
to for ideas/advice on any programming/computer-related topic. He will definitely be contributing to this blog again in the future.