Я создаю инструмент CLI, который интегрируется с несколькими модулями EJB. По этой причине мне нужно построить fat jar
, который затем выполняется как отдельное приложение.Создание автономного исполняемого JAR с OpenEJB
Однако выполнение этого fat jar
с java -jar
(Примечание: conf/openejb.xml
находится в том же каталоге, что и fat jar
) выдает следующее StackTrace:
INFORMATION - PersistenceUnit(name=demo, provider=org.hibernate.jpa.HibernatePersistenceProvider) - provider time 2706ms
INFORMATION - Jndi(name="java:global/DemoMain/demo-shade-1.0-SNAPSHOT/MEJB!javax.management.j2ee.ManagementHome")
INFORMATION - Jndi(name="java:global/DemoMain/demo-shade-1.0-SNAPSHOT/MEJB")
INFORMATION - Jndi(name="java:global/DemoMain/demo-shade-1.0-SNAPSHOT/openejb/Deployer!org.apache.openejb.assembler.Deployer")
INFORMATION - Jndi(name="java:global/DemoMain/demo-shade-1.0-SNAPSHOT/openejb/Deployer")
INFORMATION - Jndi(name="java:global/DemoMain/demo-shade-1.0-SNAPSHOT/openejb/ConfigurationInfo!org.apache.openejb.assembler.classic.cmd.ConfigurationInfo")
INFORMATION - Jndi(name="java:global/DemoMain/demo-shade-1.0-SNAPSHOT/openejb/ConfigurationInfo")
INFORMATION - Jndi(name="java:global/DemoMain/demo-shade-1.0-SNAPSHOT/DemoServiceImpl!com.github.rzo1.service.DemoService")
INFORMATION - Jndi(name="java:global/DemoMain/demo-shade-1.0-SNAPSHOT/DemoServiceImpl")
INFORMATION - Existing thread singleton service in SystemInstance(): [email protected]
INFORMATION - Closing DataSource: demoDS
INFORMATION - Closing DataSource: demoDSNonJTA
Exception in thread "Thread-0" java.lang.RuntimeException: org.apache.openejb.OpenEjbContainer$AssembleApplicationException: javax.enterprise.inject.spi.DeploymentException: couldn't start owb context
at com.github.rzo1.DemoMain.run(DemoMain.java:116)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.apache.openejb.OpenEjbContainer$AssembleApplicationException: javax.enterprise.inject.spi.DeploymentException: couldn't start owb context
at org.apache.openejb.OpenEjbContainer$Provider.createEJBContainer(OpenEjbContainer.java:346)
at javax.ejb.embeddable.EJBContainer.createEJBContainer(EJBContainer.java:56)
at com.github.rzo1.DemoMain.run(DemoMain.java:90)
... 1 more
Caused by: javax.enterprise.inject.spi.DeploymentException: couldn't start owb context
at org.apache.openejb.cdi.ThreadSingletonServiceImpl.initialize(ThreadSingletonServiceImpl.java:191)
at org.apache.openejb.cdi.CdiBuilder.build(CdiBuilder.java:41)
at org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:913)
at org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:717)
at org.apache.openejb.OpenEjbContainer$Provider.createEJBContainer(OpenEjbContainer.java:342)
... 3 more
Caused by: org.apache.webbeans.exception.WebBeansException: Wrong startup object.
at org.apache.webbeans.web.lifecycle.WebContainerLifecycle.getServletContext(WebContainerLifecycle.java:227)
at org.apache.webbeans.web.lifecycle.WebContainerLifecycle.startApplication(WebContainerLifecycle.java:86)
at org.apache.openejb.cdi.ThreadSingletonServiceImpl.initialize(ThreadSingletonServiceImpl.java:189)
... 7 more
Выполнение кода непосредственно из моего IDE (IntelliJ) автономный контейнер появляется и ведет себя так, как ожидалось.
Версия Резюме:
openejb
в версии1.7.0
/openejb-server
в версии7.0.2
maven-shade-plugin
в версии2.4.3
Maven
в версии3.3.9
hibernate
в версии5.2.7
Основные настройки
Я был в состоянии воспроизвести мою проблему на простой рабочий пример, который я добавил as an GitHub project для дальнейшего исследования.
Базовая схема проекта заключается в следующем:
| # demo-shade
| - demo-services (EJB-Module)
| - demo-main (Shading happens here)
Конфигурация maven-shade-plugin
выглядит следующим образом:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>demo-shade-${project.version}</finalName>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>com.github.rzo1.DemoMain</Main-Class>
</manifestEntries>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/openwebbeans/openwebbeans.properties</resource>
</transformer>
</transformers>
<filters>
<filter> <!-- we don't want JSF to be activated -->
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/faces-config.xml</exclude>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<shadedClassifierName>dist</shadedClassifierName>
</configuration>
</execution>
</executions>
</plugin>
код для запуска контейнера:
EJBContainer ejbContainer = null;
try {
final Properties properties = new Properties();
properties.setProperty(EJBContainer.APP_NAME, applicationName);
properties.setProperty(EJBContainer.PROVIDER, OpenEjbContainer.class.getName());
properties.setProperty(OpenEjbContainer.OPENEJB_EMBEDDED_REMOTABLE, "false");
properties.setProperty("ejbd.disabled", "true");
properties.setProperty("ejbds.disabled", "true");
properties.setProperty("admin.disabled", "true");
properties.setProperty("openejb.jaxrs.application", "false");
Path launchPath = Paths.get(DemoMain.class.getProtectionDomain().getCodeSource().getLocation().toURI());
properties.setProperty("openejb.configuration", launchPath.toAbsolutePath() + "/conf/openejb.xml");
properties.put("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
properties.put("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver");
// This is the line starting the EJB container
ejbContainer = EJBContainer.createEJBContainer(properties);
ejbContainer.getContext().bind("inject", this);
ejbContainerReady = true;
final CountDownLatch latch = new CountDownLatch(1);
// Graceful shutdown
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
try {
logger.info("Shutting down..");
latch.countDown();
logger.info("Shutdown completed successfully.");
} catch (final Exception e) {
logger.error("Graceful shutdown went wrong. SIGKILL (kill -9) if you want.", e);
}
}
});
try {
latch.await();
} catch (final InterruptedException e) {
// ignored
}
} catch (final Exception e) {
ejbContainerReady = false;
throw new RuntimeException(e);
} finally {
if (ejbContainer != null) {
ejbContainer.close();
}
}
}
Вопросы
Я пропустил что-то в конфигурации
maven-shade-plugin
?Как я могу построить
fat jar
с помощьюopenejb
в автономном режиме?
Пример проекта
UPDATE 1:
Я изменил ПОМ согласно ответу П. Merkle.Я нашел еще одну статью here, описывающую процесс затенения специально для TomEE.
pom
изменен
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>demo-shade-${project.version}</finalName>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>com.github.rzo1.DemoMain</Main-Class>
</manifestEntries>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer implementation="org.apache.openwebbeans.maven.shade.OpenWebBeansPropertiesTransformer"/>
</transformers>
<filters>
<filter> <!-- we don't want JSF to be activated -->
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/faces-config.xml</exclude>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<shadedClassifierName>dist</shadedClassifierName>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.apache.openwebbeans</groupId>
<artifactId>openwebbeans-maven</artifactId>
<version>1.7.0</version>
</dependency>
</dependencies>
</plugin>
Extecuting это fat jar
приносит:
INFORMATION - OpenWebBeans Container is starting...
INFORMATION - Adding OpenWebBeansPlugin : [CdiPlugin]
SCHWERWIEGEND - CDI Beans module deployment failed
java.lang.NullPointerException
at org.apache.openejb.cdi.CdiScanner.handleBda(CdiScanner.java:271)
at org.apache.openejb.cdi.CdiScanner.init(CdiScanner.java:148)
at org.apache.openejb.cdi.OpenEJBLifecycle.startApplication(OpenEJBLifecycle.java:179)
at org.apache.openejb.cdi.ThreadSingletonServiceImpl.initialize(ThreadSingletonServiceImpl.java:189)
at org.apache.openejb.cdi.CdiBuilder.build(CdiBuilder.java:41)
at org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:913)
at org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:717)
at org.apache.openejb.OpenEjbContainer$Provider.createEJBContainer(OpenEjbContainer.java:342)
at javax.ejb.embeddable.EJBContainer.createEJBContainer(EJBContainer.java:56)
at com.github.rzo1.DemoMain.run(DemoMain.java:90)
at java.lang.Thread.run(Unknown Source)
INFORMATION - Closing DataSource: demoDS
INFORMATION - Closing DataSource: demoDSNonJTA
Exception in thread "Thread-0" java.lang.RuntimeException: org.apache.openejb.OpenEjbContainer$AssembleApplicationException: javax.enterprise.inject.spi.DeploymentException: couldn't start owb context
at com.github.rzo1.DemoMain.run(DemoMain.java:116)
at java.lang.Thread.run(Unknown Source)
Caused by: org.apache.openejb.OpenEjbContainer$AssembleApplicationException: javax.enterprise.inject.spi.DeploymentException: couldn't start owb context
at org.apache.openejb.OpenEjbContainer$Provider.createEJBContainer(OpenEjbContainer.java:346)
at javax.ejb.embeddable.EJBContainer.createEJBContainer(EJBContainer.java:56)
at com.github.rzo1.DemoMain.run(DemoMain.java:90)
... 1 more
Caused by: javax.enterprise.inject.spi.DeploymentException: couldn't start owb context
at org.apache.openejb.cdi.ThreadSingletonServiceImpl.initialize(ThreadSingletonServiceImpl.java:191)
at org.apache.openejb.cdi.CdiBuilder.build(CdiBuilder.java:41)
at org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:913)
at org.apache.openejb.assembler.classic.Assembler.createApplication(Assembler.java:717)
at org.apache.openejb.OpenEjbContainer$Provider.createEJBContainer(OpenEjbContainer.java:342)
... 3 more
Caused by: org.apache.openejb.OpenEJBRuntimeException: java.lang.NullPointerException
at org.apache.openejb.cdi.OpenEJBLifecycle.startApplication(OpenEJBLifecycle.java:200)
at org.apache.openejb.cdi.ThreadSingletonServiceImpl.initialize(ThreadSingletonServiceImpl.java:189)
... 7 more
Caused by: java.lang.NullPointerException
at org.apache.openejb.cdi.CdiScanner.handleBda(CdiScanner.java:271)
at org.apache.openejb.cdi.CdiScanner.init(CdiScanner.java:148)
at org.apache.openejb.cdi.OpenEJBLifecycle.startApplication(OpenEJBLifecycle.java:179)
... 8 more
Я добавил ветку с этим меняется на GitHub Project для дальнейшего исследования.
UPDATE 2
я исключил javax.xml.*
из тени:
<excludes>
<exclude>META-INF/faces-config.xml</exclude>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
<exclude>javax/xml/**</exclude>
</excludes>
Однако исключение остается такой же, как и в Update 1. Я оттолкнул связанный branch в хранилище GitHub.
Так что мой вопрос:
- Что еще должен быть исключен из тени?
С помощью других ответов я, наконец, смог найти рабочее решение для создания автономного fat jar
, который работает на мой случай использования.
ОБНОВЛЕНИЕ 3:
Стадии (на данный момент) являются:
Использование
OpenWebBeansPropertiesTransformer
вместоAppendingTransformer
как заявлено P. MerkleИсключить
java.xml.*
в тени, как заявлено Romain Manni-Bucau:<excludes> <exclude>META-INF/faces-config.xml</exclude> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> <exclude>javax/xml/**</exclude>
Добавить
scan.xml
вMETA-INF
включая только пакеты/классы, которые должны сканироваться. Текущая рабочая версия может быть найдена here
Вопрос:
- Является ли их официальный или лучший способ сделать это?
http://stackoverflow.com/questions/2707733/eager-auto-loading-of-ejb-load-ejb-on-startup- on-jboss, http://blog.eisele.net/2010/12/seven-ways-to-get-things-started-java.html – Ali786
Это не совсем то, что я ищу ?! – rzo