0
votes

I am using Websphere Application Server 7.x version.

I want to read the messages buffered in MQ with the help of JMS API as given below. I referred from link1, link2

    @Resource(lookup = "jms/ConnectionFactory")
    private static ConnectionFactory connectionFactory;

    @Resource(lookup = "jms/Queue")
    private static Queue queue;

    public void readMessagesFromQueue() {
        try {

          Connection connection = connectionFactory.createConnection();
          Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
          MessageConsumer consumer = session.createConsumer(queue);

          MyListener myListener = new MyListener();
          consumer.setMessageListener(myListener); // Error here
          connection.start();
         } catch (JMSException e) {
           throw new RuntimeException(e);
         }
    }

MyListener class:

public class MyListener implements MessageListener {
    @Override
    public void onMessage(Message message) {
        try {
           String text=((TextMessage)message).getText();
           System.out.println(text);
         }
         catch (JMSException e) {
            throw new RuntimeException(e);
         }
    }
}

During the run time I am getting Exception:

javax.jms.IllegalStateException: Method setMessageListener not permitted

I could see in the link that the method setMessageListener for asynchronous messaging, it is forbidden to use this method in a WebSphere Application Server.

Question 1:

Can't this setMessageListener method be used in WAS?
If not, what is the work around to achieve the above required functionality?

Question 2:

I can explain the need in other words:
The JMS listner should not recive the messages as soon as the message arrived in the the queue. But I want the listener to listen only during the time I require.
I tried the approach which I mentioned above. But I got blocked because of the exception.

Any other way to achieve this?

3
If you want to asynchronously receive messages then create MDB, otherwise call consumer.receive() method to read messages.Gas
@Gas, I can use MDB to asynchronously receive messages. But I also want the MDB to inactive during sometime and make it active during sometime.Alagammal P

3 Answers

0
votes

This is not a WebSphere problem.
In short, the JMS spec does not allow you to use this feature in a JEE Container: Check the API here :

void setMessageListener(MessageListener listener)
             throws JMSException

   Sets the MessageConsumer's MessageListener.
   {...}
   This method must not be used in a Java EE web or EJB application. Doing so may cause a JMSException to be thrown though this is not guaranteed.
0
votes

If you want to stop receiving messages you can deactivate activation specification that manages the MDB. You can either write wsadmin script and put it for example in the crontab, pause it via admin console, or use JMX and MBean to pause.

Check these links:

UPDATE

Here is code sample. This is pseudo code - no error handling, no checking if it is correct ActiveSpec. This code must be run as user with role administrator or operator (so application security needs to be enabled), I did it by specifying @RunAs role for the servlet which invoked it, but you may need to do it differently.

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    PrintWriter out = response.getWriter();
    String action = request.getParameter("action");

    try {
        AdminService adminService = AdminServiceFactory.getAdminService();
        ObjectName asName = new ObjectName("WebSphere:*,type=J2CMessageEndpoint");

        Set names = adminService.queryNames(asName, null);
        System.out.println("Found:" + names.size());

        if(names.size() > 0) {
            ObjectName mbean = (ObjectName) names.iterator().next();
            System.out.println("mbean: " + mbean);

            if(action != null && action.equals("pause")) {
                adminService.invoke((ObjectName) mbean, "pause", null, null);
                System.out.println("invoked");
            } 
            else if(action != null && action.equals("resume")) {
                adminService.invoke((ObjectName) mbean, "resume", null, null);
                System.out.println("invoked");
            }
        }

    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

You should see in the log that AS is deactivated and activated:

[4/20/17 4:24:41:029 PDT] 00000094 SystemOut     O mbean: WebSphere:name=JMXTestEAR#JMXTestWeb.war#TestMDB_J2CMessageEndpoint,process=server1,ActivationSpec=jms/MyAS,platform=dynamicproxy,node=ubuntuNode01,J2EEApplication=JMXTestEAR,j2eeType=JCAMessageEndpoint,J2EEServer=server1,Server=server1,version=9.0.0.3,J2CResourceAdapter=SIB JMS Resource Adapter,type=J2CMessageEndpoint,mbeanIdentifier=cells/ubuntuNode01Cell/nodes/ubuntuNode01/servers/server1/resources.xml#J2CResourceAdapter_1492682844859#JMXTestEAR#JMXTestWeb.war#TestMDB_J2CMessageEndpoint,cell=ubuntuNode01Cell,MessageDrivenBean=JMXTestEAR#JMXTestWeb.war#TestMDB,spec=1.0
[4/20/17 4:24:41:037 PDT] 00000094 ActivationSpe I   J2CA0524I: The Message Endpoint for ActivationSpec jms/MyAS (com.ibm.ws.sib.api.jmsra.impl.JmsJcaActivationSpecImpl) and MDB Application JMXTestEAR#JMXTestWeb.war#TestMDB is deactivated.
[4/20/17 4:24:41:038 PDT] 00000094 SystemOut     O invoked
[4/20/17 4:24:52:890 PDT] 00000094 SystemOut     O Found:1
[4/20/17 4:24:52:890 PDT] 00000094 SystemOut     O mbean: WebSphere:name=JMXTestEAR#JMXTestWeb.war#TestMDB_J2CMessageEndpoint,process=server1,ActivationSpec=jms/MyAS,platform=dynamicproxy,node=ubuntuNode01,J2EEApplication=JMXTestEAR,j2eeType=JCAMessageEndpoint,J2EEServer=server1,Server=server1,version=9.0.0.3,J2CResourceAdapter=SIB JMS Resource Adapter,type=J2CMessageEndpoint,mbeanIdentifier=cells/ubuntuNode01Cell/nodes/ubuntuNode01/servers/server1/resources.xml#J2CResourceAdapter_1492682844859#JMXTestEAR#JMXTestWeb.war#TestMDB_J2CMessageEndpoint,cell=ubuntuNode01Cell,MessageDrivenBean=JMXTestEAR#JMXTestWeb.war#TestMDB,spec=1.0
[4/20/17 4:24:52:897 PDT] 00000094 SibMessage    I   [:] CWSIV0777I: A connection to messaging engine ubuntuNode01.server1-myBus for destination testQ1 on bus myBus has been successfully created.
[4/20/17 4:24:52:898 PDT] 00000094 ActivationSpe I   J2CA0523I: The Message Endpoint for ActivationSpec jms/MyAS (com.ibm.ws.sib.api.jmsra.impl.JmsJcaActivationSpecImpl) and MDB Application JMXTestEAR#JMXTestWeb.war#TestMDB is activated.
[4/20/17 4:24:52:899 PDT] 00000094 SystemOut     O invoked
-1
votes

You did not initialize the ConnectionFactory and the Queue try this

connectionFactory = new ConnectionFactory(the arguments); Queue q = new Queue(the arguments);

I think thats the error because than the consumer cant be used when its null.