【发布时间】:2018-01-14 05:48:57
【问题描述】:
我正在尝试使用 Jetty、OpenEJB 和 WebApps 以编程方式设置环境来开发和运行 Selenium 测试。本文中描述的内容非常相似:http://tomee.apache.org/functional-testing-with-openejb,-jetty-and-selenium.html。
这个设置很好,因为我可以通过IDE或Maven启动selenium测试,并使用相同的代码启动一个Server进行开发。
我看到这个设置使用旧版本的 Jetty (6.2) 和 EJB 3.0 中的未知 EJB 容器(称为 MyContainer)。现在我正在(或尝试做...)一个新项目中做同样的事情,它将在 Wildfly 10.1.0 中运行并通过 CDI (BeanManager) 进行 EJB 查找。
但是我在让 CDI 在较新版本的 Jetty 和 OpenEJB 或 TomEE 中正常工作时遇到了一些麻烦。我无法在 Internet 上找到与较新版本的框架相同的示例。我什至不知道我是否真的需要 Jetty 来做到这一点。
第一次尝试:Jetty(没有 jetty-jndi)+ OpenEJB + tomee.jpa.cdi=false
使用 OpenEJB 4.7.4 和 Jetty 9.4,当我运行代码 CDI.current().getBeanManager() 时:
java.lang.IllegalStateException: Unable to access CDI
persistence.xml:
<property name="tomee.jpa.cdi" value="false" />
Obs.:beans.xml 文件在所有尝试中都在我的 webapp 的 WEB-INF 目录中。
第二次尝试:Jetty(没有 jetty-jndi)+ TomEE + tomee.jpa.cdi=false
使用 TomEE 7.0.3 和 Jetty 9.4,我可以让 CDI 仅在 Maven 依赖项中更改 TomEE 的 OpenEJB(奇怪!据说 OpenEJB 支持 CDI)。当我在服务器设置中间进行调试时,此 CDI 有效,但是当程序运行 webapp 时,在我尝试进行 EJB 查找时发生错误:
"On a thread without an initialized context nor a classloader mapping a deployed app"
第三次尝试:Jetty(使用 jetty-jndi)+ TomEE 或 OpenEJB + tomee.jpa.cdi=false
EJB 容器启动但 Jetty 服务器无法启动,因为找不到 java:comp/env/。
javax.naming.NameNotFoundException: Name "comp/env" not found
添加代码:
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");
第四次尝试:Jetty(没有 jetty-jndi)+ TomEE + tomee.jpa.factory.lazy=true
更改persistence.xml中的属性:
<property name="tomee.jpa.factory.lazy" value="true" />
EJB 容器启动并且 CDI.current() 存在,但是当我尝试使用代码执行一些 SQL 之后:
@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();
}
}
});
系统在Session session = em.unwrap(Session.class); 停了很多时间。之后,出现了很多错误(Unable to build Hibernate SessionFactory,Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister)并且在stacktrace的末尾:
Caused by: javax.ejb.ConcurrentAccessTimeoutException: No instances available in Stateless Session Bean pool. Waited 30 SECONDS
问题
那么,可能是类路径问题吗?在从旧的 EJB 容器中删除一些依赖项后,我已经遇到了 TomEE CDI 的一些问题。我已经阅读了 CDI 问题,原因是与 cdi-api 依赖项相关的错误导入。
如果有人有一些与我非常不同(且更简单)的想法来使这种环境发挥作用,那么也欢迎。
代码的一些相关部分
Maven 依赖 JavaEE API:
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
Maven 依赖 CDI API:
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.2</version>
<scope>provided</scope>
</dependency>
Maven 依赖 OpenEJB 4.7.4:
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>openejb-core</artifactId>
<version>4.7.4</version>
</dependency>
Maven 依赖 TomEE 7.0.3:
<dependency>
<groupId>org.apache.tomee</groupId>
<artifactId>openejb-core</artifactId>
<version>7.0.3</version>
</dependency>
Maven 依赖 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 查找代码 (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);
}
创建 EJBContainer:
EJBContainer.createEJBContainer(props).getContext(); //nothing special in the props
【问题讨论】:
标签: ejb jetty cdi apache-tomee openejb