EJB3 - 将MDB注入另一个MDB?

时间:2011-11-23 18:03:23

标签: java java-ee ejb-3.1

由于消息驱动bean是一种EJB,我希望我能够将一个注入另一个,但我遇到了问题。我需要MDB并且需要将一个注入到另一个像这样的东西:

@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;
        }
    }
}

它们被部署为Glassfish 3.1.1。我在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)
|#]

在尝试搜索这是否真的可行时,我遇到了很多关于将MDB注入会话bean的引用,但从未将MDB注入另一个MDB。也许这不可行?

1 个答案:

答案 0 :(得分:1)

可能与问题没有直接关系,但我会将process()方法提取到两个MDB都可以修改的自己的类中。这样,MDB具有处理传入消息的sole responsibility,并且第三新类执行“实体处理”。 这个类可能是您在两个MDB中注入的另一个EJB。

在我看来,MDB通常应该专门用于处理接收消息。

修改

通过第二次查看您的代码,我鼓励您考虑两次。您的MDB具有状态,并且考虑到容器创建实例池,可能会导致意外结果。您可能处于MessageBeanTwo的实例与goodToProcess = false合并的情况。如果该实例是从池中取出并注入MessageBeanOne并调用process()方法,则可能会得到错误的结果。

这就是假设你可以在另一个中注入一个MDB,这是我从未做过或听说过的。