{"id":44580,"date":"2015-09-29T22:00:57","date_gmt":"2015-09-29T19:00:57","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=44580"},"modified":"2023-12-13T11:56:52","modified_gmt":"2023-12-13T09:56:52","slug":"spring-integration-full-example","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html","title":{"rendered":"Spring Integration Full Example"},"content":{"rendered":"<p><em>This article is part of our Academy Course titled <a href=\"http:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-for-eai\/\">Spring Integration for EAI<\/a>.<\/p>\n<p>In this course, you are introduced to Enterprise Application Integration patterns and how Spring Integration addresses them. Next, you delve into the fundamentals of Spring Integration, like channels, transformers and adapters. Check it out <a href=\"http:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-for-eai\/\">here<\/a>!<\/em><\/p>\n<div class=\"toc\">\n<h4>Table Of Contents<\/h4>\n<dl>\n<dt><a href=\"#introduction\">1. Introduction<\/a><\/dt>\n<dt><a href=\"#overview\">2. Overview of the system<\/a><\/dt>\n<dt><a href=\"#the_egyptian\">3. The Egyptian Theater service<\/a><\/dt>\n<dt><a href=\"#the_pantages\">4. The Pantages Theater service<\/a><\/dt>\n<dt><a href=\"#the_user_interface\">5. The user interface<\/a><\/dt>\n<dt><a href=\"#logging_each_user_request\">6. Logging each user request<\/a><\/dt>\n<dt><a href=\"#discarding_invalid_entries\">7. Discarding invalid entries<\/a><\/dt>\n<dt><a href=\"#theater\">8. Choosing which theater to request<\/a><\/dt>\n<dt><a href=\"#requesting_the_egyptian\">9. Requesting the Egyptian Theater<\/a><\/dt>\n<dt><a href=\"#requesting_the_pantages_theater\">10. Requesting the Pantages Theater<\/a><\/dt>\n<dt><a href=\"#handling_errors\">11. Handling errors<\/a><\/dt>\n<dd>\n<dl>\n<dt><a href=\"#storing_the_message\">11.1. Storing the message to the database<\/a><\/dt>\n<dt><a href=\"#sending_an_email\">11.2. Sending an email to the person in charge<\/a><\/dt>\n<\/dl>\n<\/dd>\n<dt><a href=\"#shutting_down\">12. Shutting down the application<\/a><\/dt>\n<dt><a href=\"#taking_a_glance\">13. Taking a glance at the complete flow<\/a><\/dt>\n<dt><a href=\"#technology_versions\">14. Technology versions<\/a><\/dt>\n<\/dl>\n<\/div>\n<h2><a name=\"introduction\"><\/a>1. Introduction<\/h2>\n<p>This tutorial will go through a complete example of an application that uses several of the components provided by Spring Integration in order to provide a service to its users. This service consists of a system prompting the user to choose among different theaters. After his selection, the system will make a request to the external system of the chosen theater and return the list of its available films. Each cinema offers its service through a different API; we will see this in the sections that explain each external system (sections three and four).<\/p>\n<h2><a name=\"overview\"><\/a>2. Overview of the system<\/h2>\n<p>The following activity diagram shows a high level view of the system.<\/p>\n<p><figure id=\"attachment_4396\" aria-describedby=\"caption-attachment-4396\" style=\"width: 1024px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/09\/ch5_pic1.png\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/09\/ch5_pic1-1024x461.png\" alt=\"Figure 1\" width=\"1024\" height=\"461\" class=\"size-large wp-image-4396\" \/><\/a><figcaption id=\"caption-attachment-4396\" class=\"wp-caption-text\">Figure 1<\/figcaption><\/figure><\/p>\n<ul>\n<li><strong>User interface<\/strong>: On the left side of the diagram, we have the start of the flow; the request user entry. This entry request shown by the system along with the system responses to the user, are both examples of integration with streams.<\/li>\n<li><strong>Web service invocations<\/strong>: Depending on the selection made by the user, the system will retrieve the films list from a different external system. The Egyptian Theater exposes its service through HTTP, while the Pantages Theater exposes its service through SOAP.<\/li>\n<li><strong>Error handling<\/strong>: If there is an error during the flow, maybe because of an unexpected exception or because a web service is not available, the system will send information to another two external systems: a noSQL database (<a href=\"https:\/\/www.mongodb.org\/\">MongoDB<\/a>) and an email address.<\/li>\n<\/ul>\n<p>Next sections will enter more deeply in each of the parts of this system.<\/p>\n<h2><a name=\"the_egyptian\"><\/a>3. The Egyptian Theater service<\/h2>\n<p>The Egyptian Theater system exposes his service through HTTP. In this section we are going to take a quick look at the application. It is a Spring 4 MVC application that contains a RESTful web service.<\/p>\n<p>The controller will serve requests to retrieve all available films that are being showed in the theater:<\/p>\n<pre class=\"brush:java\">@RestController\n@RequestMapping(value=\"\/films\")\npublic class FilmController {\n    FilmService filmService;\n\n    @Autowired\n    public FilmController(FilmService service) {\n        this.filmService = service;\n    }\n\n    @RequestMapping(method=RequestMethod.GET)\n    public Film[] getFilms() {\n        return filmService.getFilms();\n    }\n}<\/pre>\n<p>The API is simple, and for this example the service will return some dummy values, since the focus of this section is to just provide a little bit more of detail of what external system is being called:<\/p>\n<pre class=\"brush:java\">@Service(\"filmService\")\npublic class FilmServiceImpl implements FilmService {\n\n    @Override\n    public Film[] getFilms() {\n        Film film1 = new Film(1, \"Bladerunner\", \"10am\");\n        Film film2 = new Film(2, \"Gran Torino\", \"12pm\");\n\n        return new Film[]{film1, film2};\n    }\n}<\/pre>\n<p>The Spring configuration is based on annotations:<\/p>\n<pre class=\"brush:xml\">&lt;!-- Detects annotations like @Component, @Service, @Controller, @Repository, @Configuration --&gt;\n&lt;context:component-scan base-package=\"xpadro.spring.mvc.films.controller,xpadro.spring.mvc.films.service\"\/&gt;\n\n&lt;!-- Detects MVC annotations like @RequestMapping --&gt;\n&lt;mvc:annotation-driven\/&gt;<\/pre>\n<p>The web.xml file configures the web application:<\/p>\n<pre class=\"brush:xml\">&lt;!-- Root context configuration --&gt;\n&lt;context-param&gt;\n    &lt;param-name&gt;contextConfigLocation&lt;\/param-name&gt;\n    &lt;param-value&gt;classpath:xpadro\/spring\/mvc\/config\/root-context.xml&lt;\/param-value&gt;\n&lt;\/context-param&gt;\n\n&lt;!-- Loads Spring root context, which will be the parent context --&gt;\n&lt;listener&gt;\n    &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;\/listener-class&gt;\n&lt;\/listener&gt;\n\n&lt;!-- Spring servlet --&gt;\n&lt;servlet&gt;\n    &lt;servlet-name&gt;springServlet&lt;\/servlet-name&gt;\n    &lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;\/servlet-class&gt;\n    &lt;init-param&gt;\n        &lt;param-name&gt;contextConfigLocation&lt;\/param-name&gt;\n        &lt;param-value&gt;classpath:xpadro\/spring\/mvc\/config\/app-context.xml&lt;\/param-value&gt;\n    &lt;\/init-param&gt;\n&lt;\/servlet&gt;\n&lt;servlet-mapping&gt;\n    &lt;servlet-name&gt;springServlet&lt;\/servlet-name&gt;\n    &lt;url-pattern&gt;\/spring\/*&lt;\/url-pattern&gt;\n&lt;\/servlet-mapping&gt;<\/pre>\n<p>So, the system will serve requests sent to <code>http:\/\/localhost:8080\/rest-films\/spring\/films<\/code>, with <code>rest-films<\/code> being the context path of the application.<\/p>\n<h2><a name=\"the_pantages\"><\/a>4. The Pantages Theater service<\/h2>\n<p>The Pantages Theater service exposes its service through SOAP. Like the Egyptian Theater, it consists in a web application but in this case, it is implemented with Spring <a href=\"http:\/\/projects.spring.io\/spring-ws\/\">Web Services<\/a>.<\/p>\n<p>The endpoint will serve <code>filmRequest<\/code> requests with the namespace <code>http:\/\/www.xpadro.spring.samples.com\/films<\/code>. The response is built from the result received from a film service:<\/p>\n<pre class=\"brush:java\">@Endpoint\npublic class FilmEndpoint {\n    @Autowired\n    private FilmService filmService;\n    \n    @PayloadRoot(localPart=\"filmRequest\", namespace=\"http:\/\/www.xpadro.spring.samples.com\/films\")\n    public @ResponsePayload FilmResponse getFilms() {\n        return buildResponse();\n    }\n    \n    private FilmResponse buildResponse() {\n        FilmResponse response = new FilmResponse();\n        \n        for (Film film : filmService.getFilms()) {\n            response.getFilm().add(film);\n        }\n        \n        return response;\n    }\n}<\/pre>\n<p>The film service is also a dummy service that will return some default values:<\/p>\n<pre class=\"brush:java\">@Service\npublic class FilmServiceImpl implements FilmService {\n\n    @Override\n    public List&lt;Film&gt; getFilms() {\n        List&lt;Film&gt; films = new ArrayList&lt;&gt;();\n        \n        Film film = new Film();\n        film.setId(new BigInteger((\"1\")));\n        film.setName(\"The Good, the Bad and the Uggly\");\n        film.setShowtime(\"6pm\");\n        films.add(film);\n        \n        film = new Film();\n        film.setId(new BigInteger((\"2\")));\n        film.setName(\"The Empire strikes back\");\n        film.setShowtime(\"8pm\");\n        films.add(film);\n        \n        return films;\n    }\n}<\/pre>\n<p>The Spring configuration is shown below:<\/p>\n<pre class=\"brush:xml\">&lt;!-- Detects @Endpoint since it is a specialization of @Component --&gt;\n&lt;context:component-scan base-package=\"xpadro.spring.ws\"\/&gt;\n\n&lt;!-- detects @PayloadRoot --&gt;\n&lt;ws:annotation-driven\/&gt;\n\n&lt;ws:dynamic-wsdl id=\"filmDefinition\" portTypeName=\"Films\" \n                 locationUri=\"http:\/\/localhost:8080\/ws-films\"&gt;\n    &lt;ws:xsd location=\"\/WEB-INF\/schemas\/xsd\/film-service.xsd\"\/&gt;\n&lt;\/ws:dynamic-wsdl&gt;<\/pre>\n<p>Finally, the <code>web.xml<\/code> file:<\/p>\n<pre class=\"brush:xml\">&lt;context-param&gt;\n    &lt;param-name&gt;contextConfigLocation&lt;\/param-name&gt;\n    &lt;param-value&gt;classpath:xpadro\/spring\/ws\/config\/root-config.xml&lt;\/param-value&gt;\n&lt;\/context-param&gt;\n\n&lt;listener&gt;\n    &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;\/listener-class&gt;\n&lt;\/listener&gt;\n\n&lt;servlet&gt;\n    &lt;servlet-name&gt;Films Servlet&lt;\/servlet-name&gt;\n    &lt;servlet-class&gt;org.springframework.ws.transport.http.MessageDispatcherServlet&lt;\/servlet-class&gt;\n    &lt;init-param&gt;\n      &lt;param-name&gt;contextConfigLocation&lt;\/param-name&gt;\n      &lt;param-value&gt;classpath:xpadro\/spring\/ws\/config\/servlet-config.xml&lt;\/param-value&gt;\n    &lt;\/init-param&gt;\n    &lt;load-on-startup&gt;1&lt;\/load-on-startup&gt;\n&lt;\/servlet&gt;\n\n&lt;servlet-mapping&gt;\n    &lt;servlet-name&gt;Films Servlet&lt;\/servlet-name&gt;\n    &lt;url-pattern&gt;\/films\/*&lt;\/url-pattern&gt;\n&lt;\/servlet-mapping&gt;<\/pre>\n<p>Based on this configuration, the Pantages Theater application will serve requests sent to <code>http:\/\/localhost:8080\/ws-films\/films<\/code>, where <code>ws-films<\/code> is the context path of the application.<\/p>\n<h2><a name=\"the_user_interface\"><\/a>5. The user interface<\/h2>\n<p>Once we have seen what the external systems are that will communicate with our Spring Integration application, let\u2019s move on to see how this application is built.<\/p>\n<p>The standalone application starts with a main method that bootstraps the Spring context, which contains all our integration components. Next, it prompts the user to enter his selection:<\/p>\n<pre class=\"brush:java\">public class TheaterApp {\n    private static Logger logger = LoggerFactory.getLogger(\"mainLogger\");\n    static AbstractApplicationContext context;\n\n    public static void main(String[] args) {\n        \n        context = new ClassPathXmlApplicationContext(\"classpath:xpadro\/spring\/integration\/config\/int-config.xml\");\n        context.registerShutdownHook();\n        \n        logger.info(\"\\\\nSelect your option (1-Egyptian Theater \/ 2-Pantages Theater \/ 0-quit):\\\\n\");\n    }\n    \n    public static void shutdown() {\n        logger.info(\"Shutting down...\");\n        context.close();\n    }\n}<\/pre>\n<p>The application also implements a shutdown method that will be invoked by the user. We will see this in more detail in a later section.<\/p>\n<p>Ok, now how will the user selection get into the messaging system? This is where the integration with <a href=\"http:\/\/docs.spring.io\/spring-integration\/docs\/3.0.2.RELEASE\/reference\/html\/stream.html#stream-reading\">streams<\/a> comes into play. The system entry to the messaging system is implemented with an inbound channel adapter that will read from stdin (<code>System.in<\/code>).<\/p>\n<pre class=\"brush:xml\">&lt;!-- System entry --&gt;\n&lt;int-stream:stdin-channel-adapter id=\"consoleIn\" channel=\"systemEntry\"&gt;\n    &lt;int:poller fixed-delay=\"1000\" max-messages-per-poll=\"1\" \/&gt;\n&lt;\/int-stream:stdin-channel-adapter&gt;<\/pre>\n<p>By using a poller, the inbound channel adapter will try to read from System.in each second and place the result into the <code>systemEntry<\/code> channel. <\/p>\n<p>Now, we received a Spring Integration Message with the user entry as its payload. We can use our endpoints to transform the data and send it to the required system. Example: The console will prompt the user to choose among the different theaters: <\/p>\n<pre class=\"brush:bash\">2014-04-11 13:04:32,959|AbstractEndpoint|started org.springframework.integration.config.ConsumerEndpointFactoryBean#7\n\nSelect your option (1-Egyptian Theater \/ 2-Pantages Theater \/ 0-quit):<\/pre>\n<h2><a name=\"logging_each_user_request\"><\/a>6. Logging each user request<\/h2>\n<p>The first thing the system does is logging the user selection. This is done by using a <a href=\"http:\/\/www.eaipatterns.com\/WireTap.html\">wire tap<\/a>. This wire tap is an implementation of an interceptor that will intercept messages that travel across the channel, in our case, the <code>systemEntry<\/code> channel. It will not alter the flow; the message will continue to its destination, but the wire tap will also send it to another channel, usually for monitoring.<\/p>\n<p>In our application, the message is also sent to a logging channel adapter.<\/p>\n<pre class=\"brush:xml\">&lt;int:channel id=\"systemEntry\"&gt;\n    &lt;int:interceptors&gt;\n        &lt;int:wire-tap channel=\"requestLoggingChannel\"\/&gt;\n    &lt;\/int:interceptors&gt;\n&lt;\/int:channel&gt;\n\n&lt;int:logging-channel-adapter id=\"requestLoggingChannel\" \n    expression=\"'User selection: '.concat(payload)\" level=\"INFO\"\/&gt;<\/pre>\n<p>The logging channel adapter is implemented by the <code><a href=\"http:\/\/docs.spring.io\/spring-integration\/docs\/3.0.2.RELEASE\/api\/org\/springframework\/integration\/config\/xml\/LoggingChannelAdapterParser.html\">LoggingChannelAdapterParser<\/a><\/code>. It basically creates a <code><a href=\"http:\/\/docs.spring.io\/spring-integration\/docs\/3.0.2.RELEASE\/api\/org\/springframework\/integration\/handler\/LoggingHandler.html\">LoggingHandler<\/a><\/code> that will log the payload of the message using the Apache Commons Logging library. If you want to log the full message instead of only its payload, you can add the <code>log-full-message<\/code> property to the logging channel adapter.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p>Example: The log shows the selection made by the user<\/p>\n<pre class=\"brush:bash\">Select your option (1-Egyptian Theater \/ 2-Pantages Theater \/ 0-quit):\n\n1\n2014-04-11 13:06:07,110|LoggingHandler|User selection: 1<\/pre>\n<h2><a name=\"discarding_invalid_entries\"><\/a>7. Discarding invalid entries<\/h2>\n<p>Taking a glance at the user prompt, we see that the system accepts three valid entries:<\/p>\n<pre class=\"brush:bash\">logger.info(\"\\\\nSelect your option (1-Egyptian Theater \/ 2-Pantages Theater \/ 0-quit):\\\\n\")<\/pre>\n<p>The treatment for invalid entries is very simple; the system will filter invalid entries, preventing them to move forward through the flow. These discarded messages will then be sent to a <code>discards<\/code> channel.<\/p>\n<p>Subscribed to the <code>invalidEntries<\/code> discards channel, there is another stream channel adapter, in this case, an outbound adapter:<\/p>\n<pre class=\"brush:xml\">&lt;int:filter input-channel=\"systemEntry\" output-channel=\"validEntriesChannel\" ref=\"entryFilter\" \n    discard-channel=\"invalidEntries\"\/&gt;\n\n&lt;!-- Invalid entries (show on console) --&gt;\n&lt;int:chain input-channel=\"invalidEntries\"&gt;\n    &lt;int:transformer ref=\"discardsTransformer\"\/&gt;\n    &lt;int-stream:stdout-channel-adapter id=\"consoleOut\" append-newline=\"true\" \/&gt;\n&lt;\/int:chain&gt;<\/pre>\n<p>The function of this adapter is to write to stdout (<code>System.out<\/code>), so the user will receive that he entered an invalid request on the console.<\/p>\n<p>One thing to keep in mind is that we didn\u2019t create the <code>invalidEntries<\/code> channel. The adapter will be connected to the filter through an anonymous temporary direct channel.<\/p>\n<p>Example: The console shows the user entered an invalid selection.<\/p>\n<pre class=\"brush:bash\">Select your option (1-Egyptian Theater \/ 2-Pantages Theater \/ 0-quit):\n\n8\n2014-04-11 13:07:41,808|LoggingHandler|User selection: 8\nInvalid entry: 8<\/pre>\n<h2><a name=\"theater\"><\/a>8. Choosing which theater to request<\/h2>\n<p>Valid entries that successfully pass the previous filter will be sent to a router:<\/p>\n<pre class=\"brush:xml\">&lt;!-- Valid entries (continue processing) --&gt;\n&lt;int:channel id=\"validEntriesChannel\" \/&gt;\n&lt;int:router input-channel=\"validEntriesChannel\" ref=\"cinemaRedirector\"\/&gt;<\/pre>\n<p>This router is responsible of deciding which external system is the one the user is requiring information from. It will also detect when the user wants to shut down the application:<\/p>\n<pre class=\"brush:java\">@Component(\"cinemaRedirector\")\npublic class CinemaRedirector {\n    private static final String CINEMA_EGYPTIAN_CHANNEL = \"egyptianRequestChannel\";\n    private static final String CINEMA_PANTAGES_CHANNEL = \"pantagesRequestChannel\";\n    private static final String QUIT_REQUEST_CHANNEL = \"quitRequestChannel\";\n\n    @Router\n    public String redirectMessage(Message&lt;String&gt; msg) {\n        String payload = msg.getPayload();\n        \n        if (\"1\".equals(payload)) {\n            return CINEMA_EGYPTIAN_CHANNEL;\n        }\n        else if (\"2\".equals(payload)) {\n            return CINEMA_PANTAGES_CHANNEL;\n        }\n        \n        return QUIT_REQUEST_CHANNEL;\n    }\n}<\/pre>\n<p>So, here the flow splits in three different channels, a request to each theater and a request to finish the flow.<\/p>\n<h2><a name=\"requesting_the_egyptian\"><\/a>9. Requesting the Egyptian Theater<\/h2>\n<p>To communicate with the Egyptian Theater system, we need to send an HTTP request. We accomplish this by using an HTTP outbound gateway.<\/p>\n<pre class=\"brush:xml\">&lt;int-http:outbound-gateway url=\"http:\/\/localhost:8080\/rest-films\/spring\/films\" \n        expected-response-type=\"java.lang.String\" http-method=\"GET\" charset=\"UTF-8\"\/&gt;<\/pre>\n<p>This gateway is configured with several properties:<\/p>\n<ul>\n<li><code>expected-response-type<\/code>: The return type returned by the web service will be a String containing the JSON with the films listing.<\/li>\n<li><code>http-method<\/code>: We are making a GET request.<\/li>\n<li><code>charset<\/code>: the charset for converting the payload to bytes.<\/li>\n<\/ul>\n<p>Once the response is received, we will use a transformer to convert the returned JSON to a Java Object. In our case, we will convert the response to a <code>Film<\/code> array:<\/p>\n<pre class=\"brush:xml\">&lt;int:json-to-object-transformer type=\"xpadro.spring.integration.model.Film[]\"\/&gt;<\/pre>\n<p>Next, a service activator will go through the array and build a String more appropriate to the user.<\/p>\n<pre class=\"brush:xml\">&lt;int:service-activator ref=\"restResponseHandler\"\/&gt;<\/pre>\n<p>The implementation is shown below:<\/p>\n<pre class=\"brush:java\">@Component(\"restResponseHandler\")\npublic class RestResponseHandler {\n    private static final String NEW_LINE = \"\\\\n\";\n\n    @ServiceActivator\n    public String handle(Message&lt;Film[]&gt; msg) {\n        Film[] films = msg.getPayload();\n        \n        StringBuilder response = new StringBuilder(NEW_LINE);\n        if (films.length &gt; 0) {\n            response.append(\"Returned films:\" + NEW_LINE);\n        }\n        else {\n            response.append(\"No films returned\" + NEW_LINE);\n        }\n        \n        for (Film f:films) {\n            response.append(f.getName()).append(NEW_LINE);\n        }\n        \n        return response.toString();\n    }\n}<\/pre>\n<p>Finally, we will show the response to the user by printing it on the console. We are using the same channel adapter as the one used to show the user its invalid entries. The adapter will write to System.out:<\/p>\n<pre class=\"brush:xml\">&lt;int-stream:stdout-channel-adapter id=\"consoleOut\" append-newline=\"true\" \/&gt;<\/pre>\n<p>The next code snippet shows the complete request. Since I did not want to create message channels for each interaction between these endpoints, I used a message handler chain. This type of endpoint simplifies the required XML configuration when we have several endpoints in a sequence. By using a message handler chain, all its endpoints are connected through anonymous direct channels.<\/p>\n<pre class=\"brush:xml\">&lt;!-- Egyptian Theater request --&gt;\n&lt;int:chain input-channel=\"egyptianRequestChannel\"&gt;\n    &lt;int-http:outbound-gateway url=\"http:\/\/localhost:8080\/rest-films\/spring\/films\" \n        expected-response-type=\"java.lang.String\" http-method=\"GET\" charset=\"UTF-8\"\/&gt;\n    &lt;int:json-to-object-transformer type=\"xpadro.spring.integration.model.Film[]\"\/&gt;\n    &lt;int:service-activator ref=\"restResponseHandler\"\/&gt;\n    &lt;int-stream:stdout-channel-adapter id=\"consoleOut\" append-newline=\"true\" \/&gt;\n&lt;\/int:chain&gt;<\/pre>\n<p>Example: The Egyptian Theater film listing is shown to the user.<\/p>\n<pre class=\"brush:bash\">1\n2014-04-11 14:26:20,981|LoggingHandler|User selection: 1\n\nReturned films:\nBladerunner\nGran Torino<\/pre>\n<h2><a name=\"requesting_the_pantages_theater\"><\/a>10. Requesting the Pantages Theater<\/h2>\n<p>We are going to need a web service gateway to interact with the Pantages Theater system, but first, we have to build a request object of the type <code>filmRequest<\/code> in order to be served by the Egyptian web service endpoint.<\/p>\n<p>We are using a transformer to change the message to a film web service request:<\/p>\n<pre class=\"brush:xml\">&lt;int:transformer ref=\"soapRequestTransformer\"\/&gt;<\/pre>\n<p>The implementation:<\/p>\n<pre class=\"brush:java\">@Component(\"soapRequestTransformer\")\npublic class SoapRequestTransformer {\n\n    @Transformer\n    public Message&lt;?&gt; createRequestMessage(Message&lt;String&gt; msg) {\n        return MessageBuilder.withPayload(new FilmRequest()).copyHeadersIfAbsent(msg.getHeaders()).build();\n    }\n}<\/pre>\n<p>We got the request object so we can now invoke the web service using a web service gateway:<\/p>\n<pre class=\"brush:xml\">&lt;int-ws:outbound-gateway uri=\"http:\/\/localhost:8080\/ws-films\/films\" \n        marshaller=\"marshaller\" unmarshaller=\"marshaller\"\/&gt;<\/pre>\n<p>As seen in a previous tutorial, a marshaller will be required to convert the request and response. For this task we are going to use the oxm namespace:<\/p>\n<pre class=\"brush:xml\">&lt;oxm:jaxb2-marshaller id=\"marshaller\" contextPath=\"xpadro.spring.integration.ws.types\" \/&gt;<\/pre>\n<p>When we receive the web service response it will be in the form of a FilmResponse. The next endpoint in the sequence will adapt the response and return a String in order to be shown to the user in the next phase:<\/p>\n<pre class=\"brush:xml\">&lt;int:service-activator ref=\"soapResponseHandler\"\/&gt;<\/pre>\n<p>The implementation:<\/p>\n<pre class=\"brush:java\">@Component(\"soapResponseHandler\")\npublic class SoapResponseHandler {\n    private static final String NEW_LINE = \"\\\\n\";\n\n    @ServiceActivator\n    public String handle(Message&lt;FilmResponse&gt; msg) {\n        FilmResponse response = msg.getPayload();\n        \n        StringBuilder resp = new StringBuilder(NEW_LINE);\n        if (response.getFilm().size() &gt; 0) {\n            resp.append(\"Returned films:\" + NEW_LINE);\n        }\n        else {\n            resp.append(\"No films returned\" + NEW_LINE);\n        }\n        \n        for (Film f : response.getFilm()) {\n            resp.append(f.getName()).append(NEW_LINE);\n        }\n        \n        return resp.toString();\n    }\n}<\/pre>\n<p>Like in the Egyptian request, this request also ends with another stream outbound channel adapter:<\/p>\n<pre class=\"brush:xml\">&lt;int-stream:stdout-channel-adapter id=\"consoleOut\" append-newline=\"true\" \/&gt;<\/pre>\n<p>Since we have another sequence of endpoints, we use a message handler chain to minimize the quantity of configuration required:<\/p>\n<pre class=\"brush:xml\">&lt;!-- Pantages Theater request --&gt;\n&lt;int:chain input-channel=\"pantagesRequestChannel\"&gt;\n    &lt;int:transformer ref=\"soapRequestTransformer\"\/&gt;\n    &lt;int-ws:outbound-gateway uri=\"http:\/\/localhost:8080\/ws-films\/films\" \n        marshaller=\"marshaller\" unmarshaller=\"marshaller\"\/&gt;\n    &lt;int:service-activator ref=\"soapResponseHandler\"\/&gt;\n    &lt;int-stream:stdout-channel-adapter id=\"consoleOut\" append-newline=\"true\" \/&gt;\n&lt;\/int:chain&gt;<\/pre>\n<p>Example: The Pantages Theater film listing is shown to the user.<\/p>\n<pre class=\"brush:bash\">2\n2014-04-11 14:27:54,796|LoggingHandler|User selection: 2\n\nReturned films:\nThe Good, the Bad and the Uggly\nThe Empire strikes back<\/pre>\n<p>[ulp id=&#8217;DdINgEqoOovgkhhk-2&#8242;]<br \/>\n&nbsp;<\/p>\n<h2><a name=\"handling_errors\"><\/a>11. Handling errors<\/h2>\n<p>When anything goes wrong, we need to register it in some way. When this happens, the application will do two things:<\/p>\n<ul>\n<li>Store the message to a database.<\/li>\n<li>Send an email to a specified address.<\/li>\n<\/ul>\n<p>The Spring Integration message channel called <code>errorChannel<\/code> will receive errors of type <code><a href=\"http:\/\/docs.spring.io\/spring-integration\/docs\/3.0.2.RELEASE\/api\/org\/springframework\/integration\/MessagingException.html\">MessagingException<\/a><\/code> thrown by message handlers. This special channel is a publish-subscribe channel, which means that it can have several subscribers to it. Our application subscribes two endpoints in order to execute the two previously specified actions.<\/p>\n<h3><a name=\"storing_the_message\"><\/a>11.1. Storing the message to the database<\/h3>\n<p>The following service activator is subscribed to the error channel, thus it will receive the MessagingException:<\/p>\n<pre class=\"brush:xml\">&lt;int:service-activator ref=\"mongodbRequestHandler\"\/&gt;<\/pre>\n<p>What this activator will do is to resolve what theater was the request sent to and then it will build a <code>FailedMessage<\/code> object, containing the information we want to log:<\/p>\n<pre class=\"brush:java\">@Component(\"mongodbRequestHandler\")\npublic class MongodbRequestHandler {\n    private Logger logger = LoggerFactory.getLogger(this.getClass());\n    \n    @Autowired\n    private TheaterResolver theaterResolver;\n    \n    public FailedMessage handle(MessagingException exc) {\n        logger.error(\"Request failed. Storing to the database\");\n        \n        String theater = theaterResolver.resolve(exc);\n        FailedMessage failedMsg = new FailedMessage(new Date(), exc.getMessage(), theater);\n        \n        return failedMsg;\n    }\n}<\/pre>\n<p>The failed message structure contains basic information:<\/p>\n<pre class=\"brush:java\">public class FailedMessage implements Serializable {\n    private static final long serialVersionUID = 4411815706008283621L;\n    \n    private final Date requestDate;\n    private final String messsage;\n    private final String theater;\n    \n    public FailedMessage(Date requestDate, String message, String theater) {\n        this.requestDate = requestDate;\n        this.messsage = message;\n        this.theater = theater;\n    }\n    \n    \n    public Date getRequestDate() {\n        return new Date(requestDate.getTime());\n    }\n    \n    public String getMessage() {\n        return this.messsage;\n    }\n    \n    public String getTheater() {\n        return this.theater;\n    }\n}<\/pre>\n<p>Once the message is built, we store it to the database by using a mongodb outbound channel adapter:<\/p>\n<pre class=\"brush:xml\">&lt;int-mongodb:outbound-channel-adapter id=\"mongodbAdapter\" collection-name=\"failedRequests\" mongodb-factory=\"mongoDbFactory\" \/&gt;<\/pre>\n<p>The complete code for this part of the flow is shown below:<\/p>\n<pre class=\"brush:xml\">&lt;import resource=\"mongodb-config.xml\"\/&gt;\n    \n&lt;int:chain input-channel=\"errorChannel\"&gt;\n    &lt;int:service-activator ref=\"mongodbRequestHandler\"\/&gt;\n    &lt;int-mongodb:outbound-channel-adapter id=\"mongodbAdapter\" collection-name=\"failedRequests\" mongodb-factory=\"mongoDbFactory\" \/&gt;\n&lt;\/int:chain&gt;<\/pre>\n<p>The <code>mongodb-config.xml<\/code> file contains information specific to MongoDB configuration:<\/p>\n<pre class=\"brush:xml\">&lt;bean id=\"mongoDbFactory\" class=\"org.springframework.data.mongodb.core.SimpleMongoDbFactory\"&gt;\n    &lt;constructor-arg&gt;\n        &lt;bean class=\"com.mongodb.Mongo\"\/&gt;\n    &lt;\/constructor-arg&gt;\n    &lt;constructor-arg value=\"jcgdb\"\/&gt;\n&lt;\/bean&gt;\n \n&lt;bean id=\"mongoDbMessageStore\" class=\"org.springframework.integration.mongodb.store.ConfigurableMongoDbMessageStore\"&gt;\n    &lt;constructor-arg ref=\"mongoDbFactory\"\/&gt;\n&lt;\/bean&gt;<\/pre>\n<p>Example: The following screenshot shows the collection after two failed requests, one for each type of theater:<\/p>\n<p><figure id=\"attachment_4397\" aria-describedby=\"caption-attachment-4397\" style=\"width: 638px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/09\/ch5_pic2.png\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/09\/ch5_pic2.png\" alt=\"Figure 2\" width=\"638\" height=\"218\" class=\"size-full wp-image-4397\" \/><\/a><figcaption id=\"caption-attachment-4397\" class=\"wp-caption-text\">Figure 2<\/figcaption><\/figure><\/p>\n<h3><a name=\"sending_an_email\"><\/a>11.2. Sending an email to the person in charge<\/h3>\n<p>Another endpoint subscribed to the error channel is the mail request handler.<\/p>\n<pre class=\"brush:xml\">&lt;int:service-activator ref=\"mailRequestHandler\"\/&gt;<\/pre>\n<p>This handler is responsible of creating a <a href=\"http:\/\/docs.spring.io\/spring\/docs\/3.2.8.RELEASE\/javadoc-api\/org\/springframework\/mail\/MailMessage.html\">MailMessage<\/a> in order to send it to the mail gateway:<\/p>\n<pre class=\"brush:java\">@Component(\"mailRequestHandler\")\npublic class MailRequestHandler {\n    private Logger logger = LoggerFactory.getLogger(this.getClass());\n    \n    @Autowired\n    private TheaterResolver theaterResolver;\n    \n    @ServiceActivator\n    public MailMessage handle(MessagingException exc) {\n        logger.error(\"Request failed. Sending mail\");\n        \n        MailMessage mailMsg = new SimpleMailMessage();\n        mailMsg.setFrom(\"Theater.System\");\n        mailMsg.setTo(\"my.mail@gmail.com\");\n        mailMsg.setSubject(\"theater request failed\");\n        \n        String theater = theaterResolver.resolve(exc);\n        StringBuilder textMessage = new StringBuilder(\"Invocation to \").append(theater).append(\" failed\\\\n\\\\n\")\n                .append(\"Error message was: \").append(exc.getMessage());\n        mailMsg.setText(textMessage.toString());\n        \n        return mailMsg;\n    }\n}<\/pre>\n<p>The theater resolver checks the user selection and returns the name of the requested theater.<\/p>\n<p>The complete configuration is as follows:<\/p>\n<pre class=\"brush:xml\">&lt;int:chain input-channel=\"errorChannel\"&gt;\n    &lt;int:service-activator ref=\"mailRequestHandler\"\/&gt;\n    &lt;int-mail:outbound-channel-adapter mail-sender=\"mailSender\" \/&gt;\n&lt;\/int:chain&gt;\n\n&lt;import resource=\"mail-config.xml\"\/&gt;<\/pre>\n<p>The <code>mail-config.xml<\/code> contains the configuration of the Spring mail sender:<\/p>\n<pre class=\"brush:xml\">&lt;bean id=\"mailSender\" class=\"org.springframework.mail.javamail.JavaMailSenderImpl\"&gt;\n  &lt;property name=\"host\" value=\"smtp.gmail.com\" \/&gt;\n  &lt;property name=\"port\" value=\"465\" \/&gt;\n  &lt;property name=\"username\" value=\"my.mail@gmail.com\" \/&gt;\n  &lt;property name=\"password\" value=\"myPassword\" \/&gt;\n  &lt;property name=\"javaMailProperties\"&gt;\n     &lt;props&gt;\n        &lt;prop key=\"mail.smtp.starttls.enable\"&gt;true&lt;\/prop&gt;\n        &lt;prop key=\"mail.smtp.auth\"&gt;true&lt;\/prop&gt;\n        &lt;prop key=\"mail.smtp.socketFactory.class\"&gt;javax.net.ssl.SSLSocketFactory&lt;\/prop&gt;\n     &lt;\/props&gt;\n  &lt;\/property&gt;\n&lt;\/bean&gt;<\/pre>\n<p>Example: The message sent to the gmail account:<\/p>\n<p><figure id=\"attachment_4398\" aria-describedby=\"caption-attachment-4398\" style=\"width: 643px\" class=\"wp-caption aligncenter\"><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/09\/ch5_pic3.png\"><img decoding=\"async\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/09\/ch5_pic3.png\" alt=\"Figure 3\" width=\"643\" height=\"90\" class=\"size-full wp-image-4398\" \/><\/a><figcaption id=\"caption-attachment-4398\" class=\"wp-caption-text\">Figure 3<\/figcaption><\/figure><\/p>\n<h2><a name=\"shutting_down\"><\/a>12. Shutting down the application<\/h2>\n<p>When prompted, the user can decide to finish with the execution of the application by entering a zero. When he decides to do that, the router will redirect the message to the <code>quitRequestChannel<\/code> channel (see section 8). Subscribed to this channel, we have configured a message handler chain:<\/p>\n<pre class=\"brush:xml\">&lt;!-- Quit message (shutdown application) --&gt;\n&lt;int:chain input-channel=\"quitRequestChannel\"&gt;\n    &lt;int:service-activator ref=\"shutdownActivator\"\/&gt;\n    &lt;int-event:outbound-channel-adapter\/&gt;\n&lt;\/int:chain&gt;<\/pre>\n<p>The service activator will create a <code>ShutdownEvent<\/code> and return it in order to be handled by the next endpoint of the message handler chain:<\/p>\n<pre class=\"brush:java\">@Component(\"shutdownActivator\")\npublic class ShutdownActivator {\n\n    @ServiceActivator\n    public ShutdownEvent createEvent(Message&lt;String&gt; msg) {\n        return new ShutdownEvent(this);\n    }\n}<\/pre>\n<p>The <code>ShutdownEvent<\/code> is an instance of <code><a href=\"http:\/\/docs.spring.io\/spring\/docs\/3.2.8.RELEASE\/javadoc-api\/org\/springframework\/context\/ApplicationEvent.html\">ApplicationEvent<\/a><\/code>.<\/p>\n<pre class=\"brush:java\">public class ShutdownEvent extends ApplicationEvent {\n    private static final long serialVersionUID = -198696884593684436L;\n\n    public ShutdownEvent(Object source) {\n        super(source);\n    }\n    \n    public ShutdownEvent(Object source, String message) {\n        super(source);\n    }\n\n    public String toString() {\n        return \"Shutdown event\";\n    }\n}<\/pre>\n<p>The event outbound channel adapter will publish as an <code>ApplicationEvent<\/code>, any message sent to the channel where it is subscribed. In this way, they will be handled by any <code><a href=\"http:\/\/docs.spring.io\/spring\/docs\/3.2.8.RELEASE\/javadoc-api\/org\/springframework\/context\/ApplicationListener.html\">ApplicationListener<\/a><\/code> instance registered in the application context. However, if the payload of the message is an instance of <code>ApplicationEvent<\/code>, it will be passed as-is. As seen in the previous code, our <code>ShutdownEvent<\/code> is an instance of <code>ApplicationEvent<\/code>.<\/p>\n<p>Listening to this kind of events, we have registered a listener:<\/p>\n<pre class=\"brush:java\">@Component(\"shutdownListener\")\npublic class ShutdownListener implements ApplicationListener&lt;ShutdownEvent&gt; {\n\n    @Override\n    public void onApplicationEvent(ShutdownEvent event) {\n        TheaterApp.shutdown();\n    }\n}<\/pre>\n<p>The listener is used to shut down the application. If you remember the shutdown method in section five, the <code>Theater<\/code> application closes the application context.<\/p>\n<h2><a name=\"taking_a_glance\"><\/a>13. Taking a glance at the complete flow<\/h2>\n<p>I have put all integration elements within the same file just for ease of clarity, but we could consider splitting it in smaller files:<\/p>\n<pre class=\"brush:xml\">&lt;beans xmlns=\"http:\/\/www.springframework.org\/schema\/beans\"\n    xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n    xmlns:context=\"http:\/\/www.springframework.org\/schema\/context\"\n    xmlns:int=\"http:\/\/www.springframework.org\/schema\/integration\"\n    xmlns:int-jms=\"http:\/\/www.springframework.org\/schema\/integration\/jms\"\n    xmlns:int-stream=\"http:\/\/www.springframework.org\/schema\/integration\/stream\"\n    xmlns:int-event=\"http:\/\/www.springframework.org\/schema\/integration\/event\"\n    xmlns:int-http=\"http:\/\/www.springframework.org\/schema\/integration\/http\"\n    xmlns:int-ws=\"http:\/\/www.springframework.org\/schema\/integration\/ws\"\n    xmlns:int-mongodb=\"http:\/\/www.springframework.org\/schema\/integration\/mongodb\"\n    xmlns:int-mail=\"http:\/\/www.springframework.org\/schema\/integration\/mail\"\n    xmlns:oxm=\"http:\/\/www.springframework.org\/schema\/oxm\"\n    xsi:schemaLocation=\"\n        http:\/\/www.springframework.org\/schema\/beans http:\/\/www.springframework.org\/schema\/beans\/spring-beans-3.0.xsd\n        http:\/\/www.springframework.org\/schema\/context http:\/\/www.springframework.org\/schema\/context\/spring-context-3.0.xsd\n        http:\/\/www.springframework.org\/schema\/integration http:\/\/www.springframework.org\/schema\/integration\/spring-integration-3.0.xsd\n        http:\/\/www.springframework.org\/schema\/integration\/jms http:\/\/www.springframework.org\/schema\/integration\/jms\/spring-integration-jms-3.0.xsd\n        http:\/\/www.springframework.org\/schema\/integration\/stream http:\/\/www.springframework.org\/schema\/integration\/stream\/spring-integration-stream-3.0.xsd\n        http:\/\/www.springframework.org\/schema\/integration\/event http:\/\/www.springframework.org\/schema\/integration\/event\/spring-integration-event-3.0.xsd\n        http:\/\/www.springframework.org\/schema\/integration\/http http:\/\/www.springframework.org\/schema\/integration\/http\/spring-integration-http-3.0.xsd\n        http:\/\/www.springframework.org\/schema\/integration\/ws http:\/\/www.springframework.org\/schema\/integration\/ws\/spring-integration-ws-3.0.xsd\n        http:\/\/www.springframework.org\/schema\/integration\/mongodb http:\/\/www.springframework.org\/schema\/integration\/mongodb\/spring-integration-mongodb-3.0.xsd\n        http:\/\/www.springframework.org\/schema\/integration\/mail http:\/\/www.springframework.org\/schema\/integration\/mail\/spring-integration-mail-3.0.xsd\n        http:\/\/www.springframework.org\/schema\/oxm http:\/\/www.springframework.org\/schema\/oxm\/spring-oxm-3.0.xsd\"&gt;\n    \n    &lt;context:component-scan base-package=\"xpadro.spring.integration\"\/&gt;\n    \n    &lt;!-- System entry --&gt;\n    &lt;int-stream:stdin-channel-adapter id=\"consoleIn\" channel=\"systemEntry\"&gt;\n        &lt;int:poller fixed-delay=\"1000\" max-messages-per-poll=\"1\" \/&gt;\n    &lt;\/int-stream:stdin-channel-adapter&gt;\n\n    &lt;int:channel id=\"systemEntry\"&gt;\n        &lt;int:interceptors&gt;\n            &lt;int:wire-tap channel=\"requestLoggingChannel\"\/&gt;\n        &lt;\/int:interceptors&gt;\n    &lt;\/int:channel&gt;\n    \n    &lt;int:logging-channel-adapter id=\"requestLoggingChannel\" \n        expression=\"'User selection: '.concat(payload)\" level=\"INFO\"\/&gt;\n    \n    &lt;int:filter input-channel=\"systemEntry\" output-channel=\"validEntriesChannel\" ref=\"entryFilter\" \n        discard-channel=\"invalidEntries\"\/&gt;\n    \n    \n    &lt;!-- Invalid entries (show on console) --&gt;\n    &lt;int:chain input-channel=\"invalidEntries\"&gt;\n        &lt;int:transformer ref=\"discardsTransformer\"\/&gt;\n        &lt;int-stream:stdout-channel-adapter id=\"consoleOut\" append-newline=\"true\" \/&gt;\n    &lt;\/int:chain&gt;\n\n    \n    &lt;!-- Valid entries (continue processing) --&gt;\n    &lt;int:channel id=\"validEntriesChannel\" \/&gt;\n    &lt;int:router input-channel=\"validEntriesChannel\" ref=\"cinemaRedirector\"\/&gt;\n    \n    \n    &lt;!-- Quit message (shutdown application) --&gt;\n    &lt;int:chain input-channel=\"quitRequestChannel\"&gt;\n        &lt;int:service-activator ref=\"shutdownActivator\"\/&gt;\n        &lt;int-event:outbound-channel-adapter\/&gt;\n    &lt;\/int:chain&gt;\n\n    \n    &lt;!-- Continue processing (get data) --&gt;\n\n    &lt;!-- Pantages Theater request --&gt;\n    &lt;int:chain input-channel=\"pantagesRequestChannel\"&gt;\n        &lt;int:transformer ref=\"soapRequestTransformer\"\/&gt;\n        &lt;int-ws:outbound-gateway uri=\"http:\/\/localhost:8080\/ws-films\/films\" \n            marshaller=\"marshaller\" unmarshaller=\"marshaller\"\/&gt;\n        &lt;int:service-activator ref=\"soapResponseHandler\"\/&gt;\n        &lt;int-stream:stdout-channel-adapter id=\"consoleOut\" append-newline=\"true\" \/&gt;\n    &lt;\/int:chain&gt;\n    \n    &lt;oxm:jaxb2-marshaller id=\"marshaller\" contextPath=\"xpadro.spring.integration.ws.types\" \/&gt;\n\n    \n    &lt;!-- Egyptian Theater request --&gt;\n    \n    &lt;int:chain input-channel=\"egyptianRequestChannel\"&gt;\n        &lt;int-http:outbound-gateway url=\"http:\/\/localhost:8080\/rest-films\/spring\/films\" \n            expected-response-type=\"java.lang.String\" http-method=\"GET\" charset=\"UTF-8\"\/&gt;\n        &lt;int:json-to-object-transformer type=\"xpadro.spring.integration.model.Film[]\"\/&gt;\n        &lt;int:service-activator ref=\"restResponseHandler\"\/&gt;\n        &lt;int-stream:stdout-channel-adapter id=\"consoleOut\" append-newline=\"true\" \/&gt;\n    &lt;\/int:chain&gt;\n    \n    \n    &lt;!-- Error handling --&gt;\n    &lt;import resource=\"mongodb-config.xml\"\/&gt;\n    \n    &lt;int:chain input-channel=\"errorChannel\"&gt;\n        &lt;int:service-activator ref=\"mongodbRequestHandler\"\/&gt;\n        &lt;int-mongodb:outbound-channel-adapter id=\"mongodbAdapter\" collection-name=\"failedRequests\" mongodb-factory=\"mongoDbFactory\" \/&gt;\n    &lt;\/int:chain&gt;\n    \n    &lt;int:chain input-channel=\"errorChannel\"&gt;\n        &lt;int:service-activator ref=\"mailRequestHandler\"\/&gt;\n        &lt;int-mail:outbound-channel-adapter mail-sender=\"mailSender\" \/&gt;\n    &lt;\/int:chain&gt;\n    \n    &lt;import resource=\"mail-config.xml\"\/&gt;\n \n&lt;\/beans&gt;<\/pre>\n<h2><a name=\"technology_versions\"><\/a>14. Technology versions<\/h2>\n<p>For this application, I have used the 3.2.8 release version of the Spring framework and the latest 3.0.2 release version of Spring Integration.<\/p>\n<p>The full dependency list is shown here:<\/p>\n<pre class=\"brush:xml\">&lt;properties&gt;\n    &lt;spring-version&gt;3.2.8.RELEASE&lt;\/spring-version&gt;\n    &lt;spring-integration-version&gt;3.0.2.RELEASE&lt;\/spring-integration-version&gt;\n    &lt;slf4j-version&gt;1.7.5&lt;\/slf4j-version&gt;\n    &lt;jackson-version&gt;2.3.0&lt;\/jackson-version&gt;\n    &lt;javax-mail-version&gt;1.4.1&lt;\/javax-mail-version&gt;\n&lt;\/properties&gt;\n\n&lt;dependencies&gt;\n    &lt;!-- Spring Framework - Core --&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;org.springframework&lt;\/groupId&gt;\n        &lt;artifactId&gt;spring-context&lt;\/artifactId&gt;\n        &lt;version&gt;${spring-version}&lt;\/version&gt;\n    &lt;\/dependency&gt;\n\n    &lt;!-- Spring Framework - Integration --&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;org.springframework.integration&lt;\/groupId&gt;\n        &lt;artifactId&gt;spring-integration-core&lt;\/artifactId&gt;\n        &lt;version&gt;${spring-integration-version}&lt;\/version&gt;\n    &lt;\/dependency&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;org.springframework.integration&lt;\/groupId&gt;\n        &lt;artifactId&gt;spring-integration-jms&lt;\/artifactId&gt;\n        &lt;version&gt;${spring-integration-version}&lt;\/version&gt;\n    &lt;\/dependency&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;org.springframework.integration&lt;\/groupId&gt;\n        &lt;artifactId&gt;spring-integration-stream&lt;\/artifactId&gt;\n        &lt;version&gt;${spring-integration-version}&lt;\/version&gt;\n    &lt;\/dependency&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;org.springframework.integration&lt;\/groupId&gt;\n        &lt;artifactId&gt;spring-integration-event&lt;\/artifactId&gt;\n        &lt;version&gt;${spring-integration-version}&lt;\/version&gt;\n    &lt;\/dependency&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;org.springframework.integration&lt;\/groupId&gt;\n        &lt;artifactId&gt;spring-integration-http&lt;\/artifactId&gt;\n        &lt;version&gt;${spring-integration-version}&lt;\/version&gt;\n    &lt;\/dependency&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;org.springframework.integration&lt;\/groupId&gt;\n        &lt;artifactId&gt;spring-integration-ws&lt;\/artifactId&gt;\n        &lt;version&gt;${spring-integration-version}&lt;\/version&gt;\n    &lt;\/dependency&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;org.springframework.integration&lt;\/groupId&gt;\n        &lt;artifactId&gt;spring-integration-mongodb&lt;\/artifactId&gt;\n        &lt;version&gt;${spring-integration-version}&lt;\/version&gt;\n    &lt;\/dependency&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;org.springframework.integration&lt;\/groupId&gt;\n        &lt;artifactId&gt;spring-integration-mail&lt;\/artifactId&gt;\n        &lt;version&gt;${spring-integration-version}&lt;\/version&gt;\n    &lt;\/dependency&gt;\n    \n    &lt;!-- javax.mail --&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;javax.mail&lt;\/groupId&gt;\n        &lt;artifactId&gt;mail&lt;\/artifactId&gt;\n        &lt;version&gt;${javax-mail-version}&lt;\/version&gt;\n    &lt;\/dependency&gt;\n    \n    &lt;!-- Jackson --&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;com.fasterxml.jackson.core&lt;\/groupId&gt;\n        &lt;artifactId&gt;jackson-core&lt;\/artifactId&gt;\n        &lt;version&gt;${jackson-version}&lt;\/version&gt;\n    &lt;\/dependency&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;com.fasterxml.jackson.core&lt;\/groupId&gt;\n        &lt;artifactId&gt;jackson-databind&lt;\/artifactId&gt;\n        &lt;version&gt;${jackson-version}&lt;\/version&gt;\n    &lt;\/dependency&gt;\n\n    &lt;!-- Logging --&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;org.slf4j&lt;\/groupId&gt;\n        &lt;artifactId&gt;slf4j-api&lt;\/artifactId&gt;\n        &lt;version&gt;${slf4j-version}&lt;\/version&gt;\n    &lt;\/dependency&gt;\n    &lt;dependency&gt;\n        &lt;groupId&gt;org.slf4j&lt;\/groupId&gt;\n        &lt;artifactId&gt;slf4j-log4j12&lt;\/artifactId&gt;\n        &lt;version&gt;${slf4j-version}&lt;\/version&gt;\n    &lt;\/dependency&gt;\n&lt;\/dependencies&gt;<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>This article is part of our Academy Course titled Spring Integration for EAI. In this course, you are introduced to Enterprise Application Integration patterns and how Spring Integration addresses them. Next, you delve into the fundamentals of Spring Integration, like channels, transformers and adapters. Check it out here! Table Of Contents 1. Introduction 2. Overview &hellip;<\/p>\n","protected":false},"author":533,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[30,783],"class_list":["post-44580","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-spring","tag-spring-integation"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Spring Integration Full Example - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"This article is part of our Academy Course titled Spring Integration for EAI. In this course, you are introduced to Enterprise Application Integration\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spring Integration Full Example - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"This article is part of our Academy Course titled Spring Integration for EAI. In this course, you are introduced to Enterprise Application Integration\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2015-09-29T19:00:57+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-12-13T09:56:52+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Xavier Padro\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/xavips\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Xavier Padro\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/spring-integration-full-example.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/spring-integration-full-example.html\"},\"author\":{\"name\":\"Xavier Padro\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/5443fbc8fb815652f181942d4622090d\"},\"headline\":\"Spring Integration Full Example\",\"datePublished\":\"2015-09-29T19:00:57+00:00\",\"dateModified\":\"2023-12-13T09:56:52+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/spring-integration-full-example.html\"},\"wordCount\":2091,\"commentCount\":4,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/spring-integration-full-example.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"Spring\",\"Spring Integation\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/spring-integration-full-example.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/spring-integration-full-example.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/spring-integration-full-example.html\",\"name\":\"Spring Integration Full Example - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/spring-integration-full-example.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/spring-integration-full-example.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2015-09-29T19:00:57+00:00\",\"dateModified\":\"2023-12-13T09:56:52+00:00\",\"description\":\"This article is part of our Academy Course titled Spring Integration for EAI. In this course, you are introduced to Enterprise Application Integration\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/spring-integration-full-example.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/spring-integration-full-example.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/spring-integration-full-example.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"spring-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/spring-integration-full-example.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Spring Integration Full Example\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/5443fbc8fb815652f181942d4622090d\",\"name\":\"Xavier Padro\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/bbf0579a188773b88762d54dadc779b2cd17ddb261d809956ed55d8569bd7ca2?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/bbf0579a188773b88762d54dadc779b2cd17ddb261d809956ed55d8569bd7ca2?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/bbf0579a188773b88762d54dadc779b2cd17ddb261d809956ed55d8569bd7ca2?s=96&d=mm&r=g\",\"caption\":\"Xavier Padro\"},\"description\":\"Xavier is a software developer working in a consulting firm based in Barcelona. He is specialized in web application development with experience in both frontend and backend. He is interested in everything related to Java and the Spring framework.\",\"sameAs\":[\"http:\\\/\\\/xpadro.blogspot.gr\\\/\",\"http:\\\/\\\/linkedin.com\\\/pub\\\/xavier-padro-sobrepera\\\/1a\\\/64\\\/3\\\/en\",\"https:\\\/\\\/x.com\\\/https:\\\/\\\/twitter.com\\\/xavips\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/xavier-padro\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Spring Integration Full Example - Java Code Geeks","description":"This article is part of our Academy Course titled Spring Integration for EAI. In this course, you are introduced to Enterprise Application Integration","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html","og_locale":"en_US","og_type":"article","og_title":"Spring Integration Full Example - Java Code Geeks","og_description":"This article is part of our Academy Course titled Spring Integration for EAI. In this course, you are introduced to Enterprise Application Integration","og_url":"https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2015-09-29T19:00:57+00:00","article_modified_time":"2023-12-13T09:56:52+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","type":"image\/jpeg"}],"author":"Xavier Padro","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/xavips","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Xavier Padro","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html"},"author":{"name":"Xavier Padro","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/5443fbc8fb815652f181942d4622090d"},"headline":"Spring Integration Full Example","datePublished":"2015-09-29T19:00:57+00:00","dateModified":"2023-12-13T09:56:52+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html"},"wordCount":2091,"commentCount":4,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["Spring","Spring Integation"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html","url":"https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html","name":"Spring Integration Full Example - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2015-09-29T19:00:57+00:00","dateModified":"2023-12-13T09:56:52+00:00","description":"This article is part of our Academy Course titled Spring Integration for EAI. In this course, you are introduced to Enterprise Application Integration","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","width":150,"height":150,"caption":"spring-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/spring-integration-full-example.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Spring Integration Full Example"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/5443fbc8fb815652f181942d4622090d","name":"Xavier Padro","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/bbf0579a188773b88762d54dadc779b2cd17ddb261d809956ed55d8569bd7ca2?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/bbf0579a188773b88762d54dadc779b2cd17ddb261d809956ed55d8569bd7ca2?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/bbf0579a188773b88762d54dadc779b2cd17ddb261d809956ed55d8569bd7ca2?s=96&d=mm&r=g","caption":"Xavier Padro"},"description":"Xavier is a software developer working in a consulting firm based in Barcelona. He is specialized in web application development with experience in both frontend and backend. He is interested in everything related to Java and the Spring framework.","sameAs":["http:\/\/xpadro.blogspot.gr\/","http:\/\/linkedin.com\/pub\/xavier-padro-sobrepera\/1a\/64\/3\/en","https:\/\/x.com\/https:\/\/twitter.com\/xavips"],"url":"https:\/\/www.javacodegeeks.com\/author\/xavier-padro"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/44580","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/533"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=44580"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/44580\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/240"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=44580"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=44580"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=44580"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}