peterh
peterh

Reputation: 19235

Use custom charset in webapp

I'm having some trouble using a custom charset from a webapp. The charset is provided in a JAR and Charset.forName("MYCUSTOMCHARSET") works without problems from a Java SE application. However from within a webapp this method will throw UnsupportedCharsetException.

I understand that this is an issue of class loaders and I know that I can solve the problem by adding the JAR to the servlet engine's classpath. But that is not what I want. I want to be able to deliver a self-contained WAR file to my customer without the customer having to fiddle with the surrounding container.

In other words: I'm searching for a method that will allow my webapp to load the charset "manually". From the services folder in the JAR which provides the custom charset I can see the fully qualified name of the CharsetProvider, e.g. com.acme.CustomCharsetProvider. I wonder if this will help me somehow ?

Platform: Java 8 and Tomcat 8.

Upvotes: 0

Views: 2337

Answers (1)

peterh
peterh

Reputation: 19235

Based on comment above from Joop I was able to come up with the following. The method below is an attempt at a bullet-proof recipe for always being able to get hold of the custom charset no matter what scenario we are in (e.g. standalone Java SE application, webapp, etc).

In the method the custom charset is expected to be provided by class com.acme.CustomCharsetProvider (replace with your own).

The method uses three different attempts to get hold of the charset:

  1. Standard method. This will work in Java SE applications but not in webapps unless the JAR which holds the custom charset is available on the servlet engine's classpath.
  2. ServiceLoader method. This should work, but not in my case. Can't explain why.
  3. Manually instantiating the provider class. (this works for me)

Here's the code:

public static Charset getMyCustomCharset() throws java.nio.charset.UnsupportedCharsetException {
    Charset customCharset = null;
    try {
        // This will fail if running in web container because
        // the JDK loads charsets using the system class loader in the servlet
        // engine (e.g. Tomcat) so unless the JAR is available on the engine's
        // classpath then the charset will not be visible to the webapp.
        // The solution is to load the charset "manually" as below.
        customCharset = Charset.forName(CHARSET_NAME);
    } catch (Exception ex) {
        // Try to load the charset manually using ServiceLoader concept
        for (CharsetProvider charsetProvider : ServiceLoader.load(com.acme.CustomCharsetProvider.class)) {
            customCharset  = charsetProvider.charsetForName(CHARSET_NAME);
            if (customCharset != null) {
                break;
            }
        }
        // Make a final attempt. This time directly, i.e. without the use of
        // the ServiceLoader.
        if (customCharset == null) {
            com.acme.CustomCharsetProvider p = new com.acme.CustomCharsetProvider();
            customCharset = p.charsetForName(CHARSET_NAME);
        }
    }
    if (customCharset == null) {
        throw new java.nio.charset.UnsupportedCharsetException("Unknown charset : " + CHARSET_NAME);
    }
    return customCharset;
}

Upvotes: 4

Related Questions