The SOA JMS Adapter provides a lot of functionality out of the box to meet the needs of the developer.  One of the tools it provides is the ability to set a ‘Message Selector’ which adds a selection criteria to the messages which the adapter consumes from the configured JMS Queue.  One of, if not the only, caveat of utilizing the message selector is that the criteria must be established at design time.  Currently there is no solution to configure the message selector at run time through the adapter framework.
Let’s take a look at how we can dynamically set this message selector at run time by moving away from the adapter and creating a java webservice which will accept the selector as its input, create a connection, and create a consumer to a configured JMS Queue.
First, create a new project in Jdeveloper and add Java for project features. Â The rest of the default settings are fine.
We will also need to import the javax.jms.jar to the project which can be found under the modules directory of your Jdeveloper home. Â If you are unfamiliar with adding jars to your Jdeveloper project a step by step walkthrough is described below.
- Right click on your project in the Applications pane and select Project Properties.
- Select the Libraries and Classpath option.
- Click the Add JAR/Directory button.
- Navigate to the desired .jar to include, double click it and then click ok.
Next, create a new java class, which I called ‘QueueConsume’. Â This class will have 4 methods that will house the majority of our logic for this project, as well as a number of member variables. Â The source code for this class can be seen below.
package dynamicjmsconsume; import java.util.Hashtable; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.JMSException; import javax.jms.MessageConsumer; import javax.jms.Queue; import javax.jms.Session; import javax.jms.TextMessage; import javax.naming.Context; import javax.naming.InitialContext; public class QueueConsume { public QueueConsume() { super(); } private final static String JNDI_FACTORY="weblogic.jndi.WLInitialConextFactory"; private final static String JMS_FACTORY="jms/TestCF"; private final static String QUEUE="jms/TestQueue"; private static Connection mConnection; private static ConnectionFactory mConnectionFactory; private static Queue mQueue; private static MessageConsumer mConsumer; private static Session mSession; private static String mMessageSelector; public static void initialize() throws Exception { Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY); env.put(Context.PROVIDER_URL, "t3://youradminurl:port"); Context ctx= new InitialContext(env); mConnectionFactory=(javax.jms.ConnectionFactory)ctx.lookup(JMS_FACTORY); mConnection=mConnectionFactory.createConnection(); mSession=mConnection.createSession(false,Session.AUTO_ACKNOWLEDGE); mQueue=(javax.jms.Queue)ctx.lookup(QUEUE); mConsumer=mSession.createConsumer(mQueue,mMessageSelector); mConnection.start(); } public static void setMessageSelector(String pMessageSelector){ mMessageSelector=pMessageSelector; } public static void close() throws JMSException { mSession.close(); mConnection.close(); mConsumer.close(); } public static String consume() throws Exception{ try{ initialize(); TextMessage msg=(TextMessage)mConsumer.receiveNoWait(); if(msg!=null){ return msg.getText().toString(); } else return "message not found"; } catch(Exception e){ throw e; } finally{ close(); } } }
Next, we will create a wrapper class which we will expose as a webservice. Â Create a new class and above the class declaration put the @WebService annotation to declare this class as a webservice. Â When you add this line of text you will need to right click and configure the web.xml for the service. Â Select the JAX-WS Annotations.
In this class we will create our ‘main’ method essentially, which will be responsible for setting the message selector using the value passed in and then returning the messages consumed from the queue. Â I have called this method ‘Consume’ in my example. Â Similar to the @WebService annotation we added above we need to add @WebMethod annotation above the ‘Consume’ method declaration to expose this method to the webservice.
Source code for this wrapper class can be seen below.
package dynamicjmsconsume; import javax.jws.WebMethod; import javax.jws.WebService; @WebService public class QueueConsumeWrapper { public QueueConsumeWrapper() { super(); } @WebMethod public String Consume(String pMessageSelector) throws Exception { QueueConsume.setMessageSelector(pMessageSelector); return QueueConsume.consume(); } }
Note that the source code provided above is simply to show how to minimally accomplish the focus of this blog. Â It doesn’t take into account proper error handling or design.
Thanks Joel for your simple explanation. It really help me out of the wood. more post pls.