Results 1 to 8 of 8

Thread: Custom Header Message over TCP

  1. #1
    Join Date
    Oct 2012
    Posts
    6

    Default Custom Header Message over TCP

    Hi,

    I am new to Spring and trying to send a message with payload from client to server (running in separate JVMs) over TCP.

    I have read through the post here, http://forum.springsource.org/showth...pass-to-server and tried to understand how the payload is being enhanced on the client and then being stripped on the server however I'm not doing too well.

    I like the idea of keeping the enhancement within Spring rather than wrapping the message in another serializable object before sending it through and would be grateful if anyone could point me in the direction of any more examples of this?

    What I want to do is give my message object a header of ('REQUEST-TYPE', 'CREATE') and then strip this off once it gets to the server and pipe it to the create class using a header-value-router. Equally there will be a header for 'READ', 'AMEND' and 'DELETE' again distributed by the header router.

    If anyone could give any more detail on the method described in the thread above I would appreciate it!

    Thanks,
    Alex

  2. #2
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,017

    Default

    Can you provide an example of what your payload looks like? I should then be able to give you a strategy.
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  3. #3
    Join Date
    Oct 2012
    Posts
    6

    Default

    Hi Gary,
    Thanks for the quick response, I'll go into more detail of what I would like to achieve..

    I have Scheduler service (using Quartz) and other services who want to CRUD on the schedule. The services run as standalone Java apps all using Spring to talk to each other.

    I have a Schedule Object (the payload) which has setters and getters for the other services to complete before sending to the schedule service which then extracts the information and does what ever it needs to do to the schedule.

    I have a class containing four methods, one for Create, Read, Update and Delete and if I wasn't using TCP I would get whatever creates the schedule object and adds it to the message to just set the headers. Then I would use a header value router in order to send the payload to whichever of the four methods matches the header.

    The problem I have is getting the schedule object to keep the header so spring knows which method to route the object to.

    I hope that helps?

    Thanks for your help!

  4. #4
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,017

    Default

    I assume the Schedule object is Serializable. The enhance/strip logic in that other post assumes a String payload.

    You can simply wrap your Schedule object in a wrapper...

    Code:
    @SuppressWarnings("serial")
    public class Wrapper implements Serializable {
    
    	private final Schedule schedule;
    
    	private final String command;
    
    	public Wrapper(Schedule schedule, String command) {
    		this.schedule = schedule;
    		this.command = command;
    	}
    
    	public Schedule getSchedule() {
    		return this.schedule.
    	}
    
    	public String getCommand() {
    		return command;
    	}
    
    }
    Then, on the outbound side, right before the tcp outbound endpoint, add a transformer

    Code:
    <transformer input-channel="input" output-channel="toTcp"
      expression="new foo.Wrapper(payload, 'CREATE')"/>
    and on the inbound side, right after the TCP inbound...

    Code:
    <chain input-channel="fromTCP" output-channel="toHeaderRouter">
    	<header-enricher>
    		<header name="COMMAND" expression="payload.command"/>
    	</header-enricher>
    	<transformer expression="payload.schedule"/>
    </chain>
    This all assumes you're TCP connection factories are configured to use the Java serialization (de)serializers...

    Code:
    <bean id="defaultSerializer" class="org.springframework.core.serializer.DefaultSerializer" />
    
    <bean id="defaultDeserializer" class="org.springframework.core.serializer.DefaultDeserializer" />
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  5. #5
    Join Date
    Oct 2012
    Posts
    6

    Default

    Cheers, that looks great!

    I've got all the serialization in place as you suggested.

    Just to confirm my understanding with what is going on..

    Code:
    <transformer input-channel="input" output-channel="toTcp"
      expression="new foo.Wrapper(payload, 'CREATE')"/>
    When the transformer expression passes the payload (Schedule Object) to the Wrapper does Spring know the reference 'payload' is the payload being passed down the channel?


    Code:
    <chain input-channel="fromTCP" output-channel="toHeaderRouter">
    	<header-enricher>
    		<header name="COMMAND" expression="payload.command"/>
    	</header-enricher>
    	<transformer expression="payload.schedule"/>
    </chain>
    I see that this is extracting the payload from the wrapper, and then creating a new header, does the expression of the header become what mapping value in the header value router?

    Also, is the rest of the wrapper discarded so I just end up with schedule object passed down the pipe to the router and ultimately the method in the schedule service?


    I appreciate your help with this!

  6. #6
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,017

    Default

    Correct; the Wrapper is just a JavaBean; SpEL expressions (in most Spring Integration uses) have the message as the #root object. A message has two properties 'payload' and 'headers'.

    Payload is the main content; headers are metadata; headers are a map.

    In SpEL, we can use JavaBean conventions when acting on objects so things like <transform ... expression="payload.schedule" /> actually invokes

    Code:
    message.getPayload().getSchedule();
    A map in SpEL is referenced using map['key'], so if, on your client side, your command was in a header called 'COMMAND', you could create the wrapper object in SpEL using

    Code:
    expression="new foo.Wrapper(payload, headers['COMMAND'])"
    In my example above, I used a literal "CREATE" instead...

    Code:
    expression="new foo.Wrapper(payload, 'CREATE')"
    Similarly, on the server side, we are simply accessing the wrapper as a JavaBean

    Code:
    <header name="COMMAND" expression="payload.command"/>
    means the message coming out of the header-enricher (and going into the transformer) gets a new header, called "COMMAND", with the value

    Code:
    message.getPayload().getCommand()
    and

    <transformer expression="payload.schedule"/>

    means the "new" payload after the transformer has the value

    Code:
    message.getPayload().getSchedule()
    The "old" payload is simply discarded at this point and you are left with a message with the Schedule as its payload and a header that you subsequently use in a header value router, where you route on header "COMMAND" and have mappings for CREATE, UPDATE etc...

    Hope that helps.
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  7. #7
    Join Date
    Oct 2012
    Posts
    6

    Default

    This looks great! Thanks for your explanation, I appreciate it.

    Will give it all a go when I get back in the office on Monday.

  8. #8
    Join Date
    Oct 2012
    Posts
    6

    Default

    I just wanted to follow up and say I got all this working.

    Thanks Gary!

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •