WildFly Swarm microservice development: JAX-RS app deployed to a Docker container

WildFly Swarm is an interesting approach to the ‘small is good’ current trend that is ignoring the traditional, overly large Java EE App Servers, and instead deploying self-contained, executable Jars without needing a whole App Server to execute.

Rather than requiring the whole Java EE stack, WildFly Swarm lets you chose only the implementations of the parts that your service needs to execute. Need JAX-RS? Then pull it in via a Maven dependency. Need JPA? Pull that in too. Any other required transitive dependencies are automatically pulled in via Maven. Pulling in JAX-RS also requires a Servlet container and APIs, but this is pulled in for you via Maven transitive dependencies. The end result is a self-contained, packaged Jar that contains everything it needs to run with a ‘java -jar’ command.

I’ve been spending some time recently looking at getting Weblogic Portal 10.3.6 running in a Docker container (check my work in progress changes on GitHub here). As EE containers go, it’s big. It’s heavy. If you want to describe anything as a monolith, then this is your perfect example. So switching gears I wanted to go to the other extreme and look at how you would build a lightweight Java based service, and WildfFly Swarm looked pretty interesting.

I attended one of the sessions at JavaOne this year giving an intro to Swarm, so it’s been on my todo list to take a look.

Getting started with Swarm is actually pretty easy, as it’s all driven by Maven dependencies and plugins. There’s an easy to follow tutorial here. The example apps showing different WildFly components packaged using Swarm are also worth a look here.

I worked through the examples putting together a JAX-RS helloworld app, and also a Dockerfile to package and deploy it to a Docker container. It was actually pretty easy, and my app ended up looking much like the provided examples.

My example JAX-RS resource is pretty simple, nothing complicated here:

If you’re looking for the different WildFly services that you can package with Swarm, browsing the mvnrepository is a good place to start to quickly grab the mvn deps, or browse the examples or source.

For the Maven war and wildfly-storm plugins:

[code]<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins>/groupId>
<artifactId>maven-war-plugin>/artifactId>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
<packagingExcludes>WEB-INF/lib/wildfly-swarm-*.jar>/packagingExcludes>
</configuration>
</plugin>
<plugin>
<groupId>org.wildfly.swarm</groupId>
<artifactId>wildfly-swarm-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>[/code]

Next, adding a dependency for the WildFly Swarm JAX-RS:

[code]
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>wildfly-swarm-jaxrs</artifactId>
<version>1.0.0.Alpha5</version>
</dependency>[/code]

To build the self-contained executable Jar, build with ‘mvn package’ – this will build the app as normal to target, but also include a *-swarm.jar – this the self-contained Jar containing all the WildFly dependencies, and can be run standalone with ‘java -jar helloworld-swarm-0.0.1-SNAPSHOT-swarm.jar’

Building a Docker container

Given that we’ve now got a simple, single, self-contained Jar, deploying this into a Docker container is also pretty easy as we have no other dependencies to worry about (we just need a JVM).

An example Dockerfile would look like (scroll to the right):

[code]
FROM java:openjdk-8-jdk
ADD target/helloworld-swarm-0.0.1-SNAPSHOT-swarm.jar /opt/helloworld-swarm.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/opt/helloworld-swarm.jar"]
[/code]

All we’re doing here is:
1. Creating an image based on the official openjdk image from DockerHub

2. Adding our built WildFly Swarm jar containing our app into /opt in the image

3. Exposing port 8080

4. Defining the Entrypoint that executes when the container starts

To create an image based on this Dockerfile:

docker build -t helloworld .

To start a container based on this image:

docker run -d -p 8080:8080 imageid

… this creates a new container based on the new container, runs it as a daemon, with port 8080 in the container exposed to 8080 on the host. Done!

Hit the URL of our endpoint using the IP of the running Docker-Machine:

To watch the logs of the running container, do:

docker logs -f containerid

In this case you see the output as the WildFly Undertow Servlet container starts up, and initializes our JAX-RS based app:

Pretty simple! We’ve got a minimal WildFly server starting up inside a Docker container in about 10s, and our app deploying in 2s. That’s pretty good if you ask me 🙂

 

The value of simplicity in design

As a software developer I can tell you for sure that I am not a User Experience (UX) expert, but I can give you an opinion from experience on what looks good or what is easier to use verses something that is not.

What ‘looks good’ is obviously a highly subjective point of view, but what ‘works well’ or is easy to use is (again from my lack of experience as a UX expert) I assume easier to measure with a variety of metrics (think time spent on page, time spent looking for x on page, time between related clicks/keypresses, number of required navigation steps to get from x to y etc).

The reason for this post is that I’ve come across this quote a few times in multiple places over the past few days:

“… perfection is attained not when there is nothing more to add, but when there is nothing more to remove”

(from French author, Antoine de Saint Exupéry)

In software development at the lowest level, there’s a number of guiding principals that are related to simplicity, for example ‘do one thing and do it well’, with the intent that a method or a class that does one thing is far easier for a developer to understand and maintain. The current trend for microservices caries this concept through to how you structure, package and deploy your system, not as a monolithic single deployment unit, but as many smaller services that ‘do one thing and do it well’.

Bearing all the above in mind, I’ve always found it interesting how Apple clearly follows these design principals in OS X by simplifying the user experience from release to release. Even their hardware products clearly ‘do one thing and do it well’. The iPod was a perfect example of this – it was a music player and nothing else. On the other hand, Microsoft tend to take a different approach and seem to be on a never ending quest to continually add more features, with each release becoming more feature rich, more complex and more difficult to use. Think of any of the MS Office apps and the dizzying array of features each app has, and the amount of time you spend looking for the one feature that you know must be in there somewhere but it’s never in the ribbon bar where you think it should be. Presumably at some point Microsoft does usability testing with typical users – at what point though do they decide that the UX design is good or acceptable? Maybe I’m not a typical user, but if asked to give an example of a well designed and easy to use application, any Microsoft application would definitely not be first to come to mind. Apple don’t escape unscathed here either – some of the recent design changes in iTunes over the past few releases have boggled my mind (related options in different places, some on the far left of the app and some on the right).

I don’t think I had any particular point to make in this post, so I’ll leave with a link to one of my favorite UX books (again, not as an expert in this area). If you’re designing the UI for an application, please, Don’t Make Me Think.

Weblogic Portal 10.3.6 from template: [Security:090820]The internal variable ServletInfoSpi is null and it should not be

On starting a new Weblogic Portal 10.3.6 domain created from a template of a previously created domain, you see this error:

Caused by: javax.servlet.ServletException: [Security:090820]The internal variable ServletInfoSpi is null and it should not be
at weblogic.security.providers.saml.SAMLServletAuthenticationFilter.init(SAMLServletAuthenticationFilter.java:51

As noted in this post here, the *.jks keystore files are omitted when creating from a template (is this a defect?). Copy them across from a new domain created via the config wizard into the root dir of your newly created domain fixes the issue:

[mwhome]\user_projects\domains\your_domain\*.jks

Video: Docker in 5 minutes

I’ve been spending some time working with Docker recently – it’s incredible technology and understandable why it’s getting so much attention for automating reproducible runtimes.

Here’s a quick 5 min overview covering an overview in 5 mins by Vincent Batts, who works at Red Hat on Docker and OpenShift: