Monday, December 22, 2014

Exposing HTTP Restful API with Inbound Adapters. Part 2 (Java DSL)

1   Introduction

In the previous part of this tutorial, we implemented an application exposing a Restful API using XML configuration. This part will re-implement this application using Spring Integration Java DSL.

The application is implemented with Java 8, but when Java 8 specific code is used (for example, when using lambdas), I will also show you how to do it in Java 7. Anyway, I shared both versions at Github in case you want to check it out:

Java 7 Java DSL example

Java 8 Java DSL example

This post is divided into the following sections
  1. Introduction
  2. Application configuration
  3. Get operation
  4. Put and post operations
  5. Delete operation
  6. Conclusion

2   Application configuration

In the web.xml file, the dispatcher servlet is configured to use Java Config:

In the pom.xml file, we include the Spring Integration Java DSL dependency:

The configuration class contains bean and flow definitions.

In order to parse payload expressions, we define a bean parser, using an SpELExpressionParser.

The header mapper will later be registered as a property of inbound gateways, in order to map HTTP headers from/to message headers.

The detail of the flows and endpoints defined in this configuration class is explained in each of the following sections.

3   Get operation

Our first step is to define the HTTP inbound gateway that will handle GET requests.

The createMapping method is the Java alternative to the request-mapping XML element seen in the previous part of the tutorial. In this case, we can also use it to define the request path and supported methods.

Now that we have our gateway set, let’s define the flow that will serve GET requests (remember you can check a diagram of the full flow in the previous part of the tutorial):

The flow works as follows:
  • from(httpGetGate()): Get messages received by the HTTP Inbound Gateway.
  • channel(“httpGetChannel”): Register a new DirectChannel bean and send the message received to it.
  • handle(“personEndpoint”, “get”): Messages sent to the previous channel will be consumed by our personEndpoint bean, invoking its get method.

Since we are using a gateway, the response of the personEndpoint will be sent back to the client.

I am showing the personEndpoint for convenience, since it’s actually the same as in the XML application:

GetOperationsTest uses a RestTemplate to test the exposed HTTP GET integration flow:

I won’t show the full class since it is the same as in the XML example.

4   Put and post operations

Continuing with our Restful API application example, we define a bean for the HTTP inbound channel adapter.  You may notice that we are creating a new Gateway. The reason is that inbound channel adapter is internally implemented as a gateway that is not expecting a reply.

We are again using the parser to resolve the returned status code expression.

The former XML attribute request-payload-type of the inbound adapter is now set as a property of the gateway.

The flow that handles both PUT and POST operations uses a router to send the message to the appropriate endpoint, depending on the HTTP method received:

The flow is executed the following way:
  • from(httpPostPutGate()):Get messages received by the HTTP Inbound adapter.
  • channel(“routeRequest”): Register a DirectChannel bean and send the message received to it.
  • route(...): Messages sent to the previous channel will be handled by a router, which will redirect them based on the HTTP method received (http_requestMethod header). The destination channel is resolved applying the prefix and suffix. For example, if the HTTP method is PUT, the resolved channel will be httpPutChannel, which is a bean also defined in this configuration class.

Subflows (httpPutFlow and httpPostFlow) will receive messages from the router and handle them in our personEndpoint.

Since we defined an inbound adapter, no response from the endpoint is expected.

In the router definition we used Java 8 lambdas. I told you I would show the alternative in Java 7, so a promise is a promise:

A little bit longer, isn’t it?

The PUT flow is tested by the PutOperationsTest class:

The POST flow is tested by the PostOperationsTest class:

5   Delete operation

With this operation we complete our application. The entry point is defined by the following bean:

The configuration is pretty similar to the PutPost gateway. I won’t explain it again.

The delete flow sends the deletion request to the personEndpoint:

And our bean will request the service to delete the resource:

The test asserts that the resource no longer exists after deletion:

6   Conclusion

This second part of the tutorial has shown us how to implement a Spring Integration application with no XML configuration, using the new Spring Integration Java DSL. Although flow configuration is more readable using Java 8 lambdas, we still have the option to use Java DSL with previous versions of the language.

I'm publishing my new posts on Google plus and Twitter. Follow me if you want to be updated with new content.

1 comment:

  1. Nice enlightening post, though I miss the part where the server is startet to run the junit tests against it?! mvn test would resoult in connection refused exceptions.