1 2 3 4 Previous Next 51 Replies Latest reply on Nov 23, 2006 2:27 PM by ovidiu.feodorov

    Incorporating Remoting http transport into Messaging

    ron_sigal

      I'm starting this thread to discuss the integration of the JBossRemoting http transport into messaging. With some changes to Messaging code and some changes to Remoting code the test org.jboss.example.jms.http.HttpExample passes.

      The Messaging changes revolve around JMSWireFormat:

      1. JMSWireFormat can't expect to get passed ObjectInputStreams and ObjectOutputStreams. This has been discussed already, although I can't find the reference. I changed it to create object streams as necessary. However, when they are created, e.g.,

      oos = SerializationStreamFactory.getManagerInstance("key").createOutput(out);

      "key" has to be replaced by a suitable value. I assume it would be acceptable to just hard code "jboss", but the solution to problem 2) below involves passing in the server's InvokerLocator, so it's easy to do a quick check for any specific instructions about serialization. By the way, I see that in ServerPeer, the key "jms" is associated with jboss serialization, but I don't see any use of "jms" anywhere, so I commented that out. Since ServerPeer doesn't currently have access to the InvokerLocator, I also commented out the registration of a JMSWireFormat keyed on "jms".


      2. JMS uses instances of SerializableMarshaller and SerializableUnMarshaller in some default cases. However, the http transport needs to use subclasses HTTPMarshaller and HTTPUnMarshaller, which means JMSWireFormat needs to know what transport is being used. An easy way to determine the transport would be to look at the InvokerLocator, but currently the InvokerLocator doesn't seem to be available everywhere it would be needed. Instances of JMSWireFormat are created in the following classes:

      JMSRemotingConnection - no problem: it has the InvokerLocator

      ClientConnectionFactoryDelegate - no problem: it already gets the InvokerLocator

      ServerConnectionEndpoint - I changed the constructor so that ServerConnectionFactoryEndpoint can pass in the InvokerLocator

      TestWireFormat - it calls the JMSWireFormat default constructor, which defaults to the socket transport and jboss serialization

      It was also necessary to change the ServerConnectionFactoryEndpoint constructor to pass in the InvokerLocator, so it could pass it to ServerConnectionEndpoint.


      3. A third change was necessary in JMSWireFormat, due to the way the server side http invoker (CoyoteInvoker) returns invocation results. In particular, since it doesn't know if it's talking to the client side http invoker or some other foreign client, it can't necessarily return the result wrapped in an InvocationResponse. We made some changes to the http transport so that the client side can tell the server side that it's a remoting invoker, but that involves putting a flag in the InvocationRequest. Since JMSWireFormat doesn't wrap messaging messages in an InvocationRequest, the changes don't help JMSWireFormat in general (though it solves a problem with null responses from internal Remoting requests). So, I changed the decision tree in JMSWireFormat.write() to accept arbitrary objects.

      4. The http transport needs tomcat jars.

        • 1. Re: Incorporating Remoting http transport into Messaging
          timfox

          For JMS traffic (e.g. messages) going from server to client, how do you do this? (Obviously you can't have a HTTP server on the client accepting connections)

          Do you poll the server from the client intermittently, or do you piggyback server to client traffic on return values of client to server traffic, or both?

          BTW all the stream stuff in the marshaller is a big pain.

          I have been having related issues since as you realised remoting always passes in a ObjectInput/Ouput Stream.

          In TRUNK I have changed all this so that now the underlying stream is passed in, so you're changes in that area may not be necessary.

          • 2. Re: Incorporating Remoting http transport into Messaging
            ovidiu.feodorov

             

            ron_sigal wrote:

            1. JMSWireFormat can't expect to get passed ObjectInputStreams and ObjectOutputStreams. This has been discussed already, although I can't find the reference. I changed it to create object streams as necessary.


            timfox wrote:

            BTW all the stream stuff in the marshaller is a big pain.
            I have been having related issues since as you realised remoting always passes in a ObjectInput/Ouput Stream.
            In TRUNK I have changed all this so that now the underlying stream is passed in, so you're changes in that area may not be necessary.


            It looks to me that you both applied similar changes concurrently on TRUNK and Branch_1_0. Since we need to get CR5 out ASAP, how about Ron checks in his changes, and we will reconcile them with the trunk later?

            ron_sigal wrote:

            oos = SerializationStreamFactory.getManagerInstance("key").createOutput(out);
            "key" has to be replaced by a suitable value. I assume it would be acceptable to just hard code "jboss", [...]


            Messaging uses whatever serialization Remoting Connector was configured with, both on client-to-server marshalling and vice-versa. We need to keep this consistent. Take a look at CallbackSErverFactory, for example, to see how this is configured.

            timfox wrote:

            For JMS traffic (e.g. messages) going from server to client, how do you do this? (Obviously you can't have a HTTP server on the client accepting connections)
            Do you poll the server from the client intermittently, or do you piggyback server to client traffic on return values of client to server traffic, or both?


            Reiterating the same questions.



            • 3. Re: Incorporating Remoting http transport into Messaging
              ron_sigal

               

              For JMS traffic (e.g. messages) going from server to client, how do you do this?


              Sorry, Tim, I'm not sure what "this" refers to. But, actually, when you start a callback connector on the client with the http transport, the server side invoker functions like an HTTP server. The message is handled by a Tomcat connector, which calls CoyoteInvoker.service(). Tom could tell you more about it. Before he replaced it with CoyoteInvoker, he wrote HTTPServerInvoker, which is an HTTP/1.1 complient server.

              • 4. Re: Incorporating Remoting http transport into Messaging
                ovidiu.feodorov

                How does a client get asynchronously messages from the server?

                • 5. Re: Incorporating Remoting http transport into Messaging
                  timfox

                  I just wanted to clarify that there is no http server on the client side listening for connections from the server side.

                  Client side = jms client

                  Server side = jms server

                  If that's the case, then that's cool :)

                  • 6. Re: Incorporating Remoting http transport into Messaging
                    ron_sigal

                     


                    Messaging uses whatever serialization Remoting Connector was configured with, both on client-to-server marshalling and vice-versa. We need to keep this consistent. Take a look at CallbackSErverFactory, for example, to see how this is configured.


                    I was thinking of the following code from ServerPeer:

                     // We explicitly associate the datatype "jms" with the java SerializationManager
                     // This is vital for performance reasons.
                     SerializationStreamFactory.setManagerClassName(
                     "jms", "org.jboss.remoting.serialization.impl.jboss.JBossSerializationManager");
                    
                     JMSWireFormat wf = new JMSWireFormat();
                    
                     MarshalFactory.addMarshaller("jms", wf, wf);
                    


                    I can't see a use of "jms" anywhere in Messaging, so I commented it out.

                    In any case, I updated JMSWireFormat with a constructor which takes an InvokerLocator parameter, from which it attemtps to get a serializationType value. If there is none, it defaults to "jboss". All JMSWireFormat instances in Messaging 1.0 are now created with a call to this new constructor, with the exception of one test case, which should be happy with the defaults (transport = "socket", serializationType = "jboss").

                    • 7. Re: Incorporating Remoting http transport into Messaging
                      ron_sigal

                       

                      just wanted to clarify that there is no http server on the client side listening for connections from the server side.

                      Client side = jms client

                      Server side = jms server

                      If that's the case, then that's cool :)


                      I'm not sure if the Tomcat connector qualifies as a full-fledged http server, but a Connector's a Connector, wherever it is. Functionally, it's a server running on the jms client side. Normally, the org.jboss.remoting.Client that calls the callback server is built inside of Remoting, but I noticed that Messaging manages its Clients explicitly. So for callbacks, the jms server side is actiing like a client. [Try explaining this in Japan to a room full of people that don't speak English. :-)]

                      • 8. Re: Incorporating Remoting http transport into Messaging
                        timfox

                        The code in TRUNK doesn't use remoting serialization managers at all any more.

                        I was fed up with the fact that remoting always passed in an ObjectOutput/Input Stream, so I have created new subclasses of ObjectOutput/InputStream called MessagingObjectOutput/InputStream which basically are just a thin wrapper over a straightforward DataOutput/InputStream.

                        This means we can have full control over the bytes we write to the stream without having to worry about all the other serialization header rubbish being written that we don't need.

                        The only times we need to serialize stuff is for non performance critical invocations and for object messages containing a user provided object that we don't know until runtime.

                        In these cases i just create an object output/input stream on the fly and serialize to the dataoutputstream.

                        So the value of serializationType in the uri is completely ignored.

                        • 9. Re: Incorporating Remoting http transport into Messaging
                          ron_sigal

                           

                          "ovidiu.feodorov@jboss.com" wrote:
                          How does a client get asynchronously messages from the server?


                          I don't remember which Messaging classes are involved, but when a queue or a topic gets a message to transmit, it ends up calling an org.jboss.remoting.Client.

                          • 10. Re: Incorporating Remoting http transport into Messaging
                            ovidiu.feodorov

                            That's not good.

                            This is exactly what we DON'T want, a server running on the client side.

                            The whole idea with HTTP is that the user does not need to open any inboud client-side firewal ports to receive asynchonous notifications.

                            The remoting runtime should poll on the client side, not start a HTTP server.

                            • 11. Re: Incorporating Remoting http transport into Messaging
                              ron_sigal

                               

                              "timfox" wrote:

                              I was fed up with the fact that remoting always passed in an ObjectOutput/Input Stream, so I have created new subclasses of ObjectOutput/InputStream called MessagingObjectOutput/InputStream which basically are just a thin wrapper over a straightforward DataOutput/InputStream.
                              .


                              I don't see how this works. JMSWireFormat is called by Remoting, which passes in an InputStream/OutputStream. How do you get around the socket transport passing in Object streams? Just wondering.

                              • 12. Re: Incorporating Remoting http transport into Messaging
                                ovidiu.feodorov

                                These details are moot now, since the main reason we need HTTP for, firewall transparency, isn't going to be available anytime soon, not today, in any case, when we intend to release CR5.

                                • 13. Re: Incorporating Remoting http transport into Messaging
                                  ron_sigal

                                   

                                  "ovidiu.feodorov@jboss.com" wrote:
                                  That's not good.

                                  This is exactly what we DON'T want, a server running on the client side.

                                  The whole idea with HTTP is that the user does not need to open any inboud client-side firewal ports to receive asynchonous notifications.

                                  The remoting runtime should poll on the client side, not start a HTTP server.


                                  Sorry - I was thinking of push callbacks. There is also a pull callback mechanism, in which the callbacks are retrieved by calling

                                  org.jboss.remoting.Client.getCallbacks()


                                  Which is used depends on how callbacks are configured by way of the call to

                                  org.jboss.remoting.Client.addListener()


                                  I don't remember off hand how that is done in Messaging.

                                  • 14. Re: Incorporating Remoting http transport into Messaging
                                    ovidiu.feodorov

                                    Do pull calbacks work with the HTTP transport?

                                    1 2 3 4 Previous Next