The year is 2016. As a developer, the majority of the third-party service endpoints I work with on a daily basis follow (or sort of follow) the RESTful API guidelines. However, RESTful APIs were not always the web transfer methodology of choice. There are numerous ways to transmit information over HTTP. Outside of HTTP, systems might also employ FTP or another use of the TCP/IP protocol to transmit information between computers. For managing multiple myriad types of integrations, we have Spring Integration.
To get an overview of Spring Integration and understand what the tool can do, I recommend sections 3.3.1—3.4.7 of the documentation. These sections explain the concept of a message and a channel, and they provide many examples of how and why different configurations of messages and channels might be used.
After that, I would recommend taking a look at this documentation for the Spring Integration Java DSL. If you are already ramping a development team on Java or on Spring, the Java Config for Spring Integration will look and feel more similar to the other code they’re writing than an XML configuration would. It should be noted that not all of Spring Integration’s capabilities have been ported to the Java Config DSL at this time. If you find yourself needing something special that the Java DSL does not cover, the book Spring Integration in Action provides excellent examples of the XML config, as do sections 4 and above in the documentation for Spring Integration.
I found the book Spring Integration in Action extremely helpful for understanding how Spring works, but all of the examples in the book are configured in XML. So I decided to rework an example from one of the book’s introductory chapters using Java Config instead of XML.
Here is an explanation of the business problem:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Configuration | |
@EnableIntegration | |
public class ExampleConfiguration { | |
@Bean | |
IntegrationFlow inboundFlow( | |
ErrorManager errorManager, | |
SeatSelector seatSelector, | |
Prioritizer priority | |
) { | |
return IntegrationFlows | |
.from(Http.inboundGateway("/example/bookmyflight")) | |
.enrichHeaders(headerEnricherSpec -> headerEnricherSpec.header("original_request", request) | |
.header("priority", priority.for(request))) | |
.channel(channel -> channel.priority()) | |
.transform(//build credit card charge request with info from flight booking request) | |
.enrich(e -> e.requestChannel("paymentChannel") | |
.header("paymentInfo", this.paymentInfo) | |
.handle((payload, headers) -> seatSelector.selectSeat(payload)) | |
.publishSubscribeChannel(Executors.newCachedThreadPool(), s -> s | |
.subscribe(subflow -> subflow | |
.<String>handle((payload, headers) -> "You have successfully booked your seat.") | |
.subscribe(subflow -> subflow | |
.enrichHeaders(headerEnricherSpec -> headerEnricherSpec.header("mail_to", payload.getEmailAddress())) | |
.handle(Mail.outboundAdapter("smtp.gmail.com") | |
.credentials(ExampleCiConfig.AUTHENTICATION_EMAIL, ExampleCiConfig.AUTHENTICATION_PASSWORD) | |
.javaMailProperties(mailProperties())) | |
.channel(channel -> channel.queue("outboundEmail")))) | |
.get(); | |
} | |
@Bean | |
public Prioritizer prioritizer() { | |
return new Prioritizer() { | |
public int for(Object request) { | |
//Figures out from the request whether the customer came from the airline's website or from a | |
//comparison website, and assigns a higher priority to the first type of customer | |
} | |
}.get(); | |
} | |
@Bean | |
public ErrorManager errorManager() { | |
return new ErrorManager() { | |
public Object handleError(int statusCode, Object payload) { | |
//Handle different HTTP status codes and, if call successful, return payload | |
} | |
} | |
} | |
@Bean | |
public SeatSelector seatSelector() { | |
return new SeatSelector() { | |
public Object selectSeat(Object payload) { | |
//make call to some external seat selection service | |
} | |
} | |
} | |
Properties mailProperties() { | |
Properties properties = new Properties(); | |
properties.put("mail.smtp.ssl.enable", true); | |
return properties; | |
} | |
} |