Использование пути к классам веб-приложений с использованием 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

Другие вопросы по тегам