To configure a Messaging Bridge you can follow the steps provided in the post Steps to Configure Messaging Bridge on Weblogic Server
In this post I would be using a stand-alone java code for producing messages as a Producer/Clint and for consuming the messages as a Consumer/Listener. By which we can make sure that if something goes wrong then we can narrow down the issue if its an issue with WLS or the code, asmany times their an issue with the Producer or a Consumers.
.
.
Steps of test the Messaging Bridge
- Create a Directory somewhere in your file system like: “D:OracleJMSQueue” to write the QueueSend.java and QueueReceive.java programs.
- In QueueSend.java copy the below command
import java.io.*; import java.util.Hashtable; import javax.jms.JMSException; import javax.jms.Queue; import javax.jms.QueueConnection; import javax.jms.QueueConnectionFactory; import javax.jms.QueueSender; import javax.jms.QueueSession; import javax.jms.Session; import javax.jms.TextMessage; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; public class QueueSend { public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory"; // ******* Give the CONNECTION FACTORY JNDI name which is QCF ******** public final static String JMS_FACTORY="QCF"; // ******* Give the UNIFORM DISTRIBUTED QUEUE JNDI name which is TestQ ******** public final static String QUEUE="TestQ"; private QueueConnectionFactory qconFactory; private QueueConnection qcon; private QueueSession qsession; private QueueSender qsender; private Queue queue; private TextMessage msg; public void init(Context ctx, String queueName) throws NamingException, JMSException { qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY); qcon = qconFactory.createQueueConnection(); qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); queue = (Queue) ctx.lookup(queueName); qsender = qsession.createSender(queue); msg = qsession.createTextMessage(); qcon.start(); } public void send(String message) throws JMSException { msg.setText(message); qsender.send(msg); } public void close() throws JMSException { qsender.close(); qsession.close(); qcon.close(); } public static void main(String[] args) throws Exception { if (args.length != 1) { System.out.println("Usage: java QueueSend WebLogicURL"); return; } InitialContext ic = getInitialContext(args[0]); QueueSend qs = new QueueSend(); qs.init(ic, QUEUE); readAndSend(qs); qs.close(); } private static void readAndSend(QueueSend qs) throws IOException, JMSException { String line="Test Message Body with counter = "; BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); boolean readFlag=true; System.out.println("ntStart Sending Messages (Enter QUIT to Stop):n"); while(readFlag) { System.out.print("<Msg_Sender> "); String msg=br.readLine(); if(msg.equals("QUIT") || msg.equals("quit")) { qs.send(msg); System.exit(0); } qs.send(msg); System.out.println(); } br.close(); } private static InitialContext getInitialContext(String url) throws NamingException { Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY); env.put(Context.PROVIDER_URL, url); return new InitialContext(env); } }
- In QueueReceive.java copy the below command
import java.util.Hashtable; import javax.jms.*; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; public class QueueReceive implements MessageListener { public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory"; // ******* Give the CONNECTION FACTORY JNDI name which is QCF ******** public final static String JMS_FACTORY="QCF"; // ******* Give the UNIFORM DISTRIBUTED QUEUE JNDI name which is TestQ ******** public final static String QUEUE="TestQ"; private QueueConnectionFactory qconFactory; private QueueConnection qcon; private QueueSession qsession; private QueueReceiver qreceiver; private Queue queue; private boolean quit = false; public void onMessage(Message msg) { try { String msgText; if (msg instanceof TextMessage) { msgText = ((TextMessage)msg).getText(); } else { msgText = msg.toString(); } System.out.println("nt<Msg_Receiver> "+ msgText ); if (msgText.equalsIgnoreCase("quit")) { synchronized(this) { quit = true; this.notifyAll(); // Notify main thread to quit } } } catch (JMSException jmse) { jmse.printStackTrace(); } } public void init(Context ctx, String queueName) throws NamingException, JMSException { qconFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY); qcon = qconFactory.createQueueConnection(); qsession = qcon.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); queue = (Queue) ctx.lookup(queueName); qreceiver = qsession.createReceiver(queue); qreceiver.setMessageListener(this); qcon.start(); } public void close()throws JMSException { qreceiver.close(); qsession.close(); qcon.close(); } public static void main(String[] args) throws Exception { if (args.length != 1) { System.out.println("Usage: java QueueReceive WebLogicURL"); return; } InitialContext ic = getInitialContext(args[0]); QueueReceive qr = new QueueReceive(); qr.init(ic, QUEUE); System.out.println("JMS Ready To Receive Messages (To quit, send a "quit" message from QueueSender.class)."); // Wait until a "quit" message has been received. synchronized(qr) { while (! qr.quit) { try { qr.wait(); } catch (InterruptedException ie) {} } } qr.close(); } private static InitialContext getInitialContext(String url) throws NamingException { Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY); env.put(Context.PROVIDER_URL, url); return new InitialContext(env); } }
- Now open 2 – command promt Windows and run “setWLSEn.cmd” in all the three Command Windows to set the Environment (PATH & CLASSPATH).
- Then compile the QueueSend.java and QueueReceive.java programs.
- Now run the code with the following command
- Once this is been done try to send few messages in the Prompt one which is sending to the port 8001 which the Source Detonation in Domain-1 , however you will notice that the message would be received on Prompt-2 which is listening on port 7001 which the Target Detonation in Domain-2 as shown in the below snap-shot.
Prompt-1
java QueueSend t3://localhost:8001
Prompt-2
java QueueReceive t3://localhost:7001
Note:
With the “java QueueSend” and “java QueueReceive” command you have to give the<Protocol>://<IP-address>:<Port number>of the managed servers in different prompts.
.
Thus this way we can see that using weblogic messaging bridge we can transfer messages from one domain to the second domain easily.
.
Thanks,
Ravish Mody
December 3rd, 2010 on 11:47 pm
great stuff, thank you.
How much latency do you expect to be introduced by a Messaging Bridge, in a worst case scenario? Is it a matter or milliseconds, or of seconds?
thanks!
December 4th, 2010 on 10:08 pm
Hi Vernetto,
Its great to hear that you liked the post.
Your question is pretty good, however the answer to it is that it might take milliseconds or even seconds too depending on the scenario, but in the worst case scenario the message would not even go 😉
Regards,
Ravish Mody
February 20th, 2011 on 3:11 pm
Hello Ravish,
With the above example, i am also running QReceive on the domain 8001. Thus QReceive is running with 2 instances. One on 8001 and other on domain 2 with 7001.
In this case message is going alternately to each receiver and behaves like a Distributed Q.
Thanks
Sumit
February 20th, 2011 on 5:30 pm
Hi Sumit,
I dint get it, how many bridge-source and bridge-target do you have? Is it something like below
Bridge-1
=====
Source- QCF, TestQ, t3://localhost:8001
Target- QCF, TestQ, t3://localhost:7001
Bridge-2
=====
Source- QCF1, TestQ1, t3://localhost:8001
Target- QCF2, TestQ2, t3://localhost:8001
February 20th, 2011 on 7:51 pm
Ravish,
Only 1 bridge. What i am doing is
See our configuration is Q is on 8001 as well on 7001(domain2)and bridge in 8001 (domain1)
Now I am starting the QueueSend on t3://IP:8001.
Also i am starting the QueueReceive on t3://IP:8001 as well on t3://IP:7001. Thus QueueReceiver is on domain2 as well as domain1.
So what ever i am sending is coming alternately on QReceiver of domain1 and domain2. Thus behave like DistributedQ.
Thanks
Sumit
February 20th, 2011 on 8:06 pm
Hi Sumit,
🙂 Can I ask what is the purpose behind this test? Because it makes no sense and I have not seen anyone doing the same. Main purpose of bridge is to send messages from one domain to other.
If you need DistributedQ then you can use UDQ instead.
February 20th, 2011 on 8:55 pm
Ravish,
I did this , just to get to know what will be the behavior if the configurations are like the above mentioned.I did not know it will behave like DistributedQ.
However it could be possible for a given Q ,the consumer can be on local domain as well as on other domain?
Thanks
Sumit
February 20th, 2011 on 9:40 pm
Hi Sumit,
There are various combinations of the configuration can be done to achieve the same thing… It is like doing a very simple task by chosing various complex steps or doing the same thing in a single simple step.
The architecture which you are trying to implement we never used so we won;t be able to comment anything on that. But It will be a good experiment for you. Please do let us know your findings on this architecture which you are using.
.
.
Keep Posting 🙂
Thanks
Jay SenSharma
February 20th, 2011 on 9:50 pm
Hi Sumit,
If it is for testing purpose then its fair enough and yes it could be possible for a given Q ,the consumer can be on local domain as well as on other domain but not for consuming from the same queue which is been used for a bridge as its does not make sense. Because it would become confusing which queue is been used for what, for a bridge or for local consumer and I have never seen this kind of architecture been used till now.
February 20th, 2011 on 11:18 pm
Thanks Jay/Ravish,
Yes it is not the standard architecture. I just tried it out to know how WL will behave.
Thanks
Sumit
February 21st, 2011 on 12:27 pm
Hi Sumit,
The basic difference between SAF and Bridge is that the main reason SAF’s had been implemented in WLS was that they wanted the messages to be delivered to the receiver even when the receiver was down when the messages where sent and Bridge to be used for forwarding mechanism of messages, which also provides interoperability between weblogic JMS implementations and between any other JMS messaging products and two different domains of weblogic serves also.
Now when and were should one use SAF or Bridge is totally depended on the requirement and the architecture, say if I have a very critical messages which has to be delivered to the receiver even if the receiver goes down but should be delivered once it comes back on then would go for a SAF.
April 27th, 2011 on 12:08 pm
MY bridge on 8001 indicates its inactive., How should I make it active, I restarted the admin server on 8001 but still no luck.
May 2nd, 2011 on 5:14 pm
Hi Testab,
Make sure that you have checked Started check box for that particular Bridge below is the path
Bridges –> [YOUR_BRIDGE_NAME] –> Configuration [tab] –> General [sub-tab]
If it’s checked and the same server is up and running then it would be good to enable the debug flags for messagingbridge
Servers –> [YOUR_SERVER_NAME] –> Debug [tab] –> (+) weblogic
Then check your server log that would give some light on it.
Regards,
Ravish Mody
July 15th, 2011 on 10:47 am
Hi Ravish,
This post is really helpful. Please can you tell me how shoud we configure this bridge for clustered environments.
July 15th, 2011 on 6:10 pm
Hi Dnyanesh,
Are you looking out for something like “Target Bridge Destination” should send to a UDQ? or something else ?
Regards,
Ravish Mody