2013-06-02 4 views
4

У меня есть существующий пример Webapp, который ссылается на «Библиотека примеров» с использованием Maven. Я запускаю Tomcat 7 внутри Eclipse 4.3RC3 с плагином m2e. Когда я запускаю пример Webapp на Tomcat внутри Eclipse, я подтвердил, что example-library.jar, вероятно, будет развернут в папке WEB-INF/lib экземпляра Tomcat.Использовать путь к классу webapp с помощью JavaCompiler в Tomcat в Eclipse с Maven

Пример Webapp имеет код, который компилирует определенные классы «на лету», используя JavaCompiler.CompilationTask. Эти динамически сгенерированные классы задают классы в example-library.jar. К сожалению, задача компиляции терпит неудачу, потому что ссылочные классы не могут быть найдены.

Я понимаю, что я могу set the 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 

Другие имеют said, что мне нужно, чтобы получить реальный путь WEB-INF/lib из контекста сервлета но код генерации класса ничего не знает о контексте сервлета - он написан как агностик о том, используется ли он на клиенте или на сервере.

В another question, один answer указал, я мог бы перечислить ClassLoader URL-адреса, и конечно это дает мне баночки в WEB-INF/lib, но когда я обеспечиваю это как -classpath вариант для compiler.getTask(), задача по-прежнему не удается, потому что она не может найдите ссылочные классы.

Как я могу просто предоставить путь класса текущего исполняемого кода к экземпляру JavaCompiler, чтобы он нашел классы из библиотек в WEB-INF/lib? (A similar question был поднят, но никогда не отвечал относительно ссылок на банки в файлах уха с помощью JavaCompiler.)

Пример: В попытке заставить его работать любой ценой, я даже пытался жестко прописать путь к классам. Например, у меня есть foobar.lib в моей WebAPP 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.

ответ

1

Поместите example-library.jar где-нибудь в вашей файловой системе и передайте это место коду, который запускает JavaCompiler (опция -classpath). Если вы используете развернутый файл WAR для развертывания, вы можете, конечно, указать его на физическое местоположение в папке WEB-INF/lib. Дело в том, что для этого вам нужен только один настраиваемый параметр в вашем webapp, который может быть вложением файла свойств, -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 для образца работоспособный веб-приложение.

+0

Вы внимательно прочитали мой вопрос, а также ссылки, которые я предоставил? Как ваш ответ отличается от тех подходов, которые я уже пробовал, которые, кроме того, предоставили фактический код? –

+0

Да, я прочитал ваш вопрос. Вы предоставили ссылку на ответ stackoverflow, который показал вам, как вы можете установить JavaCompiler -classpath, а затем вы спросили: «Как вы можете просто предоставить путь к классу в настоящее время, выполняющий код для JavaCompiler». Теперь просто создайте строку classpath (например, /path/to/webapp/WEB-INF/lib/example-library.jar) и передайте ее javaCompiler. Не нужно, чтобы ваш компонент знал что-либо о сервлет-контекстах или URL-адресах загрузчиков классов. – Jukka

+0

Я уже пробовал это, и он не работает. Я обновил вопрос, чтобы включить пример того, что я пробовал. Может быть, вы можете указать, что я делаю неправильно. –

0

Я встретил тот же вопрос. Причина не в «классовом пути».

мой код:

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(); 

«Результат» возвращает истину.

0

Вы можете выполнить ответ, предоставленный для еще более конкретного вопроса о том, как загружать зависимости скомпилированного кода из веб-приложения, запущенного непосредственно из файла нераскрытой WAR (для ссылки на файлы JAR нет ссылки - только класс класса контейнера знает, как получить доступ к классам): https://stackoverflow.com/a/45038007/2546679

 Смежные вопросы

  • Нет связанных вопросов^_^