System.getProperty(“java.class.path”) does not show “WEB-INF/lib” and the including jars

拜拜、爱过 提交于 2019-11-30 20:32:10

问题


String CompilePath = "abc.java";
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
String classpath = System.getProperty("java.class.path");
System.setProperty("java.class.path", classpath + ";" + LocalMachine.home + "WebContent/WEB-INF/lib");
int result = compiler.run(null, null, null, CompilePath);

The above runs fine when executed as a JUnit test since all the jars required for compiling the abc.java file. But when the same code is being run in as server, it fails to find the required jar files. The output of System.getProperty("java.class.path") is E:\apache-tomcat-7.0.4\bin\bootstrap.jar;E:\apache-tomcat-7.0.4\bin\tomcat-juli.jar;C:\Program Files\Java\jdk1.6.0_21\lib\tools.jar

So, my question is how do I make the compiler refer to the jar files from the WEB-INF/lib directory?


回答1:


They way you are setting the java.class.path system property is asking for trouble - better not do that. More elegant approach would be to use the -classpath option to pass in the custom classpath. See How do I use JDK6 ToolProvider and JavaCompiler with the context classloader? for details.

Also this question can be useful reference: Using javax.tools.ToolProvider from a custom classloader?


As to building the actual classpath, you could cast the context classloader to URLClassLoader and get files from those URLs (as done in this answer).

Or you could use ServletContext.getRealPath(String) and build the entire classpath by hand:

ServletConfig cfg = ...; //obtained in Servlet.init(ServletConfig) method
ServletContex ctx = cfg.getServletContext();
String realWebInfPath = ctx.getRealPath("WEB-INF/lib");
//TODO use the realWebInfPath to create a File object and iterate over all JAR files

Warning: both approaches ONLY work if web application is expanded (not WAR file). If it is not expanded, you are out of luck.




回答2:


You cannot depend on java.class.path to be set to anything in particular.

Java establishes this variable when it launches the entire JVM containing your servlet container. As it creates many different class loaders for many different other purposes, it does not change it. It cannot. There is only one value of java.class.path for the entire process, but there can be many different webapps, and indeed many different class loaders inside each webapp.

You will need your own explicit configuration mechanism to communicate the class path for this sort of compilation stuff, and to use getRealPath to construct the pathnames.




回答3:


So, my question is how do I make the compiler refer to the jar files from the WEB-INF/lib directory?

Provide that the webapp's WAR is expanded, you should be able to programmatically create a classpath string that corresponds to what the web container gives you. It is "simply" a matter of duplicating the effective class search path that the web container uses.

However, I suspect that passing a "classpath" argument to the compiler, explicitly or via the System properties is the wrong approach. I found the following in this IBM article.

Compiling Java source requires the following components:

  • A classpath, from which the compiler can resolve library classes. The compiler classpath is typically composed of an ordered list of file system directories and archive files (JAR or ZIP files) that contain previously compiled .class files. The classpath is implemented by a JavaFileManager that manages multiple source and class JavaFileObject instances and the ClassLoader passed to the JavaFileManager constructor. ...

So it would seem that the correct approach is to just grab the relevant classloader object and pass it to the JavaFileManager constructor.




回答4:


Assuming you are using ANT to build your WAR file. You need to do something like below to include jars under WEB-INF/lib in your WAR. Modify the directory structure as it fits your app directory structure.

<war warfile="yourApp.war" webxml="WEB-INF/web.xml">
            <fileset dir="yourWarDir">
                <include name="**/*.jsp"/>  
                <include name="**/include/**"/>
            </fileset>
            <include name="WEB-INF/lib/*"/>
            <include name="WEB-INF/classes/**"/>

</war>


来源:https://stackoverflow.com/questions/4273039/system-getpropertyjava-class-path-does-not-show-web-inf-lib-and-the-includ

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!