Jared
Jared

Reputation: 2133

Tomcat webapp ClassLoader not working with runtime compilation

I have some Java classes that are generated at runtime and compiled using a

JavaCompiler.CompilationTask.

The generated code references classes that are in other projects that are maven dependencies of my project. Everything runs fine locally, but when I deploy to our dev Tomcat server, I get a bunch of

"package xxx does not exist"

and

"cannot find symbol"

errors in the compilation task. I checked the WEB-INF/lib directory of the Tomcat-deployed webapp project, and all of the jars are there, including the project dependencies. Isn't everything in the WEB-INF/lib dir supposed to be available to a Tomcat project at runtime?

EDIT: Here is my context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <Loader className="org.apache.catalina.loader.VirtualWebappLoader"
        virtualClasspath="${catalina.home}/webapps/kdweb/WEB-INF/lib/acommons-0.0.1-SNAPSHOT.jar;${catalina.home}/webapps/kdweb/WEB-INF/lib/abizcommons-0.0.1-SNAPSHOT.jar;${catalina.home}/webapps/kdweb/WEB-INF/lib/kd_market_data-common-0.0.1-SNAPSHOT.jar;${catalina.home}/webapps/kdweb/WEB-INF/lib/aggregation-0.0.1-SNAPSHOT.jar;${catalina.home}/webapps/kdweb/WEB-INF/lib/apods-client-0.0.1-SNAPSHOT.jar;${catalina.home}/webapps/kdweb/WEB-INF/lib/framework-common-0.0.1-SNAPSHOT.jar" />
</Context>

Upvotes: 5

Views: 958

Answers (3)

timlg07
timlg07

Reputation: 626

While @Jared's solution led me in the right direction, I needed to make a few adjustments to get it to work:

  1. Specify the full path, in my case: /opt/tomcat/webapps/ROOT/lib/<libname>.jar
  2. Use : instead of ; as a delimiter to separate the paths.
  3. Add to the original default classpath instead of replacing it. So just add System.getProperty("java.class.path") (separated with a :) to your string.

Upvotes: 0

Jared
Jared

Reputation: 2133

It turns out that I needed to pass an explicit classpath to the JavaCompiler.CompilationTask in the code. Here is how I got it to work:

String classPath = "webapps/WEB-INF/lib/jar1.jar;webapps/WEB-INF/lib/jar2.jar";
List<String> options = new ArrayList<String>();
options.addAll(Arrays.asList("-classpath", classPath));
final JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, options, null, Arrays.asList(source));

Upvotes: 1

Scis
Scis

Reputation: 2974

you can use the Loader and set the reloadable to true.(This might be related as well)

Upvotes: 1

Related Questions