Announcement Announcement Module
Collapse
No announcement yet.
Remoting using SI and AMQP? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Remoting using SI and AMQP?

    Hi,

    Just getting to grips with this all.

    I was wondering if it is possible for a web layer (for example) to send an Object (say a Person) via Spring Integration into AMQP then a Service Layer pick up that Object from the queue and invoke a service method it knows about?

    I.e.,

    http request (/person/1) -> web layer -> SI (amqp outbound-gateway) (using a gateway)

    PersonGateway -> Person getPerson(String id) -> SI -> AMQP (rest.to.service.queue)

    then something listening to RabbitMQ rest.to.service.queue...

    AMQP (rest.to.service.queue) -> SI (amqp inbound-gateway) -> some magic here that routes the payload of the message to PersonService.getPerson(String id). It processes the request and sends the reply all the way back to the web layter (via SI then AMQP into SI and then into the Controller).

    I'm not sure if this can be done? I've googled around and nothing comes up with an answer that I can make sense of.

    Thanks!

    bootlaces

  • #2
    I suggest you explore the samples https://github.com/SpringSource/spri...ration-samples and reference documentation http://static.springsource.org/sprin...eference/html/

    If you are talking about a new application then just wire up an http inbound gateway to an amqp outbound gateway (web tier); in the service layer, use an amqp inbound gateway and a <service-activator/> to invoke your person service; the object returned by the person service will be returned (over AMQP) to the original http inbound gateway. You can use java serialization or JSON (preferred) to transfer objects over AMQP.

    If you have an existing web application that you want to use to invoke your person service, then the Messaging Gateway is your friend http://static.springsource.org/sprin...r.html#gateway

    Instead of using an http inbound gateway, wire the messaging gateway into your web app and invoke your Spring Integration flow that way.

    Comment


    • #3
      Hi Gary,

      Thanks for replying.

      I've tried messaging gateway (can't use http-inbound gateway - using Spring MVC to handle stuff on the web layer and do some processing before handing off to the service layer (hopefully via AMQP and SI)).

      The problem I see with the gateway, is that I don't know how to route to different service methods within a service, i.e:

      Web Layer:

      Code:
      <int:gateway id="systemGateway" service-interface "com.fubar.service.SystemGateway" default-request-channel="restToServiceGateway"/>
      now, in my SystemGateway:

      Code:
      public interface SystemGateway {
      
          @Payload("'status'")
          Future<String> getStatus();
      
          Future<Information> getInformation();
      
          Future<Information> getInformation(final Computer computer);
      
      }
      Service Layer (different app running in a different JVM but listening to the "rest.to.service.queue" on RabbitMQ)

      Code:
      public class StatusEndpointImpl {
      
         @ServiceActivator
         public String status() {
             return "w00t";
         }
      
        @ServiceActivator
        public Information information() {
             return new Information();
        }
      
        @ServiceActivator
        public Information information(final Computer computer) {
            return new Information(computer);
        }
      
      }
      And the Spring Integration for the Service Layer:

      Code:
      <int-amqp:inbound-gateway 
      id="restToService"    
      connection-factory="rabbitConnectionFactory" 
      request-channel="restToServiceChannel"
      reply-channel="serviceToRestChannel"
      queue-names="rest.to.service.queue"               
      />
      How does SI know how to invoke each method in the StatusEndpointImpl depending on the message coming in from RabbitMQ via the queue (rest.to.service.queue).

      This bit is unclear for me. If I have a gateway on the "rest" layer that I invoke from a controller and a JSON message is marshalled out and put on the wire to AMQP and I have a service listening on that queue, how does SI take that message and invoke the correct service activator?

      Very lost! I'm sorry! :-(

      bootlaces

      Comment


      • #4
        There are a number of ways to do that. One way would be to add <int:method/> sub elements to your <gateway/>...

        Code:
        <int:gateway id="systemGateway" service-interface "com.fubar.service.SystemGateway" default-request-channel="restToServiceGateway">
        	<int:method name="send">
        		<int:header name="requestType" value="foo" />
        	</int:method>
        	<int:method name="info">
        		<int:header name="requestType" value="info" />
        	</int:method>
        </int:gateway>
        Add mapped-request-headers="requestType" to the outbound and inbound amqp gateways so that the header is propagated.

        On the service side define 3 <service-activator/>s; one for each method, and use routers to route to the appropriate service corresponding to the appropriate information() method.

        Code:
        <int:header-value-router ... header-name="requestType">
           <int:mapping value="status" channel="statusChannel" />
           <int:mapping value="info" channel="infoChannel" />
        </int:header-value-router>
        It would be easiest if you can rename one of your 'information' methods. If not, you can use a payload type router in infoChannel to route to the appropriate service.



        Another thing you could do is use @Payload("#method") on the no-arg methods (so the method name becomes the payload) and use a payload type router on the server side to route payloads of type Computer to the information(Computer computer) service and type String to another router that routes to the appropriate service based on the payload value.

        This second mechanism has the benefit that you don't have to configure the amqp gateways to handle custom headers.
        I hope that's clear.

        Comment


        • #5
          Hi Gary,

          Thank you for your comprehensive reply. I'm not sure what approach to take. If I go with custom headers, then I see potentially we could have lots of services with lots of methods in each service, thus making the xml that configures each gateway long and hard to maintain. I suppose I could do it as a series of import statements to import the xml configurations for each gateway. Hmmm...

          Second approach I'll have to think about a bit more.

          In general, I'm starting to feel it's quite a lot of effort to invoke a remote service from the web layer (with a sense of decoupling the web layer way from the service layer - but having some type of messaging system inbetween to handle remote calls).

          I'm just wondering, from your POV, if you wanted to decouple the web from the service layer (and be able to invoke remote spring services), what would you do (no using http inbound gateway :-)) - it has to flow through Spring MVC :-)).

          I'll be using SI for other stuff (like within the Service layer, channeling off emails or things like that)

          bootlaces.

          Comment


          • #6
            FYI, it is less complex when you always have an argument. For example, if you have methods in a service such as

            Code:
            public interface MyServiceInterface {
            
                Order getOrder(OrderRequest or);
            
                Customer getCustomer(CustomerRequest cr);
            
                Invoice getInvoice(InvoiceRequest ir);
            
            }
            The framework can figure out which method to call based on what's in the payload; you just need a distinct type for each. It's only when there's ambiguity that the framework needs help.

            Comment


            • #7
              Hi Gary,

              When you say the "framework can figure out which method to call based on what's in the payload", I still need a payload router to examine the contents of the payload and route to the appropriate channel, right?

              Comment

              Working...
              X