1 2 3 4 Previous Next 46 Replies Latest reply on Dec 7, 2009 11:37 PM by mnop629

    Remote replyto functionality - Bridge configuration in pairs

    thomasra

      Continuing discussion from http://www.jboss.org/index.html?module=bb&op=viewtopic&t=110293...

      It is common to want to bridge new and existing messaging systems (JBM Bridge makes this easy) but replies and correlation are a bit more difficult.

      If the Bridge were to be configured as an in/out pair instead of just being in one direction, the outbound route could:

      * see that a JBM message has a replyto destination set (which indicates a reply is wanted at that destination)
      * create a remote temp destination
      * send the message to the remote provider using the remote temp destination as the replyto destination

      ...then the inbound route could share this information and listen to remote temp destinations knowing which inbound message is a reply to an outbound message.

      If the idea of temp destinations doesn't work, we could still keep the state of the messageid's from JBM and the remote provider so that correlation could be done on the JBM side, but again, this would probably be much easier if the Bridge was two-way.

      Any thoughts?

        • 1. Re: Remote replyto functionality - Bridge configuration in p
          thomasra

          Continuing the thoughts from the previous post....

          Adding two sets of source/destination is pretty trivial (Perhaps differentiate bridges by calling them OneWayBridge and TwoWayBridge?).

          Without using temp destinations we could just keep track of original messageid's and original ReplyTo destinations from JBM and their corresponding remote messageid. Then, when the message is received from the remote provider (using JMSCorrelationId to link request/response), we could look up the correlationid on it and find the original data, replacing it before sending to a JBM destination.

          A lookup table would need:

          originalJBMJMSMessageId - originalJBMReplyTo - remoteJMSMessageId

          With temp destinations it becomes even more powerful (but requires more support on the remote side, both client and server). In this case we don't need to keep track of the remote messageid, since we know that messages received on the temp destination are a reply to a specific JBM message. The downside is that the receiving part of the bridge would need to listen to a temp destination (or use unique selectors on a shared destination). Come to think of it, selectors would actually suffice and be cleaner, but maybe theres an anti-pattern there somewhere.

          * JMS Message arrives at a JBM destination
          * TwoWayBridge receives it, sees that it has a ReplyTo destination, keeps track of the original replyto destination and jmsmessageid
          * TWB creates a remote temp destination
          * TWB sends the message with the remote temp destination as the ReplyTo value, after send() it adds the remoteJMSMessageId to the same record
          * TWB begins listening on the remote temp queue (it now knows which message it is waiting for a response to)
          * TWB receives a response from the remote provider on the temp destination
          * TWB replaces the correlationid and the replyto values with the original ones
          * TWB sends to a JBM destination

          • 2. Re: Remote replyto functionality - Bridge configuration in p
            thomasra

             

            "thomasra" wrote:

            * JMS Message arrives at a JBM destination
            * TwoWayBridge receives it, sees that it has a ReplyTo destination, keeps track of the original replyto destination and jmsmessageid
            * TWB creates a remote temp destination
            * TWB sends the message with the remote temp destination as the ReplyTo value, after send() it adds the remoteJMSMessageId to the same record
            * TWB begins listening on the remote temp queue (it now knows which message it is waiting for a response to)
            * TWB receives a response from the remote provider on the temp destination
            * TWB replaces the correlationid and the replyto values with the original ones
            * TWB sends to a JBM destination


            Correction: we do not need to keep the remote messageid in this scenario (it is irrelevant).

            • 3. Re: Remote replyto functionality - Bridge configuration in p
              thomasra

              Actually, JMS 1.1 section 5.10 QueueRequestor already does the temp stuff for us, so we could just thread out a QueueRequestor from the Bridge when sending to the remote provider, it will block until a response is received, and then we know what this is a response to.

              • 4. Re: Remote replyto functionality - Bridge configuration in p
                thomasra

                It could be as simple as this perhaps (from inside the sendBatch method in Bridge):

                 // Differentiate between messages that require a reply
                 Destination originalDestination = msg.getJMSReplyTo();
                 if(originalDestination == null) {
                 producer.send(msg);
                 } else {
                 // This probably needs to be spawned in a separate thread so it doesn't block
                 QueueRequestor q = new QueueRequestor((QueueSession) targetSession, (Queue) producer.getDestination());
                 Message response = q.request(msg);
                 producer.send(originalDestination, response); // This isn't the correct producer, though
                 }
                
                


                • 5. Re: Remote replyto functionality - Bridge configuration in p
                  timfox

                  Haven't forgotten about this.

                  Will reply soon. :)

                  • 6. Re: Remote replyto functionality - Bridge configuration in p
                    timfox

                    Interestintg ideas, some thoughts:

                    Regading the correlation id approach, wo we really need to automatically correlate message ids from server 1 with message ids from server 2?

                    One other possibility would be for the JBM bridge to take the old message id (the message id before sending to the second server) and set it is a property of the message (with a key JBossMessage.JBM_OLD_MESSAGE_ID (or whatever)).

                    The receiver of the message on the second server then has access to this property and can set it as the JMSCorrelationID of the response message. This would avoid the bridge having to maintain its own lookup map.

                    The JBM_OLD_MESSAGE_ID could even be chained, if the message has been routed through several servers before arriving at its destination, so it would actually be a set of message ids.

                    Regarding the temporary queue approach, yes this could work and is quite a nice idea. However, the tricky bit would knowing whether you'd already created a temporary queue on the remote server for a particular message, since you don't want to create a new temp queue on *every* message send, with a temp queue request/response model you typicall use the same remote queue for the whole sender's session. Also we would need to know when it is safe to delete the remote temp queue - this might be tricky too.

                    • 7. Re: Remote replyto functionality - Bridge configuration in p
                      thomasra

                      I agree the correlation bit isn't necessary if we use temp queues, however, the JMS spec intent on using those fields (albeit on a single provider) is something that would be very nice to have.

                      I went along and changed Bridge.java to test this using temp queues, by adding an inner class that is a Runnable, and then using QueueRequestor. Then the bridge would just spawn the inner class in a new thread, which blocks until a response arrives, and then it switches ReplyTo back again to the original values. I haven't thought about the overhead of creating/closing temp queues, so that is valuable input.

                      Atleast if things were implemented this way we wouldn't have to keep a mapping (the Runnable is given the necessary state through the constructor).

                      I see some problems with this, but they might be trivial to implement:

                      * Threading and replies that don't arrive (we would need to set a timeout and handle the situation)
                      * Pooling the threads so things don't get out of hand
                      * Reduce performance hit by reusing temp queues for a session

                      Oh, and I am testing the bridge using activemq as the remote provider, and will gather some experiences with this that I can give you.

                      Any more?

                      • 8. Re: Remote replyto functionality - Bridge configuration in p
                        thomasra

                        Oh, and I'm not a big fan of using properties on the message since that implicitly ties the client to using "our" semantics. I think it is better to keep things as transient to the remote client as possible.

                        • 9. Re: Remote replyto functionality - Bridge configuration in p
                          thomasra

                          BTW: In order to get Bridge to work with activemq (via a resource adapter) I had to update the sendBatch method and create a new javax.jms.Message, copying properties since the current implementation is tied to JBossMessage and complains when using a foreign destination.

                          • 10. Re: Remote replyto functionality - Bridge configuration in p
                            timfox

                             

                            "thomasra" wrote:
                            BTW: In order to get Bridge to work with activemq (via a resource adapter) I had to update the sendBatch method and create a new javax.jms.Message, copying properties since the current implementation is tied to JBossMessage and complains when using a foreign destination.


                            Not sure I follow, can you expand please?

                            • 11. Re: Remote replyto functionality - Bridge configuration in p
                              thomasra

                              Well, after deploying the activemq rar according to online docs, when I configured Bridge to use an activemq queue as the target (and a local queue as the source) it began complaining about not supporting "foreign" destinations, since it was attempting to set a destination from one implementation on a message from another.

                              • 12. Re: Remote replyto functionality - Bridge configuration in p
                                thomasra

                                To elaborate further:

                                The code in question does this:

                                producer.send(msg);
                                


                                ...which doesn't quite work when the message is from another provider than the producer.

                                • 13. Re: Remote replyto functionality - Bridge configuration in p
                                  timfox

                                  I don't follow why you are using an ActiveMQ rar. The bridge only requires you to set up a JMSProviderAdaptor for ActiveMQ, the JMSProviderAdaptor should just specify the ConnectionFactory lookup and jndi properties, no rar necessary.


                                  • 14. Re: Remote replyto functionality - Bridge configuration in p
                                    timfox

                                    Here's the default (local) JMSProviderLoader from jms-ds.xml:

                                     <mbean code="org.jboss.jms.jndi.JMSProviderLoader"
                                     name="jboss.mq:service=JMSProviderLoader,name=JMSProvider">
                                     <attribute name="ProviderName">DefaultJMSProvider</attribute>
                                     <attribute name="ProviderAdapterClass">
                                     org.jboss.jms.jndi.JNDIProviderAdapter
                                     </attribute>
                                     <!-- The combined connection factory -->
                                     <attribute name="FactoryRef">java:/XAConnectionFactory</attribute>
                                     <!-- The queue connection factory -->
                                     <attribute name="QueueFactoryRef">java:/XAConnectionFactory</attribute>
                                     <!-- The topic factory -->
                                     <attribute name="TopicFactoryRef">java:/XAConnectionFactory</attribute>
                                     <!-- Uncomment to use HAJNDI to access JMS
                                     <attribute name="Properties">
                                     java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
                                     java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
                                     java.naming.provider.url=localhost:1100
                                     </attribute>
                                     -->
                                     </mbean>
                                    


                                    You should just be able to set one up pointing to your ActiveMQ instance and reference that as your target JMSProviderLoader in the bridge config.

                                    1 2 3 4 Previous Next