2013-06-02 33 views
4

我有一个使用Maven引用“Example Library”的现有“示例Webapp”。我使用m2e插件在Eclipse 4.3RC3内部运行Tomcat 7。当我在Eclipse内部的Tomcat上启动示例Webapp时,我已验证example-library.jar可能正在部署在Tomcat实例的WEB-INF/lib文件夹中。在Maven中使用Tomcat中的Tomcat中的JavaCompiler使用webapp classpath

示例Web应用程序具有使用JavaCompiler.CompilationTask即时编译某些类的代码。这些动态生成的类引用example-library.jar中的类。不幸的是编译任务失败,因为无法找到引用的类。

我知道我可以set the JavaCompiler classpath,但System.getProperty("java.class.path")只返回我Tomcat的类路径,而不是Web应用程序类路径:

C:\bin\tomcat\bin\bootstrap.jar;C:\bin\tomcat\bin\tomcat-juli.jar;C:\bin\jdk6\lib\tools.jar 

其他有said,我需要从servlet上下文得到的WEB-INF/lib真实路径,但类生成代码并不知道关于servlet上下文的任何信息---它被写成不知道它是在客户端还是在服务器上使用。

another question,一个answer表示我可以列举的类加载器的网址,果然这为我提供了的罐子在WEB-INF/lib,但是当我提供这作为-classpath选项compiler.getTask(),任务仍然失败,因为它不能找到引用的类。

如何简单地将当前正在执行的代码的类路径提供给JavaCompiler实例,以便它可以从WEB-INF/lib的库中找到类? (A similar question升高而对于使用JavaCompiler引用耳朵文件中的罐子根本没有回答。)

例子:在试图得到的东西,不惜任何代价的工作,我甚至尝试硬编码的类路径。例如,我在我的web应用lib目录foobar.lib,所以用下面的代码,来自我上面所指出的问题的答案修改:

List<String> options = new ArrayList<String>(); 
options.add("-classpath"); 
options.add("C:\\work\\.metadata\\.plugins\\org.eclipse.wst.server.core\\tmp0\\wtpwebapps\\FooBar\\WEB-INF\\lib\\foobar.jar"); 
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits); 
boolean success = task.call(); 

在端successfalse,我的diaognostics表示package com.example.foo.bar does not exist...,即使该包在foobar.jar

回答

1

将example-library.jar放入文件系统的某个位置,并将该位置传递给运行JavaCompiler的代码(-classpath选项)。如果您使用展开的WAR文件进行部署,则当然可以将其指向WEB-INF/lib文件夹中的物理位置。重点是你只需要在你的webapp中有一个可配置的参数来做到这一点,它可以是一个属性文件入口,-D系统属性,数据库行或其他东西。

示例代码(在Fedora 18 64 Tomcat中7和OpenJDK的1.7测试):

private File compile(File javaFile, String classpath) throws IOException { 
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
    StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); 
    Iterable<? extends JavaFileObject> compilationUnit = fileManager.getJavaFileObjects(javaFile); 
    List<String> options = classpath != null ? Arrays.asList("-classpath", classpath) : null; 
    StringWriter output = new StringWriter(); 
    try { 
     boolean successful = compiler.getTask(output, fileManager, null, options, null, compilationUnit).call(); 
     if (!successful) { 
      throw new CompilationException("Failed to compile: " + javaFile, output.toString()); 
     } 
     return firstClassFileFrom(javaFile.getParentFile()); 
    } finally { 
     fileManager.close(); 
    } 
} 

private File firstClassFileFrom(File directory) { 
    return directory.listFiles(new FilenameFilter() { 
     @Override 
     public boolean accept(File dir, String name) { 
      return name.endsWith(".class"); 
     } 
    })[0]; 
} 

为可运行的web应用样品参见https://github.com/jpalomaki/compiler

+0

您是否仔细阅读过我的问题以及我提供的链接?你的答案与我已经尝试的方法有什么不同,而且提供了实际的代码? –

+0

是的,我的确看过你的问题。您提供了一个指向stackoverflow答案的链接,向您展示了如何设置JavaCompiler -classpath,然后您问“如何简单地向JavaCompiler提供当前正在执行的代码的类路径”。现在只需创建classpath字符串(例如/path/to/webapp/WEB-INF/lib/example-library.jar)并将其传递给javaCompiler。您的组件无需了解有关Servlet上下文或类加载器URL的任何信息。 – Jukka

+0

我已经尝试过了,并且不起作用。我已经更新了这个问题,以包含我尝试过的一个例子。也许你可以指出我做错了什么。 –

0

我遇到了同样的问题。原因不是“-classpath”。

我的代码:

String classpath ="xx/WEB-INF/clases "; 
    List<String> options = classpath != null ? Arrays.asList("-d", classpath,"-cp",classpath) : null; 
    CompilationTask task = compiler.getTask(null, javaDinamicoManager, diagnostics, 
      options, null, Arrays.asList(sourceObj)); 
    boolean result = task.call(); 

的“结果”将返回true。

0

您可以按照提供的答案提供更具体的问题,以了解如何从直接从未展开WAR文件运行的Web应用程序中加载编译代码的依赖关系(没有要引用的JAR文件 - 只有容器的类代码知道如何进入课程):https://stackoverflow.com/a/45038007/2546679