Dependency injection EJB3.1设计难题-需要从MDB实例化有状态bean

Dependency injection EJB3.1设计难题-需要从MDB实例化有状态bean,dependency-injection,ejb-3.1,message-driven-bean,stateful-session-bean,Dependency Injection,Ejb 3.1,Message Driven Bean,Stateful Session Bean,最近我对EJB3.1了解了很多,但显然还不够。这是我的悲伤故事 我和servlet有一场战争,批处理文件可以上传到servlet。servlet验证文件,将文件数据存储在数据库中,并向队列发送一条消息,表明已收到新批。这一切都很好 我有一个部署了ejbjar的ear,它有一个MDB,用于侦听新的批接收消息 它还有一个有状态EJB(使用无接口视图)来执行实际的批处理。EJB引用了无状态JPA实体服务bean,因此需要对其进行容器管理,以获得容器注入的EntityManager 每当MDB收到消息时

最近我对EJB3.1了解了很多,但显然还不够。这是我的悲伤故事

我和servlet有一场战争,批处理文件可以上传到servlet。servlet验证文件,将文件数据存储在数据库中,并向队列发送一条消息,表明已收到新批。这一切都很好

我有一个部署了ejbjar的ear,它有一个MDB,用于侦听新的批接收消息

它还有一个有状态EJB(使用无接口视图)来执行实际的批处理。EJB引用了无状态JPA实体服务bean,因此需要对其进行容器管理,以获得容器注入的EntityManager

每当MDB收到消息时,我需要创建有状态处理器bean的实例。我还没有找到任何涉及此场景的示例/教程

我已经尝试将有状态bean注入MDB,但它不起作用:

[#|2011-11-24T13:25:45.470-0700|SEVERE|glassfish3.1.1|javax.enterprise.system.container.ejb.mdb.com.sun.ejb.containers|_ThreadID=21;_ThreadName=Thread-2;|MDB00050: Message-driven bean [MyProcessor-ear-1.0:MyMDB]: Exception in creating message-driven ejb : [com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Remote ejb-ref name=my.package.MyMDB/myEJB,Remote 3.x interface =my.package.MyEJB,ejb-link=null,lookup=,mappedName=,jndi-name=my.package.MyEJB,refType=Session into class my.package.MyMDB: Lookup failed for 'java:comp/env/my.package.MyMDB/myEJB' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming}]|#]
显然这是一种糟糕的设计方法,因为MDB本质上是无状态的,所以不应该注入有状态的EJB。这是有道理的


我的问题是,当MDB接收到消息并确保EJB是容器管理的时,我还可以如何实例化我的有状态EJB?

如果您需要像上面指出的那样为批处理维护单个状态(运行、暂停、取消),而不依赖于批处理,也就是说,该状态适用于在特定时刻消费的所有MDB:为什么不将EJB实现为一个
@Singleton
?通过这种方式,您可以在EJB中的实例变量中拥有该状态,并且您的MDB可以从中读取该状态。

我们重新设计了类并合并了它们,以便MDB的onMessage方法进行处理。各个批的状态存储在MDB上的静态映射中。

您可以使用javax.jms.QueueBrowser检查队列中消息的状态,您可以使用选择器和属性消息来定位具体的批处理过程。

为什么EJB需要有状态?因为我们需要跟踪批处理状态,这些状态可以独立于其他批处理进行更改(运行、暂停、取消)。此外,批处理程序正在处理单个批处理,所以它的一部分状态是跟踪“its”批处理。该状态不适用于MDB,它适用于给定的EJB。MDB接收到一条消息,表示已接收到一个新批,需要创建/启动一个处理EJB。处理EJB通过它作为注册侦听器的另一个MDB接收状态更改消息。