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 🙂

 

3 Replies to “WildFly Swarm microservice development: JAX-RS app deployed to a Docker container”

  1. HI i having issues when bringing the container up.
    [org.wildfly.extension.undertow] (MSC service thread 1-2) WFLYU
    T0012: Started server default-server.
    2018-03-15 19:00:22,209 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-4) MSC000001
    : Failed to start service org.wildfly.undertow.listener.default: org.jboss.msc.service.StartE
    xception in service org.wildfly.undertow.listener.default: WFLYUT0082: Could not start ‘defau
    lt’ listener.
    at org.wildfly.extension.undertow.ListenerService.start(ListenerService.java:181)
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControll
    erImpl.java:2032)
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.ja
    va:1955)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
    Caused by: java.net.SocketException: Protocol family unavailable
    at sun.nio.ch.Net.bind0(Native Method)
    at sun.nio.ch.Net.bind(Net.java:433)
    at sun.nio.ch.Net.bind(Net.java:425)
    at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
    at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74)
    at org.xnio.nio.NioXnioWorker.createTcpConnectionServer(NioXnioWorker.java:179)
    at org.xnio.XnioWorker.createStreamConnectionServer(XnioWorker.java:310)
    at org.wildfly.extension.undertow.HttpListenerService.startListening(HttpListenerServ
    ice.java:106)
    at org.wildfly.extension.undertow.ListenerService.start(ListenerService.java:169)
    … 5 more

    2018-03-15 19:00:22,214 ERROR [org.jboss.as.controller.management-operation] (Controller Boot
    Thread) WFLYCTL0013: Operation (“add”) failed – address: ([
    (“subsystem” => “undertow”),
    (“server” => “default-server”),
    (“http-listener” => “default”)
    ]) – failure description: {“WFLYCTL0080: Failed services” => {“org.wildfly.undertow.listener.
    default” => “WFLYUT0082: Could not start ‘default’ listener.
    Caused by: java.net.SocketException: Protocol family unavailable”}}
    2018-03-15 19:00:22,255 INFO [org.jboss.as.controller] (Controller Boot Thread) WFLYCTL0183:
    Service status report
    WFLYCTL0186: Services which failed to start: service org.wildfly.undertow.listener.def
    ault: WFLYUT0082: Could not start ‘default’ listener.

    2018-03-15 19:00:22,284 INFO [org.jboss.as.server] (Controller Boot Thread) WFLYSRV0212: Res
    uming server
    2018-03-15 19:00:22,298 ERROR [org.jboss.as] (Controller Boot Thread) WFLYSRV0026: WildFly Sw
    arm 2018.3.3 (WildFly Core 3.0.8.Final) started (with errors) in 1564ms – Started 97 of 105 s
    ervices (1 services failed or missing dependencies, 16 services are lazy, passive or on-deman
    d)
    2018-03-15 19:00:22,302 ERROR [stderr] (main) java.lang.RuntimeException: org.jboss.msc.servi
    ce.StartException in service org.wildfly.undertow.listener.default: WFLYUT0082: Could not sta
    rt ‘default’ listener.
    2018-03-15 19:00:22,304 ERROR [stderr] (main) at org.wildfly.swarm.spi.api.ClassLoading.wit
    hTCCL(ClassLoading.java:45)
    2018-03-15 19:00:22,305 ERROR [stderr] (main) at org.wildfly.swarm.container.runtime.Server
    BootstrapImpl.bootstrap(ServerBootstrapImpl.java:113)
    2018-03-15 19:00:22,305 ERROR [stderr] (main) at org.wildfly.swarm.Swarm.start(Swarm.java:3
    98)
    2018-03-15 19:00:22,306 ERROR [stderr] (main) at org.wildfly.swarm.Swarm.main(Swarm.java:74
    2)
    2018-03-15 19:00:22,306 ERROR [stderr] (main) at sun.reflect.NativeMethodAccessorImpl.invok
    e0(Native Method)
    2018-03-15 19:00:22,307 ERROR [stderr] (main) at sun.reflect.NativeMethodAccessorImpl.invok
    e(NativeMethodAccessorImpl.java:62)
    2018-03-15 19:00:22,307 ERROR [stderr] (main) at sun.reflect.DelegatingMethodAccessorImpl.i
    nvoke(DelegatingMethodAccessorImpl.java:43)
    2018-03-15 19:00:22,308 ERROR [stderr] (main) at java.lang.reflect.Method.invoke(Method.jav
    a:498)
    2018-03-15 19:00:22,309 ERROR [stderr] (main) at org.wildfly.swarm.bootstrap.MainInvoker.in
    voke(MainInvoker.java:53)
    2018-03-15 19:00:22,309 ERROR [stderr] (main) at org.wildfly.swarm.bootstrap.Main.run(Main.
    java:132)
    2018-03-15 19:00:22,309 ERROR [stderr] (main) at org.wildfly.swarm.bootstrap.Main.main(Main
    .java:85)
    2018-03-15 19:00:22,310 ERROR [stderr] (main) Caused by: org.jboss.msc.service.StartException
    in service org.wildfly.undertow.listener.default: WFLYUT0082: Could not start ‘default’ list
    ener.
    2018-03-15 19:00:22,310 ERROR [stderr] (main) at org.wildfly.extension.undertow.ListenerSer
    vice.start(ListenerService.java:181)
    2018-03-15 19:00:22,315 ERROR [stderr] (main) at org.jboss.msc.service.ServiceControllerImp
    l$StartTask.startService(ServiceControllerImpl.java:2032)
    2018-03-15 19:00:22,316 ERROR [stderr] (main) at org.jboss.msc.service.ServiceControllerImp
    l$StartTask.run(ServiceControllerImpl.java:1955)
    2018-03-15 19:00:22,316 ERROR [stderr] (main) at java.util.concurrent.ThreadPoolExecutor.ru
    nWorker(ThreadPoolExecutor.java:1142)
    2018-03-15 19:00:22,316 ERROR [stderr] (main) at java.util.concurrent.ThreadPoolExecutor$Wo
    rker.run(ThreadPoolExecutor.java:617)
    2018-03-15 19:00:22,317 ERROR [stderr] (main) at java.lang.Thread.run(Thread.java:745)
    2018-03-15 19:00:22,317 ERROR [stderr] (main) Caused by: java.net.SocketException: Protocol f
    amily unavailable
    2018-03-15 19:00:22,318 ERROR [stderr] (main) at sun.nio.ch.Net.bind0(Native Method)
    2018-03-15 19:00:22,319 ERROR [stderr] (main) at sun.nio.ch.Net.bind(Net.java:433)
    2018-03-15 19:00:22,320 ERROR [stderr] (main) at sun.nio.ch.Net.bind(Net.java:425)
    2018-03-15 19:00:22,320 ERROR [stderr] (main) at sun.nio.ch.ServerSocketChannelImpl.bind(Se
    rverSocketChannelImpl.java:223)
    2018-03-15 19:00:22,321 ERROR [stderr] (main) at sun.nio.ch.ServerSocketAdaptor.bind(Server
    SocketAdaptor.java:74)
    2018-03-15 19:00:22,321 ERROR [stderr] (main) at org.xnio.nio.NioXnioWorker.createTcpConnec
    tionServer(NioXnioWorker.java:179)
    2018-03-15 19:00:22,323 ERROR [stderr] (main) at org.xnio.XnioWorker.createStreamConnection
    Server(XnioWorker.java:310)
    2018-03-15 19:00:22,323 ERROR [stderr] (main) at org.wildfly.extension.undertow.HttpListene
    rService.startListening(HttpListenerService.java:106)
    2018-03-15 19:00:22,323 ERROR [stderr] (main) at org.wildfly.extension.undertow.ListenerSer
    vice.start(ListenerService.java:169)
    2018-03-15 19:00:22,324 ERROR [stderr] (main) … 5 more
    2018-03-15 19:00:22,324 ERROR [stderr] (main) java.lang.RuntimeException: org.jboss.msc.servi
    ce.StartException in service org.wildfly.undertow.listener.default: WFLYUT0082: Could not sta
    rt ‘default’ listener.
    2018-03-15 19:00:22,324 ERROR [stderr] (main) at org.wildfly.swarm.spi.api.ClassLoading.wit
    hTCCL(ClassLoading.java:45)
    2018-03-15 19:00:22,325 ERROR [stderr] (main) at org.wildfly.swarm.container.runtime.Server
    BootstrapImpl.bootstrap(ServerBootstrapImpl.java:113)
    2018-03-15 19:00:22,325 ERROR [stderr] (main) at org.wildfly.swarm.Swarm.start(Swarm.java:3
    98)
    2018-03-15 19:00:22,326 ERROR [stderr] (main) at org.wildfly.swarm.Swarm.main(Swarm.java:74
    2)
    2018-03-15 19:00:22,326 ERROR [stderr] (main) at sun.reflect.NativeMethodAccessorImpl.invok
    e0(Native Method)
    2018-03-15 19:00:22,326 ERROR [stderr] (main) at sun.reflect.NativeMethodAccessorImpl.invok
    e(NativeMethodAccessorImpl.java:62)
    2018-03-15 19:00:22,327 ERROR [stderr] (main) at sun.reflect.DelegatingMethodAccessorImpl.i
    nvoke(DelegatingMethodAccessorImpl.java:43)
    2018-03-15 19:00:22,327 ERROR [stderr] (main) at java.lang.reflect.Method.invoke(Method.jav
    a:498)
    2018-03-15 19:00:22,327 ERROR [stderr] (main) at org.wildfly.swarm.bootstrap.MainInvoker.in
    voke(MainInvoker.java:53)
    2018-03-15 19:00:22,328 ERROR [stderr] (main) at org.wildfly.swarm.bootstrap.Main.run(Main.
    java:132)
    2018-03-15 19:00:22,328 ERROR [stderr] (main) at org.wildfly.swarm.bootstrap.Main.main(Main
    .java:85)
    2018-03-15 19:00:22,328 ERROR [stderr] (main) Caused by: org.jboss.msc.service.StartException
    in service org.wildfly.undertow.listener.default: WFLYUT0082: Could not start ‘default’ list
    ener.
    2018-03-15 19:00:22,329 ERROR [stderr] (main) at org.wildfly.extension.undertow.ListenerSer
    vice.start(ListenerService.java:181)
    2018-03-15 19:00:22,329 ERROR [stderr] (main) at org.jboss.msc.service.ServiceControllerImp
    l$StartTask.startService(ServiceControllerImpl.java:2032)
    2018-03-15 19:00:22,329 ERROR [stderr] (main) at org.jboss.msc.service.ServiceControllerImp
    l$StartTask.run(ServiceControllerImpl.java:1955)
    2018-03-15 19:00:22,330 ERROR [stderr] (main) at java.util.concurrent.ThreadPoolExecutor.ru
    nWorker(ThreadPoolExecutor.java:1142)
    2018-03-15 19:00:22,330 ERROR [stderr] (main) at java.util.concurrent.ThreadPoolExecutor$Wo
    rker.run(ThreadPoolExecutor.java:617)
    2018-03-15 19:00:22,331 ERROR [stderr] (main) at java.lang.Thread.run(Thread.java:745)
    2018-03-15 19:00:22,331 ERROR [stderr] (main) Caused by: java.net.SocketException: Protocol f
    amily unavailable
    2018-03-15 19:00:22,331 ERROR [stderr] (main) at sun.nio.ch.Net.bind0(Native Method)
    2018-03-15 19:00:22,332 ERROR [stderr] (main) at sun.nio.ch.Net.bind(Net.java:433)
    2018-03-15 19:00:22,332 ERROR [stderr] (main) at sun.nio.ch.Net.bind(Net.java:425)
    2018-03-15 19:00:22,332 ERROR [stderr] (main) at sun.nio.ch.ServerSocketChannelImpl.bind(Se
    rverSocketChannelImpl.java:223)
    2018-03-15 19:00:22,332 ERROR [stderr] (main) at sun.nio.ch.ServerSocketAdaptor.bind(Server
    SocketAdaptor.java:74)
    2018-03-15 19:00:22,333 ERROR [stderr] (main) at org.xnio.nio.NioXnioWorker.createTcpConnec
    tionServer(NioXnioWorker.java:179)
    2018-03-15 19:00:22,333 ERROR [stderr] (main) at org.xnio.XnioWorker.createStreamConnection
    Server(XnioWorker.java:310)
    2018-03-15 19:00:22,333 ERROR [stderr] (main) at org.wildfly.extension.undertow.HttpListene
    rService.startListening(HttpListenerService.java:106)
    2018-03-15 19:00:22,334 ERROR [stderr] (main) at org.wildfly.extension.undertow.ListenerSer
    vice.start(ListenerService.java:169)
    2018-03-15 19:00:22,334 ERROR [stderr] (main) … 5 more
    2018-03-15 19:00:22,345 INFO [org.wildfly.swarm] (Thread-2) WFSWARM0027: Shutdown requested
    2018-03-15 19:00:22,357 INFO [org.jboss.as.server] (Thread-3) WFLYSRV0220: Server shutdown h
    as been requested via an OS signal
    2018-03-15 19:00:22,357 INFO [org.wildfly.extension.undertow] (MSC service thread 1-4) WFLYU
    T0004: Undertow 1.4.18.Final stopping
    2018-03-15 19:00:22,389 INFO [org.jboss.as] (MSC service thread 1-1) WFLYSRV0050: WildFly Swarm 2018.3.3 (WildFly Core 3.0.8.Final) stopped in 33ms

    C:\DEV\TESTCODE\microservice>docker logs -f helloworld
    Error response from daemon: No such container: helloworld

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.