I'm trying to setup programatically an environment with Jetty, OpenEJB and WebApps to development and run Selenium tests. Something very similar described in this article: http://tomee.apache.org/functional-testing-with-openejb,-jetty-and-selenium.html.
This setup is very good, because I can start selenium test by the IDE or Maven, and use the same code to start a Server for development.
I saw this setup working using an old version of Jetty (6.2) and with an unknown EJB container (called MyContainer) in EJB 3.0. Now I'm doing (or tryingto do ...) the same thing in a newer project, that will run in Wildfly 10.1.0 and do EJB lookups by CDI (BeanManager).
But I have some troubles to put CDI to work correctly in the newer versions of Jetty and OpenEJB or TomEE. I can't find another examples on Internet to the same thing with newer versions of the frameworks. I don't even know if I really need Jetty to do that.
First attempt: Jetty (without jetty-jndi) + OpenEJB + tomee.jpa.cdi=false
Using the OpenEJB 4.7.4 and Jetty 9.4, when I run the code CDI.current().getBeanManager()
results in:
java.lang.IllegalStateException: Unable to access CDI
persistence.xml:
<property name="tomee.jpa.cdi" value="false" />
Obs.: The beans.xml file is in the WEB-INF directory of my webapp in all attempts.
Second attempt: Jetty (without jetty-jndi) + TomEE + tomee.jpa.cdi=false
Using TomEE 7.0.3 and Jetty 9.4, I'm able to have CDI only changing OpenEJB for TomEE in maven dependency (weird! It's supposed that OpenEJB have CDI support). This CDI works when I'm debugging in the middle of the Server setup, but when the program hit the webapp, occur an error whem I'm trying to made a EJB lookup:
"On a thread without an initialized context nor a classloader mapping a deployed app"
Third attempt: Jetty (with jetty-jndi) + TomEE or OpenEJB + tomee.jpa.cdi=false
EJB Container starts but Jetty server can't start because not found java:comp/env/
.
javax.naming.NameNotFoundException: Name "comp/env" not found
Code added:
Configuration.ClassList classlist = Configuration.ClassList.setServerDefault(server);
classlist.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration",
"org.eclipse.jetty.plus.webapp.EnvConfiguration",
"org.eclipse.jetty.plus.webapp.PlusConfiguration");
Fourth attempt: Jetty (without jetty-jndi) + TomEE + tomee.jpa.factory.lazy=true
Change the property in persistence.xml:
<property name="tomee.jpa.factory.lazy" value="true" />
The EJB container started and CDI.current() exists, but when I try to execute some SQLs after that with the code:
@PersistenceContext(unitName="my-pu")
private EntityManager em;
//method
Session session = em.unwrap(Session.class);
session.doWork(new Work() {
@Override
public void execute(Connection connection) throws SQLException {
try (Statement statement = connection.createStatement()) {
statement.executeUpdate(sql);
connection.commit();
}
}
});
The system stops a lot of time in Session session = em.unwrap(Session.class);
. After that, a lot of errors appear (Unable to build Hibernate SessionFactory
, Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister
) and at the end of the stacktrace:
Caused by: javax.ejb.ConcurrentAccessTimeoutException: No instances available in Stateless Session Bean pool. Waited 30 SECONDS
Question
So, could be a classpath problem? I already had some problems with TomEE CDI that was resolved after remove some of dependencies from the old EJB container. I already read about CDI problems that the cause was wrong imports related with cdi-api
dependency.
If someone has some very different (and simpler) idea than mine to made this kind of environment work, it's welcome too.
Some relevant parts of the code
Maven dependency JavaEE API:
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
Maven dependency CDI API:
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.2</version>
<scope>provided</scope>
</dependency>
Maven dependency OpenEJB 4.7.4:
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-core</artifactId>
<version>4.7.4</version>
</dependency>
Maven dependency TomEE 7.0.3:
<dependency>
<groupId>org.apache.tomee</groupId>
<artifactId>openejb-core</artifactId>
<version>7.0.3</version>
</dependency>
Maven dependency Jetty:
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.6.v20170531</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>9.4.6.v20170531</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-plus</artifactId>
<version>9.4.6.v20170531</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jndi</artifactId>
<version>9.4.6.v20170531</version>
</dependency>
persistence.xml
<!-- I uncomment only one of this properties each time -->
<!-- <property name="tomee.jpa.factory.lazy" value="true" />-->
<property name="tomee.jpa.cdi" value="false" />
ServiceLocator lookup code (ServiceLocator.lookup(CrudService.class)
):
@Override
public Object lookup(Class<?> type, Annotation... annotations) throws NamingException {
BeanManager manager = CDI.current().getBeanManager();
Iterator<Bean<?>> beans = manager.getBeans(type, annotations).iterator();
if (!beans.hasNext()) {
throw new NamingException("CDI BeanManager cannot find an instance of requested type " + type.getName());
}
Bean<?> bean = beans.next();
CreationalContext<?> ctx = manager.createCreationalContext(bean);
return manager.getReference(bean, type, ctx);
}
Create EJBContainer:
EJBContainer.createEJBContainer(props).getContext(); //nothing special in the props