EJB3 - 将MDB注入另一个MDB? [英] EJB3 - Inject a MDB into another MDB?

查看:225
本文介绍了EJB3 - 将MDB注入另一个MDB?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

它们被部署为Glassfish 3.1.1。我得到了我的server.log中出现此错误消息:

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)
|#]

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

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?

推荐答案

可能与问题没有直接关系,但我会提取 process()自己的类的方法,两个MDB都可以修改。这样,MDB就可以处理传入消息的单一责任,第三个新类执行实体处理。
这个类可能是你在两个MDB中注入的另一个EJB。

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.

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

In my opinion, MDBs should generally be dedicated only to process receive messages.

编辑

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

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.

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

This is all assuming you can inject an MDB in another one, which I have never done or heard of.

这篇关于EJB3 - 将MDB注入另一个MDB?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆