Question

I have an EAR which I deploy on Websphere Application Server, that uses a function to send a message to a MQ by using JMS, and receives a message inmediately from another queue.:

    ConnectionFactory cf = null;
    InitialContext context = null;
    String[] arrDatos_SR = null;

    Connection conn = null;
    Session session = null;
    Queue queue = null;
    Queue queue2 = null;

    Destination dest = null;
    Destination dest2 = null;
    MessageConsumer consumer = null;
    MessageProducer producer = null;
    TextMessage message = null;

    String comando = "";
    int tamanio = 0;
    String tamanio2 = "";
    String cadena = "";

    try {
        context = new InitialContext();
        cf = (ConnectionFactory) context.lookup(arrDatos[1].trim());
        conn = cf.createConnection();
        session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);      
        queue = (Queue) context.lookup(arrDatos[2].trim());
        queue2 = (Queue) context.lookup(arrDatos[3].trim());
        dest = (Destination) queue;
        dest2 = (Destination) queue2;

        producer = session.createProducer(dest);


        // Create a text message using the queue session.
        TextMessage textMessage = session.createTextMessage();

        textMessage.setText(arrDatos[4]);

        textMessage.setJMSReplyTo(dest2);
        textMessage.setJMSMessageID(arrDatos[6]);
        textMessage.setJMSCorrelationID(arrDatos[7]);
        producer.send(textMessage);


    } catch (NamingException e) {
        // TODO Auto-generated catch block
        logger.error("MQSendReceive() - Exception e2 = "
                + e, e);
    } catch (JMSException e) {
        // TODO Auto-generated catch block
        logger.error("MQSendReceive() - Exception e2 = "
                + e, e);
    } 

        arrDatos[5] = arrDatos[5].trim();

        try{
            conn.start();       
            consumer = session.createConsumer(dest2);
            Message receivedMessage = consumer.receive(Long.parseLong(arrDatos[5]) * 1000);



            if(receivedMessage != null)
            {
                message = (TextMessage)receivedMessage;
                comando = message.getText();
                comando = comando.trim();
                tamanio = comando.length();
                tamanio2 = StringUtils.leftPad(Integer.toString(tamanio), 9, '0');

                comando = StringUtils.rightPad(comando, Constantes.TAMANIO_RESPUESTA_DES_C1, ' ');
                cadena = arrDatos[0] + comando + tamanio2; 
            }
            else
            {
                comando = new String();
                comando = "";
                tamanio = comando.length();
                tamanio2 = StringUtils.leftPad(Integer.toString(tamanio), 9, '0');

                cadena = arrDatos[0] + comando + tamanio2;
            }

            arrDatos_SR = new String[2];
            arrDatos_SR[0] = cadena;
            arrDatos_SR[1] = arrDatos[0];

        }
        catch(Exception e)
        {
            logger.error("MQSendReceive() - Excepcion:" + e);
        }
        finally
        {
            try {
                consumer.close();
                session.close();
                conn.close();
                context.close();
            } catch (JMSException e) {
                // TODO Auto-generated catch block
                logger.error("MQSendReceive() - Error desconectando de MQ - Excepcion:" + e);
            } catch (NamingException e) {
                // TODO Auto-generated catch block
                logger.error("MQSendReceive() - Error desconectando de MQ - Excepcion:" + e);
            }

        }

        return arrDatos_SR;

The message is sent to a a MQ Queue #1, which is then transferred to another MQ Queue #2 which is a tranmission queue to another MQ Queue #3. I tested with the Websphere MQ Administration GUI putting messages to this queue, and they transfer smoothly. But when I use my code for some reason the send is not made inmediately. Instead, it is done after the receive ends (when the timeout expires or when it actually receives a message)

Can someone tell me why is this happening?

UPDATE: (March 31st, 2014) I forgot to mention that I'm using an EJB container with @LocalBean, @Singleton and @TransactionManagement(TransactionManagementType.CONTAINER) annotations. By reading this post from SO (http://goo.gl/JBSW7r), I realized that I have 3 classes that make the whole connection, and one main that makes use of all of them as objects from which I use the public methods. I decided to turn these classes into EJB as well with the same annotation. I also tried to change the @TransactionAttribute type of each method to REQUIRED, NOT SUPPORTED and MANDATORY one at a time, just to test if some of them worked. I also changed the session line to this:

session = conn.createSession(true, Session.SESSION_TRANSACTED); 

Result appears to be the same. The message is still stuck in the transmission queue while the message is being received during timeout interval of the MessageConsumer.

Can someone give me some thoughs on these?

Was it helpful?

Solution 2

After so much trying, I ended removing the EJB. I made a web project with the whole logic. I decided to control the repetition of the code by using a Thread with a while loop. I use a boolean variable to control the init and stop of the while loop on EAR start and shutdown.

Well, back to the web application, it works as it should. I don't know yet why it works this way and not the other, but I think it's okay for now.

OTHER TIPS

Based on your description of the problem I believe the code you have provided is executing in the context of an EJB with a container managed transaction in effect. In a Java EE application server the JMS operations will be coordinated by the transaction. That means the send will not in fact complete until the transaction is committed by the container at the end of the EJB method.

Although you have set false when creating the Session in a Java EE application server this is ignored and the session will be enrolled in any global transaction in effect.

The solution to this problem is to ensure that the JMS send executes with no transaction. To do this the EJB method should be configured with a transaction type of NOT_SUPPORTED.

Though it looks like OP got a workaround solution by moving his logic to a web module instead, figured I would add a potential option in case others are requiring the use of the EJB.

Alasdair's answer is definitely the preferred way over moving EJB type logic back into a web app. We just encountered this issue when creating a new EJB 3.0 project and defining a bean that sends messages and waits for replies from Websphere MQ. We had found that we had indeed defined our session bean with a transaction type of Container in the beginning, which fails for the exact reason mentioned earlier.

Switching the transaction-type to Bean, however, resolved this for us. It still allowed the session bean to retain some transactional properties but also let JMS send a committed message.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top