1
votes

My project are built based on websphere 8.5 and we decided to use JMS quque for message within my project.

So, I createad a bus named MyBus, also created a destination myBusDistination.

Then I created a Connection Factory named myConF

Then I created two JMS queues, one is myQueue1 with JNDI jndi/myQueue1. The other one is myQueue2 with JNDI jndi/mQueue2.

Then I created two Activation specifications, one is myAS1 with JNDI jndi/myAS1, the other is myAS2 with JNDI jndi/myAS2.

Then I created two message driven beans and they are in EJB3.0, named MyMDB1 and MyMDB2. The class code is like this,

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

The ejb_jar.xml is like this,

<?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>

And the ibm-ejb-jar-bnd.xml is like this,

<?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>

At last, here is the code for my test,

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();

The strange thing is,

Message can be sent out, and the message can be processed by MDB MyMDB1(if I log something within MyMDB1.onMesssage()). But if I send the message again. the message will be processed by MyMDB2.

Anyone have some ideas on this 'strange thing'?

2

2 Answers

1
votes

As i understand, you created two JMS queues (jndi/myQueue1, jndi/myQueue2) which was connected to the same destination. That is why both MDBs waiting for a message from that destination. As a result which one takes the message from queue faster will run. This is a bad practice. And in your test you only put message into destination using jndi/myQueue1 and jndi/myAS1, but it doesn't mean. You can try to stop one of your MDBs and after that you can see that will work only another one, and messages will not stay in queue.

Update. If need two different queues to receive different messages. You should make something like this:

  1. Create second destination named, for example, myDestination2.
  2. Change configuration of your myQueue2(Resourses->JMS->Queues). In Connection block change 'Queue name' from myBusDistination to the myDestination2.
  3. To put message for the second MDB use:

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

    to put messages to the first one nothing changes:

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

0
votes

You have to create one bus destination per queue, so in your case myBusDistination1 for queue1 and myBusDistination2 for queue2. Then when you will send to queue1 MDB1 will receive the message and if you will send to queue2, MDB2 will receive the message. If you want all MDBs receive same message you will have to create topic not queue, and activation specs pointing to the topic.

You didn't specify in the question what actually you are trying to achieve.