JMS队列和消息驱动的bean在websphere 8.5中奇怪地工作

时间:2015-07-09 08:07:38

标签: queue jms websphere message-driven-bean

我的项目是基于websphere 8.5构建的,我们决定在项目中使用JMS quque作为消息。

所以,我创建了一个名为MyBus的总线,也创建了一个目标myBusDistination。

然后我创建了一个名为myConF的连接工厂

然后我创建了两个JMS队列,一个是带有JNDI jndi / myQueue1的myQueue1。另一个是带有JNDI jndi / mQueue2的myQueue2。

然后我创建了两个激活规范,一个是带有JNDI jndi / myAS1的myAS1,另一个是带有JNDI jndi / myAS2的myAS2。

然后我创建了两个消息驱动的bean,它们在EJB3.0中,名为MyMDB1和MyMDB2。   类代码就像这样,

@MessageDriven(mappedName = "jndi/myQueue1", activationConfig = {     @ActivationConfigProperty(propertyName = "destinationType", propertyValue     = "javax.jms.Queue") })
public class MyMDB1 implements MessageListener {
    @Override
    public void onMessage(Message message) {
    }
}

ejb_jar.xml就像这样,

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http:/java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee      http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
version="3.0" metadata-complete="false">
<display-name>My MDB</display-name>
<enterprise-beans>

    <message-driven>
        <display-name>MyMDB1</display-name>
        <ejb-name>MyMDB1</ejb-name>
        <ejb-class>com.test.mdb.MyMDB1</ejb-class>
        <message-destination-ref>
            <message-destination-ref-name>jndi/myQueue1</message-destination-ref-name>
            <message-destination-type>javax.jms.Queue</message-destination-type>
            <message-destination-usage>Consumes</message-destination-usage>
            <message-destination-link>jndi/myQueue1</message-destination-link>
        </message-destination-ref>
    </message-driven>

    <message-driven>
        <display-name>MyMDB2</display-name>
        <ejb-name>MyMDB2</ejb-name>
        <ejb-class>com.test.mdb.MyMDB2</ejb-class>
        <message-destination-ref>
            <message-destination-ref-name>jndi/myQueue2</message-destination-ref-name>
            <message-destination-type>javax.jms.Queue</message-destination-type>
            <message-destination-usage>Consumes</message-destination-usage>
            <message-destination-link>jndi/myQueue2</message-destination-link>
        </message-destination-ref>
    </message-driven>
</enterprise-beans>

ibm-ejb-jar-bnd.xml就像这样,

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar-bnd xmlns="http://websphere.ibm.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-ejb-jar-bnd_1_0.xsd"
version="1.0">

<message-driven name="MyMDB1">
    <jca-adapter activation-spec-binding-name="jndi/myAS1" destination-binding-name="jndi/myQueue1"/>
    <message-destination-ref name="jndi/myQueue1" binding-name="jndi/myQueue1" />
</message-driven>

<message-driven name="MyMDB2">
    <jca-adapter activation-spec-binding-name="jndi/myAS2" destination-binding-name="jndi/myQueue2"/>
    <message-destination-ref name="jndi/myQueue2" binding-name="jndi/myQueue2" />
</message-driven>

最后,这是我测试的代码,

Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY,
      "com.ibm.websphere.naming.WsnInitialContextFactory");
props.put(Context.PROVIDER_URL, "corbaloc:iiop:localhost:2809");               InitialContext ctx = new InitialContext(props);
ConnectionFactory factory = (ConnectionFactory) ctx.lookup("jndi/myConF"); 
        Destination destination = (Destination) ctx.lookup("jndi/myQueue1");  
        Connection conn = factory.createConnection(); 
        Session session = conn.createSession(false, QueueSession.AUTO_ACKNOWLEDGE); 
        MessageProducer producer = session.createProducer(destination);

                    ObjectMessage objMsg = session.createObjectMessage();
        objMsg.setObject("MDB Test");

        producer.send(objMsg); 
        session.close();
        conn.close();

奇怪的是,

可以发送消息,MDB MyMDB1可以处理消息(如果我在MyMDB1.onMesssage()中记录了某些内容)。但是,如果我再次发送消息。该消息将由MyMDB2处理。

任何人对这个“奇怪的事情”都有一些想法吗?

2 个答案:

答案 0 :(得分:1)

据我了解,您创建了两个连接到同一目标的JMS队列(jndi / myQueue1,jndi / myQueue2)。这就是为什么两个MDB都在等待来自该目的地的消息。结果,哪一个从队列中获取消息将更快运行。这是一种不好的做法。 在您的测试中,您只使用jndi / myQueue1和jndi / myAS1将消息放入目标,但这并不意味着。 您可以尝试停止其中一个MDB,然后您可以看到它只能用于另一个MDB,并且消息不会保留在队列中。

更新。如果需要两个不同的队列来接收不同的消息。你应该做这样的事情:

  1. 创建第二个目的地,例如myDestination2
  2. 更改myQueue2(资源 - &gt; JMS-&gt;队列)的配置。在“连接”栏中,将“队列名称”从myBusDistination更改为myDestination2
  3. 要为第二个MDB使用消息:

    ConnectionFactory factory = (ConnectionFactory) ctx.lookup("jndi/myConF"); Destination destination = (Destination) ctx.lookup("jndi/myQueue2");

    将消息放到第一个没有任何变化:

    ConnectionFactory factory = (ConnectionFactory) ctx.lookup("jndi/myConF"); Destination destination = (Destination) ctx.lookup("jndi/myQueue1");

答案 1 :(得分:0)

您必须为每个队列创建一个总线目标,因此,myBusDistination1 queue1myBusDistination2 queue2。然后,当您发送到queue1时,MDB1将收到该消息,如果您将发送到queue2,MDB2将收到该消息。如果您希望所有MDB都收到相同的消息,则必须创建topic而不是队列,以及指向该主题的激活规范。

您没有在问题中指明您实际想要实现的目标。