Search code examples
javajmsjava-ee-6ibm-mq

How to make JMS message send to MQ to commit fully?


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?


Solution

  • 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.