Both Spring and Java EE provide possibility of processing requests send to RESTful web services asynchronously. I’ve read some good comparisons of Spring vs. JAX-RS REST API’s, some quite are quite old now. Regarding Spring I can recommend an article by Magnus Larsson. In this article Magnus used Spring Boot to develop a RESTful web service (or a REST service if you prefer this name ;)).

I wanted to build an example of dockerized Spring REST service using Spring Boot and compare it to what Java EE can give us. In this post I will focus on Spring and in the next post I will develop similar service in JAX-RS to show similarities and differences. In order for the architecture to be cohesive I will not use Spring Boot then, instead I will use Wildfly Swarm – a Java EE solution that allows to build your own custom container for Java EE based services. To be honest nowadays I prefer spring when it comes to flexibility, but Java EE is really getting closer in the mainstream technologies – I mean messaging, batch, components, web frameworks (hey ! there will be a Java EE MVC Framework !).

If you would be curious about WildFly swarm tak a look at Markus Eisele article or great Mastertheboss website.

Why async ? Because it’s more fun 🙂 and in some cases it is viable to use asynchronous service, especially that most JavaScipt API’s uses nowadays some kind of reactive or reactive-like API – like Q in Angular JS. We live in an async world.

So let’s get down to work. We will create a simple service that will accept request and then process it asynchronously allowing http connector thread to service some other request. The processing is well described in Spring Reference Docs – there is no point in repeating it here. The important things are:

  • There will be some performance penalty due to releasing thread and then re-attaching a thread to return data to client
  • We are talking about connector thread, not application thread – the latter is under your control in case of Spring (well in Java EE in most cases also)
  • Scalability will be better in cases where http threads just waited for application threads, so when application took some non-negligible time to process request
  • Fast processing requests may benefit also – if there are more http threads free to service requests more fast requests can be processed as web server’s or application server’s thread pool is most likely used to service not only requests (it is like this in WildFly, Weblogic, Tomcat)

First thing we need to do is to create a Spring Boot application – we will use @SpringBootApplication as this meta-annotation specifies @EnableAutoConfiguration, @ComponentScan and @Configuration, we will also @EnableAsync so that one of our components can provide asynchronous method (this is not the same as async controller method):

Our service will invoke an EIS businnes delegate components – in real app this could be a connector to ESB, a core banking system or something like this.

In order to better see the asynchronous processing order we log some information, and simulate that processing takes 5 seconds. Notice that first process method is @Async, so it will be invoked in separate thread.

A simple DTO for task data:

And finally the REST service:

First method (or operation in web services nomenclature) returns a DeferredResult, and as state in Spring docs, where an instance of DeferredResult is returned asynchronous request processing kicks in – response processing is suspended, thread is released but http connections is kept open ready for actual response to be send when it is ready. Processing is restarted when setResult or setError result is invoked on DeferredResult instance. We can also register timeout and completion callbacks on DeferredResult instance.

In case of EISBusinessDelegate line below is setting result:

We use @Async to simulate some long processing in separate thread and to show that DeferredResult can be passed to a separate layer and set response there.

This is the biggest difference compared to next method that returns Callable. Here result is returned by RESTful controller. The third method add possibility of registering timeout and completion callback.

Exception processing in basically the same as form synchronous controller methods.

In order to test our services we can use Spring’s REST Templates (full code available on github):

 

Spring boot role in all these is of course to simplify processing and make application more cloud friendly. We can build fat jar, and Spring Boot takes care of things such as marking DispatcherServlet as async capable (<asycn-supported> – see Configuring Asynchronous Request Processing in Spring ref docs). Let’s go one step further especially that it is very easy to dockerize this app using Spotify Docker Maven plugin, important parts of pom.xml are:

docker.image.prefix will be used as image prefix used to identify this image. See imageName tag below – second part of it will the project’s artifact id

Important detail – docker must run under root or sudo, but if you want to build docker image with maven plugin then Eclipse must also run under sudo or root. I haven’t tried Intellij Idea yet… I really should.

To build a docker image we must write a Docker file like the one below

FROM java:8 – tells docker to take an image that we will build upon.
VOLUME /tmp – instructs docker to create /tmp directory (it will be used by e.g. embedded Tomcat)
ADD asynch-service-1.0.0-SNAPSHOT.jar app.jar – adds our application from the local filesystem to image
EXPOSE 8080 – we expose port 8080
RUN sh -c ‘touch /app.jar’ – touch will ensure that file modification timestamp is ok
ENTRYPOINT [“java”,”-Djava.security.egd=file:/dev/./urandom”,”-jar”,”/app.jar”] – we run our app (spring boot will take care of server etc.)

After docker image is build we can run docker image using command like the one below (using sudo or root):

sudo docker run –p 8080:8080 –name contaier_name spiralarchitect/asynch-service

Code on GitHub,

Hav en dejlig dag !

Ps. simplish test client has localhost:8080 hardcoded – be aware of this.