6. A Better Solution: Spring Integration
• Spring Integration Brings EAI
To Your Application
• not the other way ‘round
• Provides the best support for
“Enterprise Integration
Patterns”
• patterns are built right into the
API
• Heavy Emphasis on
“channels”
• other solutions omit this key
concept
6
7. Messaging
• Integrates two different systems
• Different parties need to share the same data contract
• Not the same service contract
• Fault tolerant, since requests are enqueued and delivered as possible
• AMQP, JMS provide powerful, robust options
7
9. Data Processing with Spring: Integration
• Messaging works by decoupling systems
• The Spring messaging machinery lets you react to messages,
declaratively
• Spring Integration takes this approach to the next level
?
Events
?
9
10. Data Processing with Spring: Messaging
• JMS
• Standard in the Java space
• Lots of open source options
• Provided with Java EE application servers
• Spring JMS
10
11. Data Processing with Spring: Messaging
Java producers Message broker Java consumers
C
P queue
C
P queue
C
11
12. JMS
• Sending JMS Messages
• Inject an instance of Spring's JmsTemplate.
• Provide the JMS ConnectionFactory in the JmsTemplate bean
definition.
12
13. JMS
@Component public class MessageSender {
@Autowired private JmsTemplate jmsTemplate;
public void send(String message) {
this.jmsTemplate.convertAndSend("example.queue", message);
}
}
@Bean public ConnnectionFactory cf (){
return new CachingConnectionFactory(...);
}
@Bean public JmsTemplate template(){
return new JmsTemplate(this.cf()) ;
}
13
14. Data Processing with Spring: Messaging
• AMQP
• Real standard
• A product of the the companies with the most mission critical
requirements
• Spring AMQP
1
15. Data Processing with Spring: Messaging
AMQP producers exchanges Message broker AMQP consumers
C
P X queue
C
P X queue
C
1
16. AMQP
• Sending AMQP Messages
• Use AmqpTemplate instead of JmsTemplate (accepts exchange and
routingKey).
• Nothing changes on the listener side (just a POJO).
@Component public class MessageSender {
@Autowired
private AmqpTemplate amqpTemplate;
public void send(String message) {
this.amqpTemplate.convertAndSend(
"myExchange", "some.routing.key", message);
}
}
16
17. HTTP
• HTTP Messaging (Request/Reply)
• Use RestTemplate, passing URI to methods based on HTTP methods
• Configure HttpMessageConverters if out-of-the-box support is
insufficient
17
18. HTTP
public class HttpClient {
private final String uri = “http://localhost/demo/{name}”;
private final RestTemplate template = new RestTemplate();
public String getResource(String name) {
this.template.getForObject(uri, String.class, name);
}
public URI postResource(String name, Object resource) {
this.template.postForLocation(uri, resource, name);
}
}
18
19. Mail
• Sending Mail Messages
• Create a SimpleMailMessage instance (or JavaMail MimeMessage).
• Use MailSender (or JavaMailSender) configured with host/user/
password, etc.
@Component public class MailClient {
@Autowired private MailSender mailSender;
public void send(String subject, String to, String text) {
SimpleMailMessage message = new SimpleMailMessage();
message.setSubject(subject);
message.setTo(to);
message.setText(text);
this.mailSender.send(message);
}
}
19
21. Pipes and Filters
• Messaging
• Payload can be any object
• Header values are stored in a Map
21
22. Pipes and Filters
• Message and Headers
public interface Message<T> {
MessageHeaders getHeaders();
T getPayload();
}
Message<String> m1 = MessageBuilder.withPayload(“foo”)
.setHeader(“itemId”, 123).build();
Message<String> m2 = MessageBuilder.fromMessage(m1)
.setHeader(“itemId”, 456).build();
MessageHeaders headers = message.getHeaders();
long timestamp = headers.getTimestamp();
String value = headers.get(“someKey”, String.class);
22
23. Pipes and Filters
• Message channel
• Decouples Producers from Consumers
• Provides extension point for interceptors
• May be Point-to-Point
• Or Publish/Subscribe
23
25. Pipes and Filters
• Sending Messages
public interface MessageChannel {
boolean send(Message<?> message);
boolean send(Message<?> message, long timeout);
}
MessagingTemplate template = new MessagingTemplate();
template.send(someChannel, message);
template.send(“fooChannel”, message);
template.convertAndSend(someChannel, “hello”);
template.convertAndSend(“fooChannel”, someObject);
template.setSendTimeout(5000);
template.setDefaultChannel(someChannel);
template.convertAndSend(someObject);
25
26. Pipes and Filters
• Receiving Messages
• Inversion of Control
• Endpoints delegate to Spring-managed objects
• Framework handles message reception and method invocation (including
conversion)
• Similar but more abstract than Spring JMS
• Clean separation of Code and Configuration
<service-activator input-channel="requests"
ref="loanBroker" method="processRequest"
output-channel="quotes"/>
@Component public class LoanBroaker {
public Message<Quote> processRequest( Message<Loan> loan) {
}
}
26
28. Pipes and Filters
• Message Endpoint
• Producers send Messages to a MessageChannel
• Depending on their type, MessageChannels may have
PollingConsumers
• Or Event-Driven Consumers
28
30. Message Endpoint Types
• Transformer
• Convert payload or modify headers
• Filter
• Discard messages based on boolean evaluation
• Router
• Determine next channel based on content
• Splitter
• Generate multiple messages from one
• Aggregator
• Assemble a single message from multiple
30
31. Filtering and Routing
• Filter returns a boolean
• Router returns a channel name (or map key)
• Other routers included out of the box:
• recipient-list
• payload-type <filter input-channel="customers"
ref="customerRegistry"
• header-value,
method="isVip"
• xpath, ... output-channel="vips"
discard-channel="nonVips"/>
<router input-channel="customers"
ref="customerRegistry"
method="getStatus">
<mapping value="1" channel="platinum"/>
</router>
31
33. Splitting and Aggregating
• Splitter returns a Collection or Array
• Aggregator accepts a Collection or Array
<splitter input-channel="orders"
ref="orderRepository"
method="getLineItems"
output-channel="lineItems"/>
• Default Splitter and Aggregator require no ref/method
• Aggregator also has ReleaseStrategy and CorrelationStrategy
<aggregator input-channel="processedItems"
ref="orderRepository"
method="generateConfirmation"
output-channel="confirmations"/>
33
34. Annotation Support
• Alternative to XML
@ServiceActivator(inputChannel=“accounts”)
public void createAccount(Account account) {…}
@Filter(inputChannel=“customers”, outputChannel=“vips”)
public boolean isVip(Customer customer) {…}
@Splitter(inputChannel=“orders”, outputChannel=“lineItems”)
public List<LineItem> getLineItems(Order order) {…}
34
35. Expression Language Support
• Alternative option for ref/method in endpoints
<filter input-channel="customers"
expression="payload.vip"
output-channel="vips"
discard-channel="nonVips"/>
• Mapping between Messages and Methods
public void createAccount(
@Payload("firstName") String firstName,
@Payload("lastName") String lastName,
@Header("userInfo.account.id") String accountId) {
…
}
35
42. Major Themes
• Spring 3.0 support
• JDK 5 Support
• New Message Stores
• New Adapters
• Misc.
42
43. Spring 3.0
• ConversionService
• Spring Integration takes advantage of a configured conversion service
whenever it wants to perform certain conversions, from a certain
primitives to complex objects in message parameters, for example.
• default Spring Integration conversion service bean ID:
integrationConversionService
• must implement org.springframework.core.convert.converter.Converter
<int:converter>
<bean class="….MyConverterImplementation" />
</int:converter>
43
44. Spring 3.0
• Spring Expression Language
• through XML or Java
<int:recipient-list-router id="customRouter"
input-channel="routingChannel">
<int:recipient channel="channel1"
selector-expression="payload.equals('foo')"/>
<int:recipient channel="channel2"
selector-expression="headers.contains('bar')"/>
</int:recipient-list-router>
<int:router input-channel="inChannel"
expression="payload + 'Channel'"/>
<filter input-channel="input"
expression="payload.equals('nonsense')"/>
44
45. Spring 3.0
• Spring Expression Language
• through XML or Java
<int:transformer input-channel="inChannel"
output-channel="outChannel"
expression="payload.toUpperCase() + '- [' +
T(java.lang.System).currentTimeMillis() + ']'" />
<filter input-channel="input" expression="payload.matches(
#{filterPatterns.nonsensePattern}
)" />
45
46. Spring Integration 2.0
• New Adapters
• Drastically improved file system support
• JDBC inbound and outbound adapters
• RSS / ATOM
• Twitter
• XMPP
• TCP/
• Misc
• new JMS channel
• revised HTTP support
46