Reputation: 8042
Since a message driven bean is a type of EJB, I would expect that I would be able to inject one into another, but I am having issues. I have to MDBs and need to inject one into the other something like this:
@MessageDriven(mappedName = "jms/QueueOne")
public class MessageBeanOne
{
@EJB
private EntityService service;
@EJB
private MessageBeanTwo mdbTwo;
public void onMessage(Message message)
{
log.info("Received message from jms/QueueOne: " + message);
String entityId= null;
try
{
if (message instanceof TextMessage)
{
entityId = ((TextMessage) message).getText();
}
else
{
// error handling
}
}
catch (Exception ex)
{
// error handling
}
Entity myEntity = service.getEntity(entityId);
mdbTwo.process(myEntity);
}
}
@MessageDriven(mappedName = "jms/TopicOne")
public class MessageBeanTwo
{
@EJB
private EntityService service;
private boolean goodToProcess = true;
public void process(Entity entity)
{
while(goodToProcess)
{
// process entity using injected service object
}
}
public void onMessage(Message message)
{
log.info("Received message from jms/TopicOne: " + message);
String status = null;
try
{
if (message instanceof TextMessage)
{
status = ((TextMessage) message).getText();
}
else
{
// error handling
}
}
catch (Exception ex)
{
// error handling
}
if (status.equals("cancel")
{
goodToProcess = false;
}
}
}
They are deployed as an ear into Glassfish 3.1.1. and I get this error message in my server.log:
[#|2011-11-23T10:55:35.546-0700|SEVERE|glassfish3.1.1|javax.enterprise.system.container.ejb.mdb.com.sun.ejb.containers|_ThreadID=19;_ThreadName=Thread-2;|MDB00050: Message-driven bean [MyApp-ear-1.0:MessageBeanOne]: Exception in creating message-driven ejb : [com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Remote ejb-ref name=my.package.MessageBeanOne/messageBeanTwo,Remote 3.x interface =my.package.MessageBeanTwo,ejb-link=null,lookup=,mappedName=,jndi-name=my.package.MessageBeanTwo,refType=Session into class my.package.MessageBeanOne: Lookup failed for 'java:comp/env/my.package.MessageBeanOne/messageBeanTwo' 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}]|#]
[#|2011-11-23T10:55:35.547-0700|SEVERE|glassfish3.1.1|javax.enterprise.system.container.ejb.mdb.com.sun.ejb.containers|_ThreadID=19;_ThreadName=Thread-2;|com.sun.enterprise.container.common.spi.util.InjectionException com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Remote ejb-ref name=my.package.MessageBeanOne/messageBeanTwo,Remote 3.x interface =my.package.MessageBeanTwo,ejb-link=null,lookup=,mappedName=,jndi-name=my.package.MessageBeanTwo,refType=Session into class my.package.MessageBeanOne: Lookup failed for 'java:comp/env/my.package.MessageBeanOne/messageBeanTwo' 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}
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:703)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.inject(InjectionManagerImpl.java:470)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:171)
at com.sun.ejb.containers.BaseContainer.injectEjbInstance(BaseContainer.java:1691)
at com.sun.ejb.containers.MessageBeanContainer.createMessageDrivenEJB(MessageBeanContainer.java:706)
at com.sun.ejb.containers.MessageBeanContainer.access$100(MessageBeanContainer.java:101)
at com.sun.ejb.containers.MessageBeanContainer$MessageBeanContextFactory.create(MessageBeanContainer.java:483)
at com.sun.ejb.containers.util.pool.NonBlockingPool.getObject(NonBlockingPool.java:247)
at com.sun.ejb.containers.MessageBeanContainer._getContext(MessageBeanContainer.java:547)
at com.sun.ejb.containers.BaseContainer.getContext(BaseContainer.java:2528)
at com.sun.ejb.containers.MessageBeanContainer.beforeMessageDelivery(MessageBeanContainer.java:989)
at com.sun.ejb.containers.MessageBeanListenerImpl.beforeMessageDelivery(MessageBeanListenerImpl.java:77)
at com.sun.enterprise.connectors.inbound.MessageEndpointInvocationHandler.invoke(MessageEndpointInvocationHandler.java:139)
at $Proxy337.beforeDelivery(Unknown Source)
at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java:247)
at com.sun.enterprise.connectors.work.OneWork.doWork(OneWork.java:114)
at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.performWork(ThreadPoolImpl.java:497)
at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:540)
Caused by: javax.naming.NamingException: Lookup failed for 'java:comp/env/my.package.MessageBeanOne/messageBeanTwo' 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} [Root exception is javax.naming.NamingException: Exception resolving Ejb for 'Remote ejb-ref name=my.package.MessageBeanOne/messageBeanTwo,Remote 3.x interface =my.package.MessageBeanTwo,ejb-link=null,lookup=,mappedName=,jndi-name=my.package.MessageBeanTwo,refType=Session' . Actual (possibly internal) Remote JNDI name used for lookup is 'my.package.MessageBeanTwo#my.package.MessageBeanTwo' [Root exception is javax.naming.NamingException: Lookup failed for 'my.package.MessageBeanTwo#my.package.MessageBeanTwo' 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} [Root exception is javax.naming.NameNotFoundException: my.package.MessageBeanTwo#my.package.MessageBeanTwo not found]]]
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:518)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:455)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:599)
... 17 more
Caused by: javax.naming.NamingException: Exception resolving Ejb for 'Remote ejb-ref name=my.package.MessageBeanOne/messageBeanTwo,Remote 3.x interface =my.package.MessageBeanTwo,ejb-link=null,lookup=,mappedName=,jndi-name=my.package.MessageBeanTwo,refType=Session' . Actual (possibly internal) Remote JNDI name used for lookup is 'my.package.MessageBeanTwo#my.package.MessageBeanTwo' [Root exception is javax.naming.NamingException: Lookup failed for 'my.package.MessageBeanTwo#my.package.MessageBeanTwo' 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} [Root exception is javax.naming.NameNotFoundException: my.package.MessageBeanTwo#my.package.MessageBeanTwo not found]]
at com.sun.ejb.EjbNamingReferenceManagerImpl.resolveEjbReference(EjbNamingReferenceManagerImpl.java:178)
at com.sun.enterprise.container.common.impl.ComponentEnvManagerImpl$EjbReferenceProxy.create(ComponentEnvManagerImpl.java:1106)
at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:776)
at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:744)
at com.sun.enterprise.naming.impl.JavaURLContext.lookup(JavaURLContext.java:172)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:498)
... 21 more
Caused by: javax.naming.NamingException: Lookup failed for 'my.package.MessageBeanTwo#my.package.MessageBeanTwo' 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} [Root exception is javax.naming.NameNotFoundException: my.package.MessageBeanTwo#my.package.MessageBeanTwo not found]
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:518)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:455)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at com.sun.ejb.EjbNamingReferenceManagerImpl.resolveEjbReference(EjbNamingReferenceManagerImpl.java:173)
... 26 more
Caused by: javax.naming.NameNotFoundException: my.package.MessageBeanTwo#my.package.MessageBeanTwo not found
at com.sun.enterprise.naming.impl.TransientContext.doLookup(TransientContext.java:248)
at com.sun.enterprise.naming.impl.TransientContext.lookup(TransientContext.java:215)
at com.sun.enterprise.naming.impl.SerialContextProviderImpl.lookup(SerialContextProviderImpl.java:77)
at com.sun.enterprise.naming.impl.LocalSerialContextProviderImpl.lookup(LocalSerialContextProviderImpl.java:119)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:505)
... 30 more
|#]
[#|2011-11-23T10:55:35.548-0700|WARNING|glassfish3.1.1|javax.resourceadapter.mqjmsra.inbound.message|_ThreadID=19;_ThreadName=Thread-2;|MQJMSRA_MR2001: run:Caught Exception from onMessage():Redelivering:
javax.ejb.EJBException: ESwimMessageBeanTwo-ear-1.0:MessageBeanOne: message-driven bean invocation closed by container
at com.sun.ejb.containers.MessageBeanContainer.deliverMessage(MessageBeanContainer.java:1163)
at com.sun.ejb.containers.MessageBeanListenerImpl.deliverMessage(MessageBeanListenerImpl.java:81)
at com.sun.enterprise.connectors.inbound.MessageEndpointInvocationHandler.invoke(MessageEndpointInvocationHandler.java:171)
at $Proxy337.onMessage(Unknown Source)
at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java:260)
at com.sun.enterprise.connectors.work.OneWork.doWork(OneWork.java:114)
at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.performWork(ThreadPoolImpl.java:497)
at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:540)
|#]
On trying to search if this is actually possible, I've come across lots of references to injecting MDBs into Session beans, but never injecting an MDB into another MDB. Maybe this isn't doable?
Upvotes: 1
Views: 2470
Reputation: 4941
Probably not directly related to the question, but I would extract the process()
method to its own class that both MDBs can modify. This way MDBs have the sole responsibility of processing incoming messages and the third new class performs the "entity processing".
This class could then be another EJB that you inject in both MDBs.
In my opinion, MDBs should generally be dedicated only to process receive messages.
EDIT
By looking at your code a second time, I would encourage you to think about it twice. Your MDBs have state and that could lead to unexpected results taking into account that the container creates a pool of instances. You could be in the situation where an instance of MessageBeanTwo
is pooled with goodToProcess = false
. If that instance is taken from the pool and injected in MessageBeanOne
and process()
method is called, you might get a wrong result.
This is all assuming you can inject an MDB in another one, which I have never done or heard of.
Upvotes: 1