Blogs

SpringSource Blog

Using UDP and TCP Adapters in Spring Integration 2.0 M3

Gary Russell

The UDP and TCP channel adapters introduced in Spring Integration 2.0 Milestone 3 provide lightweight communication either between two or more Spring Integration applications, or between a Spring Integration application and some other platform.

Following on from Oleg's blog about the Loan Broker, I use the same example to show how to use the new UDP adapters available with M3. Assume that the CEO of the Loan Broker company has heard complaints from some customers that several banks are quoting outrageous rates. He asks the CIO if he can monitor the quotes coming back from the banks for a while.

Since the Loan Broker app is built using Spring Integration, it is easy to wire-tap the quotes, filter them, and send them off-box to another application using the new ip adapters in M3. This can be done with minimal reconfiguration; the illustration below shows how multicast can be used to send the high-rate quotes to a simple Spring Roo application as well as to Groovy and Perl scripts, or indeed to any platform that supports IP.

First of all, let's explicitly add the aggregation channel and wiretap the quotes…


<int:channel id="quotesAggregationChannel">
    <int:interceptors>
        <int:wire-tap channel="loanSharkDetectorChannel"/>
    </int:interceptors>
</int:channel>

This sends each quote to the loanSharkDetectorChannel (as well as the aggregator).

The next step is to set up the filter and channels to detect the loan sharks…


<int:channel id="loanSharkDetectorChannel" />

<int:filter id="loanSharkFilter"
        input-channel="loanSharkDetectorChannel"
        output-channel="loanSharkChannel"
        expression="payload.rate > 5.2"/>

<int:channel id="loanSharkChannel" />

<int:transformer ref="udpTransformer"
        input-channel="loanSharkChannel"
        output-channel="sharkOutChannel"/>

<int:channel id="sharkOutChannel" />

The filter drops non-loan sharks (those that quote <= 5.2%; the transformer simply converts the LoanQuote to a string containing the bank name and rate, delimited by a comma.

Finally, we add the UDP channel adapter; choosing multicast so we can send the quotes to several destinations…

	<int-ip:outbound-channel-adapter id="udpOut"
		channel="sharkOutChannel"
		protocol="udp"
		host="225.6.7.8"
		multicast="true"
		port="11111"/>

This adapter will multicast the data to port 11111 on multicast address 225.6.7.8.

Now let's take a look at the receiving side. First of all, I created a simple Roo application with the following script…

project --topLevelPackage com.springframework.integration.loanbroker.loanshark
persistence setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY
entity --class ~.domain.LoanShark
field string --fieldName name
field number --type java.lang.Long --fieldName counter
field number --type java.lang.Double --fieldName averageRate
finder add --finderName findLoanSharksByName
controller scaffold --class ~.web.SharkController
logging setup --level DEBUG
dependency add --artifactId org.springframework.integration.ip --groupId org.springframework.integration --version 2.0.0.M3
perform eclipse

(Note, before issuing the perform eclipse, I changed the Spring version in the pom.xml to 3.0.1.RELEASE-A).

Please refer to the Roo documentation to see how these steps generate the initial Roo application.

Finally, I added some Spring Integration to the Roo application.

	<int-ip:inbound-channel-adapter id="udpIn"
		channel="channel"
		multicast="true"
		protocol="udp"
		multicast-address="225.6.7.8"
		port="11111"/>

	<int:channel id="channel" />
	<int:transformer ref="transformer"
		input-channel="channel"
		output-channel="transformedChannel"/>
	<int:channel id="transformedChannel" />
	<int:service-activator
		id="activator"
		input-channel="transformedChannel"
		ref="accumulator" />

	<bean id="accumulator" class="com.springframework.integration.loanbroker.loanshark.biz.Accumulator" />
	<bean id="transformer" class="com.springframework.integration.loanbroker.loanshark.biz.SharkTransformer" />

The channel adapter receives the packets ([bankName],[rate]); the transformer transforms the data to a SharkQuote object which is passed in to the accumulator. This looks up the bank, creates it if necessary, increments the counter and calculates the average rate for that bank.

Here is a screen shot of the Roo application; click for a larger image.


LoanSharkRoo

This Groovy script also sees the packets…

socket = new MulticastSocket(11111)
mcast = InetAddress.getByName("225.6.7.8")
socket.joinGroup(mcast)
buffer = (' ' * 1024) as byte[]
while(true) {
    incoming = new DatagramPacket(buffer, buffer.length)
    socket.receive(incoming)
    s = new String(incoming.data, 0, incoming.length)
    println ("**Shark** " + s)
}

… as does this Perl script…

#!/usr/bin/perl -w
use strict;
use IO::Socket::Multicast;
my $socket = IO::Socket::Multicast->new(LocalPort=>11111, ReuseAddr=>1)
  or die "Can't start UDP server: $@";
$socket->mcast_add('225.6.7.8');
my ($datagram,$flags);
while ($socket->recv($datagram,1024,$flags)) {
	print "**Shark** $datagram\n";
}
$socket->close();

You may have to install IO::Socket::Multicast for this script to work.

Either of the above scripts creates this output…

perl

Conclusion

This is just a brief introduction to the new IP adapters. The code (updates to Loan Broker as well as the Loan Shark Roo application) is available in svn.

https://src.springsource.org/svn/spring-integration/trunk/spring-integration-samples/loan-broker/

https://src.springsource.org/svn/spring-integration/trunk/spring-integration-samples/loanshark/

TCP adapters are also provided in M3; read about them here.

We are considering creating TCP/IP gateways for bidirectional communication. If this is something you need, vote for the JIRA issue.

Similar Posts

Share this Post
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • DZone
  • LinkedIn
  • Slashdot
  • Technorati
  • Twitter
 

5 responses


  1. The power of Spring Integration continues to amaze me! So many possibilities. Thanks for sharing Gary!


  2. Thanks for the blog post :) Roo rocks.


  3. Any example code to read from the COM port? For example, I am trying to write a Spring Integration Application that reads the data from a device attached to COM/USB port and tries to setup a Message Channel to other application that subscribe to it.

    Thank you

    SanS


  4. We don't currently have com port adapters for Spring Integration.

    Feel free to enter a new feature JIRA here…

    https://jira.springsource.org/browse/INT

    In the mean time, you could roll your own com code, using the Java Communications API…

    http://www.oracle.com/technetwork/java/index-jsp-141752.html

    …receive a message and send to an SI flow using a gateway.

    If you wish to discuss further, please start a topic here…

    http://forum.springsource.org/forumdisplay.php?42-Integration

    …rather than using this blog.

    Thanks.


  5. Thanks very much, Gary!
    I could make the required changes using this example.

2 trackbacks

Leave a Reply