Выполнение Jar сервера программно (смола Caucho)

Я успешно использовал веб-сервер Caucho Resin и собираюсь упаковать его в Java-приложение. Они предоставляют файл JAR и код для программного запуска сервера.

Example: example/TestResin.java

package example;

import com.caucho.resin.*;

public class TestResin {

  public static void main(String []args)
  {
    ResinEmbed resin = new ResinEmbed();

    HttpEmbed http = new HttpEmbed(8080);
    resin.addPort(http);

    WebAppEmbed webApp = new WebAppEmbed("/", "/var/www/htdocs");
    resin.addWebApp(webApp);

    resin.start();
    resin.join();
  }
}

Однако я получаю следующую ошибку

java.lang.NoClassDefFoundError: javax/transaction/TransactionManager
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    at com.caucho.server.resin.EnvInit.init(EnvInit.java:49)
    at com.caucho.server.resin.EnvInit.<init>(EnvInit.java:44)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at java.lang.Class.newInstance(Class.java:374)
    at com.caucho.loader.Environment.initializeEnvironment(Environment.java:971)
    at com.caucho.resin.ResinEmbed.start(ResinEmbed.java:320)
    at com.mycompany.server.Resin.main(Resin.java:23)
Caused by: java.lang.ClassNotFoundException: javax.transaction.TransactionManager
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 22 more
Exception in thread "main" java.lang.NoClassDefFoundError: javax/enterprise/inject/spi/BeanManager
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    at com.caucho.env.service.ResinSystem.<init>(ResinSystem.java:138)
    at com.caucho.env.service.ResinSystem.<init>(ResinSystem.java:99)
    at com.caucho.server.resin.Resin.<init>(Resin.java:236)
    at com.caucho.server.resin.ResinEmbedded.<init>(ResinEmbedded.java:46)
    at com.caucho.resin.ResinEmbed.start(ResinEmbed.java:322)
    at com.mycompany.server.Resin.main(Resin.java:23)
Caused by: java.lang.ClassNotFoundException: javax.enterprise.inject.spi.BeanManager
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 18 more
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)

Решение:

Добавлена ​​библиотека javaee-16.jar, найденная в каталоге установки glassfish, и все работает. Очевидно, что выгрузка glassfish-api.jar из Oracle не работает, потому что включены только объявления методов и никаких реализаций.

3 ответа

Решение

Добавлена ​​библиотека javaee-16.jar, найденная в каталоге установки glassfish, и все работает.

Используйте это, чтобы интерпретировать банку так, как будто вы java -jar ...:

File f = new File("resin-3.1.0/lib/resin.jar");
URL url = new URL("file", null, f.getAbsolutePath());
ClassLoader cl = new URLClassLoader(new URL[] {url});
Class<?> mcls = cl.loadClass("a.b.c.Main");
Method mmethod = mcls.getMethod("main", new Class[] {String[].class});
mmethod.invoke(mcls);

Здесь Resin будет работать в своем собственном загрузчике классов.

Это вопрос жизненного цикла процесса, который следует тщательно рассмотреть для вашего приложения. Есть несколько способов сделать это:

  • Выполнение из вашего приложения через Runtime.getRuntime().exec() или эквивалент. По сути, порождайте какой-то процесс вне запущенной JVM из вашего приложения.
  • Написание сценариев и / или cron работа внешне. То есть внешне порождает какой-то процесс вне вашего приложения.
  • Запуск веб-сервера main() метод из потока в вашем приложении. (Вы можете определить это, проверив jarманифест ее Main Class.) Это означает, что вы запускаете его как поток (или потоки) внутри вашей работающей JVM.

Исходя из этого, мы можем определить, что вы должны учитывать два аспекта:

  1. Spawn / контроль изнутри или вне вашего приложения.
  2. Запуск изнутри или снаружи вашей JVM.

Суть в том, что вам придется определить, что лучше всего подходит для вашего приложения, поскольку вы знаете, кто будет его запускать, как оно будет развернуто, будет ли оно работать долго или в течение короткого времени, будет ли оно порождено часто или нечасто и т. д. советую выбирать тщательно. Часто люди оставляют это как запоздалую мысль, которая часто приводит к большим головным болям в будущем.

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