Hot questions for Using Enterprise JavaBeans in jms

Question:

This is my sender class:

private void sendJMSMessage(Object data) throws JMSException {
        Connection con = null;
        Session s = null;
        try {
            con = context.createConnection();
            s = con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
            MessageProducer producer = s.createProducer(glassFishQueue);
            ObjectMessage msg = s.createObjectMessage();
            ArrayList list = new ArrayList();
            list.add("name");
            msg.setObject(p);
            producer.send(msg);
        }

And my Message-driven Bean:

public void onMessage(Message message) {
    try {
        ObjectMessage om = (ObjectMessage) message;
        ArrayList al = (ArrayList) om.getObject();
        System.out.println("Msg: " + al.get(0));

    } catch (JMSException jex) {
        System.out.println("Exception: " + jex);
    }

I got the message sent from sender class but I need a message back from EJB to the sender. Im doing a web client with a table but I need to fill it getting the info from a database remotely, I really doesnt know what i should to use to do this, so if im doing right let me know or tell me any suggestion

Thank u


Answer:

JMS is asynchronous, so it won't work in request-response style out of the box.

If you want to send a reply, one way is to use a separate queue. Your MDB can write the response to this second queue and your client can listen to this queue by creating a QueueReceiver.

Another way is to use QueueRequestor. From javadocs:

It creates a TemporaryQueue for the responses and provides a request method that sends the request message and waits for its reply.

Look here and here for QueueRequestor examples.

Question:

I'm having troubles with migration from old JBoss to Wildfly 14 (or some other latest version). Currently I'm stuck with JMS configuration. Here is the configuration:

  • In <subsystem xmlns="urn:jboss:domain:messaging-activemq:4.0">I have added two queue definitions with the following code <jms-queue name="MyQueue" entries="java:/jms/queue/MyQueue"/> <jms-queue name="OtherQueue" entries="java:/jms/queue/OtherQueue"/>
  • In mentioned above subsystem definition I've added the following connection factory definition <connection-factory name="InVmConnectionFactory" entries="java:/ConnectionFactory" connectors="in-vm" />
  • In my application initialization code I have code which instantiates these jms queues.

In my class I have the following fields

private static final String JMS_CONNECTION_FACTORY_JNDI_NAME = "java:/ConnectionFactory";
@Resource(mappedName=JMS_CONNECTION_FACTORY_JNDI_NAME)
ConnectionFactory factory;

and in this class I have the following method:

public void openJmsSession() {
    try {
        connection = factory.createConnection();
        Context jndiContext = getInitialContext();
        queue =(Queue) jndiContext.lookup(JMS_MAIL_QUEUE_NAME);
        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    } catch (NamingException e) {
        logger.error("Naming exception during opening JMS session", e);
    } catch (JMSException e) {
        logger.error("JMS exception during opening JMS session", e);
    }
}

Line connection = factory.createConnection(); throws NPE because factory is null.


Answer:

Having the following config:

<connection-factory name="InVmConnectionFactory" entries="java:/ConnectionFactory" connectors="in-vm"/>

I'm using this code:

@Resource(mappedName = "java:/ConnectionFactory")
private static ConnectionFactory connectionFactory;

Hope this helps.

Question:

I am currenlty involved in the development of a JMS Request Response service using EJB. The service receives JMS Messages as request through MDB and responds back with a JMS Message ( using the ReplyToQ configured in the request ).

The requirement is that even in case an error happens in the service, a response should be sent back. If the response is being sent within the onMessage() method, then it is being sent within the same transaction where the request is being processed or received. In this case, when an error happens the transaction gets rolled back and hence the response is not being sent.

So, i have moved the part of the code which sends the response, to a method, in a different stateless Session bean with TransactionAttribute.REQUIRES_NEW. The code works now..

But I am a bit confused as to whether to have the response send method in a new transaction using the TransactionAttribute.REQUIRES_NEW or have it as TransactionAttribute.NOT_SUPPORTED. Can you please let me know which is better..using TransactionAttribute.REQUIRES_NEW or using TransactionAttribute.NOT_SUPPORTED over the method.

I have provided an excerpt from the code below

   @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
       public void sendResponse(Message inMessage, Object responseObj)
        throws JMSException {
          Connection jmsConnection = null;
    Session jmsSession = null;
    try {

        jmsConnection = getConnection();
        Destination jmsDestination = inMessage.getJMSReplyTo();
        jmsSession = jmsConnection.createSession(false,
                Session.AUTO_ACKNOWLEDGE);
        String marshalTxt = "Sample Response";
        Message responseMessage = jmsSession.createTextMessage(marshalTxt);
        responseMessage.setJMSCorrelationID(getCorrelId());
        jmsSession.createProducer(jmsDestination).send(responseMessage);
    } catch (JMSException | IllegalStateException exception) {
        LOGGER.error("void sendResponse ->Unable to send the response",
                exception);
        throw exception;
    }finally{
        if(jmsConnection != null){
        jmsConnection.close();
        }
    }
}

Thanks in Advance.


Answer:

The lightest weight is going to be NOT_SUPPORTED so there no transactional overhead, but assumes that response sending is always going to succeed and there's no need to rollback that transaction. If there are error conditions that might require yanking back the response and, I guess, sending a different response, then transactions might be necessary. However, I'd hope that all the processing is done before you send the response, and then commit/rollback the overriding transaction afterwards.