On Mar 21, 2013, at 4:31 PM, Nick Williams wrote:

> I have built an executable Tomcat JAR file. It has all of the Tomcat classes 
> and dependencies zipped into one big JAR. Inside that JAR is also a WAR file, 
> the native DLL, and logging.properties. My com.ul.io.Bootstrap class creates 
> an .extract directory in the CWD, extracts the native DLL, WAR file and 
> logging.properties, configures Tomcat logging, configures a Tomcat class 
> instance, adds the WAR file is a web app, starts the Tomcat class instance, 
> and waits for it.
> 
> If I run this JAR like this:
> 
>> java -jar PeripheralProxy-1.0.0.SNAPSHOT.jar
> 
> Everything works fine. It starts up, I can go to the application, no errors 
> in the logs ... everything is perfect. The output from stdout is below if 
> you're interested. Now, I take the same JAR file and sign it with the jar 
> signer. To make sure nothing got messed up, I run the signed JAR file:
> 
>> java -jar PeripheralProxy-1.0.0.SNAPSHOT-signed.jar
> 
> This worked to. Exact same stdout output, application works fine. Perfect! 
> Next I created a JNLP file with, among other things, <security> set to 
> <all-permissions />. I open the JNLP file in my browser. It accepts the 
> certificate and starts the JAR file. First problem is logging doesn't work. 
> Not sure why. I had to enable the Java console in Java Control Panel to see 
> what was going on.
> 
> 1) It created the .extract directory, so the first step worked.
> 2) It extracted the WAR file, native DLL and logging.properties without a 
> problem, so that worked, too.
> 3) It could not deploy the application. At this point it began getting class 
> loading errors.
> 
> The output from the Java console is also below. Anyone have a clue what went 
> wrong? Obviously the classes ARE in the JAR file, otherwise it wouldn't work 
> from the command line.
> 
> <snip>

Well, I got this working. I'm not sure anyone has ever successfully done this 
before, because I didn't really find much of anything on Google that helped. 
Here's what I had to do:

1) Sign the JAR and use <all-permissions />. This was a given and I was already 
doing this.

2) Use tomcat-embed-logging-log4j instead of tomcat-embed-logging-juli. The Web 
Start deployer is NOT friendly to the way JULI deals with class loaders.

3) Don't put ANY classes in the WAR files included in the JAR file. ALL classes 
(Tomcat AND application AND dependency classes) must go in the 
root/embedded/same JAR. Otherwise the security manager detects that they were 
loaded differently and doesn't apply the <all-permissions /> rule to them. 
There IS an alternative to this: System.setSecurityManager(null). But that's 
not pretty, and discouraged.

4) After instantiating the Tomcat instance and before starting it, set the 
parent class loaders to the current thread context class loader. Otherwise 
Tomcat tries to use the System class loader. You cannot use the System class 
loader in Java Web Start. None of the application classes are loaded by it.

        Tomcat tomcat = new Tomcat();
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        tomcat.getEngine().setParentClassLoader(loader);
        tomcat.getHost().setParentClassLoader(loader);
        tomcat.getServer().setParentClassLoader(loader);
        tomcat.getService().setParentClassLoader(loader);

5) Patch JarScanner. The JarScanner only scans JARs at URLs starting with file: 
and jndi:. It ignores http: and https: URLs, and in Web Start, all JAR URLs 
start with http: or https:. I filed bug 54745 about this, because it's a 
noninvasive patch that I think improves Tomcat.
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to