Использование пути к классам веб-приложений с использованием JavaCompiler в Tomcat в Eclipse с Maven
У меня есть "Пример веб-приложения", который ссылается на "Пример библиотеки" с помощью Maven. Я использую Tomcat 7 в Eclipse 4.3RC3 с плагином m2e. Когда я запускаю Пример Webapp на Tomcat внутри Eclipse, я убедился, что example-library.jar
вероятно развертывается в экземпляре Tomcat WEB-INF/lib
папка.
У примера Webapp есть код, который компилирует определенные классы на лету, используя JavaCompiler.CompilationTask
, Эти динамически сгенерированные классы ссылаются на классы в example-library.jar
, К сожалению, задача компиляции терпит неудачу, потому что ссылочные классы не могут быть найдены.
Я понимаю, что могу установить JavaCompiler
classpath, но System.getProperty("java.class.path")
возвращает только путь к классам Tomcat, а не путь к классам веб-приложений:
C:\bin\tomcat\bin\bootstrap.jar;C:\bin\tomcat\bin\tomcat-juli.jar;C:\bin\jdk6\lib\tools.jar
Другие говорили, что мне нужно получить реальный путь WEB-INF/lib
из контекста сервлета, но код генерации класса ничего не знает о контексте сервлета - он написан, чтобы не зависеть от того, используется ли он на клиенте или на сервере.
В другом вопросе один ответ показал, что я мог бы перечислить URL загрузчика классов, и, конечно же, это дает мне банку в WEB-INF/lib
, но когда я предоставляю это как -classpath
возможность compiler.getTask()
, задача все еще не выполнена, потому что она не может найти указанные классы.
Как я могу просто указать путь к классу исполняемого в данный момент кода JavaCompiler
экземпляр, так что он найдет классы из библиотек в WEB-INF/lib
? ( Подобный вопрос был поднят, но никогда не отвечал относительно ссылок на jar-файлы в файлах ear с использованием JavaCompiler
.)
Пример: пытаясь заставить вещи работать любой ценой, я даже пытался жестко закодировать путь к классам. Например, у меня есть foobar.lib
в моем каталоге 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();
В конце success
является false
, и мой diaognostics
указывает package com.example.foo.bar does not exist...
даже если этот пакет находится в foobar.jar
,
3 ответа
Поместите example-library.jar где-нибудь в вашей файловой системе и передайте это местоположение коду, который выполняет JavaCompiler (опция -classpath). Если вы используете развернутый WAR-файл для развертывания, вы, конечно, можете указать его физическое местоположение в папке WEB-INF/lib. Дело в том, что для этого вам нужен только один настраиваемый параметр в вашем веб-приложении, который может быть записью в файле свойств, системным свойством -D, строкой базы данных или чем-то другим.
Пример кода (протестирован в Tomcat 7 и OpenJDK 1.7 на Fedora 18 x64):
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];
}
См. https://github.com/jpalomaki/compiler для запускаемого примера веб-приложения.
Я встретил тот же вопрос. Причина не в "-классе" .
мой код:
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();
"результат" вернет истину.
Вы можете следовать ответу, предоставленному для еще более конкретного вопроса о том, как загружать зависимости скомпилированного кода из веб-приложения, работающего непосредственно из нерасширенного файла WAR (нет файлов JAR для ссылки - только загрузчик классов контейнера знает, как получить доступ занятия): /questions/44654017/ispolzovanie-javacompiler-s-classpath-ssyilayuschimsya-na-jar-vnutri-uha/44654036#44654036