A Simple Java EE Docker Example

read the asciidoc based version of this post here.

 

In this post we will play a bit with docker in the context of Java EE. Here is what we will do:

  • Create, build and run a docker image;
  • the image will start a wildfly server within a JavaEE sample application deployed;
  • show some docker commands;
  • start multiple containers to see the same app running on different ports.

Introduction

I will not introduce docker as there are already many good references on the subject. To create this post i’ve read the following tutorials:

  1.  Docker userguide;
  2. Working with docker images;
  3.  this great post: Docker begginers tutorial;
  4. Arun Gupta’s tech tips: #39, #57#61 and #65.

Pre requisites

To run this tutorial you will need:

  • A docker daemon running on your host machine
    •  after installing docker add this lines in ‘etc\default\docker‘ file: DOCKER_OPTS=”-H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock”
    •  after that, restart your machine and try to run the command:  docker -H tcp://127.0.0.1:2375 –version
      the output must be something like: Docker version 1.4.1, build 5bc2ff8
  • A wildfly 8.2.0 installation(unziped);
  • jdk-8u25-linux-x64.tar.gz file;
  • car-service.war available here;
  • Dockerfile available here.

Creating the Docker image

Docker images represent/describe the container itself. As i got limited internet access(3g from my cellphone) i have created an image using resources from my local machine. So the image will only work if it is build in a directory containing the following files:

  • wildfly-8.2.0.Final: the application server
  • car-service.war: the app we will deploy
  • Dockerfile: the file describing this container
  • jdk-8u25-linux-x64.tar.gz: the java version we will install in the container

NOTE: It is not good practice to use fixed resources in a docker container as it will only work if the files are present during the image build. The best approach is to install everything from scratch and download necessary files. Here is an example of docker file that download/install/deploy an app into wildfly 10 without using local files.

Here is the Dockerfile content:

FROM ubuntu
MAINTAINER Rafael Pestano <rmpestano@gmail.com>

# setup WildFly
COPY wildfly-8.2.0.Final /opt/wildfly

# install example app on wildfy
COPY car-service.war /opt/wildfly/standalone/deployments/

# setup Java

RUN mkdir /opt/java

COPY jdk-8u25-linux-x64.tar.gz /opt/java/

# change dir to Java installation dir

WORKDIR /opt/java/

RUN tar -zxf jdk-8u25-linux-x64.tar.gz

# setup environment variables

RUN update-alternatives --install /usr/bin/javac javac /opt/java/jdk1.8.0_25/bin/javac 100

RUN update-alternatives --install /usr/bin/java java /opt/java/jdk1.8.0_25/bin/java 100

RUN update-alternatives --display java

RUN java -version

# Expose the ports we're interested in
EXPOSE 8080 9990

# Set the default command to run on boot
# This will boot WildFly in the standalone mode and bind to all interface
CMD ["/opt/wildfly/bin/standalone.sh", "-c", "standalone-full.xml", "-b", "0.0.0.0"]

The image inherits from ubuntu, an image which installs Ubuntu OS. Ubuntu image is installed when you follow the docker instalation tutorial.

Next we copy the server to the folder /opt/wildfly inside the container we are creating. COPY is a command available in Dockerfile DSL. All commands can be found here.

Next we copy our app war inside the server with: COPY car-service.war /opt/wildfly/standalone/deployments/.

After, we setup Java by unziping it to /opt/java inside the container and setting up environment variables. A best approach would be apt-get but it requires (good)internet access which i didn’t had at the time of the writing. I used RUN command to execute java -version which will print the version during the image build (if java is correctly installed).

Later I use EXPOSE 8080 9990 to tell docker the ports that can be exposed by the container. A container is the instantiation of a Docker image. When we run an image (docker run) we can specify which ports are accessible to the host machine.

Finally we specify the default command using CMD [“/opt/wildfly/bin/standalone.sh”, “-c”, “standalone-full.xml”, “-b”, “0.0.0.0”]. This command will be fired everytime our container is stated.

Building the image

After describing our image we have to build it. Run the following command from the parent folder containing the Dockerfile:

docker -H tcp://127.0.0.1:2375 build -t javaee_sample java_ee/

  • -H flag specify docker daemon address(we are using tcp to communicate with daemon);
  • build is the command itself;
  • -t specify the name of the tag to identify the image (javaee_sample in this case);
  • java_ee/ is the folder containing the Dockerfile describing our image.

More docker commands can be found here. Here is the output of the command:

After that we can see the created image by listing images installed: docker -H tcp://127.0.0.1:2375 images :

 

Starting the container

The container can be started with the command: docker -H tcp://127.0.0.1:2375 run -p 8180:8080 javaee_sample

  • -p specifies the container port(8080) to be exposed on the host machine. Port 8180 in this case (EXPOSE Dockerfile command);
  • run is the command itself;
  • javaee_sample is the name of the image.

The output of command is wildfly starting because we set it as initial command (CMD Dockerfile command):

img4

Running multiple containers

We can instantiate many container as we want since their ports don’t conflict in the host machine. I will start two more containers exposing port 8080 to 8280 and 8380 respectively:

docker -H tcp://127.0.0.1:2375 run -p 8280:8080 javaee_sample
docker -H tcp://127.0.0.1:2375 run -p 8380:8080 javaee_sample

To list started containers we can use the command docker -H tcp://127.0.0.1:2375 ps, here is the output:

rmpestano@rmpestano-ubuntu:~/docker /images$ docker -H tcp://127.0.0.1:2375 ps
CONTAINER ID        IMAGE                  COMMAND                CREATED             STATUS              PORTS                              NAMES
7b9079806e69        javaee_sample:latest   "/opt/wildfly/bin/st   27 seconds ago      Up 27 seconds       9990/tcp, 0.0.0.0:8280->8080/tcp   suspicious_lovelace
d4975e825751        javaee_sample:latest   "/opt/wildfly/bin/st   28 seconds ago      Up 28 seconds       9990/tcp, 0.0.0.0:8380->8080/tcp   loving_hopper
96e58eb65126        javaee_sample:latest   "/opt/wildfly/bin/st   42 seconds ago      Up 42 seconds       9990/tcp, 0.0.0.0:8180->8080/tcp   clever_cori

And now we can access the three apps in the browser at the same time:

img5

You can stop the container by its ID or by name with docker -H tcp://127.0.0.1:2375 stop suspicious_lovelace

Remember that all data will be lost when the container is stopped. Use Docker volumes for persistent data.

RESTFul Java with JAX-RS 2.0 Book Review

During my vacation i’ve read RESTFul Java with JAX-RS 2.0 second edition by Bill Burk.

This review is just some notes i made while i was visiting each chapter. It is mainly listing the topics i found important and interesting in the book. I’ve also made some comments.

Positive aspects:

  • Very practical with plenty of nice examples using latest JAX-RS version;
  • really easy to ready and understand book;
  • interesting topics were covered.

Negative Aspects:

  • Missing a REST API documentation chapter;
  • not enough attention on testing, maybe a dedicate chapter with best practices;
  • use more json in favor of xml;
  • Jersey was not mentioned.

Overall it is a great book and fully recommended, even for those already working with REST.

Here are my notes on each chapter. A narrative on most important topics covered so you can have an idea on the content of the book:

Chapter 1 – Introduction to REST

Although it is very objective and succinct, this chapter goes directly to the heart of REST. Compares with CORBA, SOAP and WS-* standards. How REST and HTTP are related. A bit of SOA. Refers to Roy Fielding’s PhD thesis[LINK], a must read article. Finally describes the five RESTful architectural principles: Addressability, Constrained Interface, Representation-Oriented, Communicate Statelessly and HATEOAS.
An excellent overview.

Chapter 2 – Designing RESTful Services

This chapter presents a RESTFul Order entry system interface(a.k.a endpoint) of an hypothetical ecommerce. It shows the concepts described on the first chapter explaining it in an HTTP oriented way, no Java code yet. There is an interesting discussion about “State vs Operation” and best practice to model REST resources. The data format chosen(XML) for model was not the best option i think, in my opinion json would be a best approach both for exemplifying as for best practices (i don’t buy that xml is for Java and json is for web related technologies such as Ajax). This chapter accomplishes well it’s objectives which is to illustrate RESTful concepts in practice.

Chapter 3 – Your First JAX-RS Service

It starts talking a bit of servlets then jumps to JAX-RS, it summarizes well the framework for writing RESTFul services in Java.
Next the Order system designed in chapter 2 is implemented in Java using JAX-RS. For the ones already working with REST in Java it does not adds much to the table but it is a necessary step so the application can evolve during the book. Maybe its a personal taste but i have to say again that “application/xml” was not a good choice. In my opinion the examples would be simpler with json, for example


return new StreamingOutput() {
public void write(OutputStream outputStream)
throws IOException, WebApplicationException {
outputCustomer(outputStream, customer);
}
};

Maybe introducing JAX-B in this chapter could be an option to avoid “streams”, inner classes and could simplify the client example.

Chapter 4 – HTTP Method and URI Matching

Details @Path annotation and its matching rules, a bit of sub resources and dispatching, matrix x query params and finally some gotchas in request matching.

Chapter 5 – JAX-RS Injection

Interesting hint on field injection versus singleton resources. @PathParam injection is revisited and more examples are presented. PathSegment and UroInfo are introduced. MatrixParam, QueryParam, FormParam, HeaderParam, CookieParam and BeanParam are detailed with nice examples. BeanParam is new and added to JAX-RS 2.0, a very useful feature. Next it talks about automatic type conversion. How JAX-RS can map request Strings to primitives, enums, lists and objects. Later it goes into details about ParamConverter so JAX-RS can convert http request String into Java objects. Finally the chapter ends explaining @Encoded annotation.

Chapter 6 – JAX-RS Content Handlers

The chapter starts with content marshalling and build in providers (maybe here is the motivation of streams in previous chapters). Some byte and File related examples are presented. Next there is an example of posting a form with Multivalued Map<String, String>. Next the chapter focus JAXB. There is a small intro and some examples. There is an interesting section about JAXB and JSON and how they integrate. Later the chapter details JSON objects. Finally it talks about custom marshalling and exemplifies message body reader and writer.

Chapter 7 – Server Responses and Exception Handling

It starts talking about successful and error responses. Next topic is how to create response with ResponseBuilder. A bit on cookies and later status codes. Next GenericEntity is presented to deal with generics. Finally exception handling is detailed by showing WebApplicationException, exception mappers. It ends explaining error codes and build in JAX-RS exceptions.

Chapter 8 – JAX-RS Client API

A very good introduction to the Client API that comes in JAX-RS 2.0. It really do its job in a very practical way with nice examples.

Chapter 9 – HTTP Content Negotiation

A nice overview of how JAX-RS supports the Conneg protocol to easy the integration with heterogeneous clients and evolution of the system. It starts explaining the negotiation protocol with media type examples, language negotiation and encoding. Next, examples with JAX-RS are presented.The chapter ends with Variants (multiple types of response for the same uri), URI negotiation, new media types (for versioning) and flexible schemas using content negotiation.

Chapter 10 – HATEOAS

A little introduction to the concept. How it can be applied to Web Services. Atom links is presented. Next, the advantages of HATEOAS are explained. Later JAX-RS and HATEOAS plus URI builder and URIInfo are presented with examples. Finally building links and link header is presented.

Chapter 11 – Scaling JAX-RS Applications

The chapter begins talking about the web and mechanisms that help it scale. It talks about caching (browser, proxy and CDN). After introducing caching it explores the HTTP caching with JAX-RS examples. Cache revalidation is visited, again with nice examples. Next topic is concurrency with conditional PUT and POST followed by JAX-RS examples.

Chapter 12 – Filters and Interceptors

Server side filter are presented first with Request and Response filter examples like cache control and authorization. Next, reader and writer interceptors with GZIP example. Client Filters are presented using JAX-RS client API. A cache control filter example is explained, it basically caches some requests and manipulates “If-None-Match” and “If-Modified-Since” headers. Deploying (@Provider) and ordering (@Priority) of filters and interceptors are visited. Method filters and interceptors are exemplified with DynamicFeature and NameBinding. Finally there is a note on exception on filters or interceptors.

Chapter 13 – Asynchronous JAX-RS

It first starts with Client API and AsyncInvoker using futures. Next, Callbacks are presented with nice examples. Server side asynchronous response is introduced. The Internet HTTP request/response thread model and its challenges is explained. Next, the AsyncResponse API is presented with JAX-RS examples.
The chapter made clear that asynchronous responses is for specific applications and most of the times “normal” request/response paradigm is sufficient. Later exception handling and response with resume and cancel is explained. Timeouts and response callbacks are explained. Use cases like server push and publish subscribe (chat) are presented and exemplified. A note on WebSockets and Server Sent Events versus pure HTTP server push apps. Finally scheduling using executors is presented.

Chapter 14 – Deployment and Integration

It starts by registering REST resources by extending application class, initializing Singletons and Classes. Difference between Servlet container and JavaEE JAX-RS deployment is explained. Web.xml configuration is presented. Next topics are EJB 3.1 ad Spring integration. Pretty simple but useful chapter.

Chapter 15 – Securing JAX-RS

A small introduction to security in the web and JavaEE like authentication, authorization, and encryption. It dive in servlet authentication and authorization mechanism followed by encryption. Next authorization annotations like @RolesAllowed and @PermitAll is presented. Next topic is programmatic security with SecurityContext. A JAX-RS RequestFilter for authorization is exemplified. Next is Client side security using JAX-RS client API. OAuth is the next topic. The CNN case is presented as an example of OAuth. Signing and encrypting message bodies is next security topic. It is basically concerned with security in intermediary REST services (a.k.a integrations), twitter is used as example. Later Digital signatures is introduced. DKIM and JOSE JSON Signature (JWS) are exemplified. The last topic is the encryption of representations (the message body). JOSE JSON Encryption (JWE) is used as example. The chapter is more conceptual, the majority of security examples are in Chapter 29.

In chapter 29 there is an interesting OTPAuthenticated Request Filter(one time password). @AllowedPerDay is introduced in the security chain, a nice example of limiting number of access to a resource by user. It is also a ContainerRequestFilter by with lower priority meaning that it runs after OTPAuthenticated filter.

Chapter 16 – Alternative Java Clients

Besides JAX-RS client API other clients are presented. It starts with “pure Java” and HttpURLConnection examples. There is a small note on caching and authentication using java.net classes. Standard Java certificate auth using “keytool” command is introduced. Next topic is HttpClient examples. Client authentication with HttpClient is presented. RESTEasy client proxy is introduced.

CHAPTER 17 – Workbook Introduction

This chapter is a step by step tutorial on how to setup your environment with RESTEasy 3.x(an implementation of JAX-RS 2.0 spec). It uses JDK 6, Maven 3, Jetty 8.1 for servlet container and Wildfly 8.0 for examples that require JavaEE 7. It creates the project and illustrates its directory structure.

From chapter 18 to Chapter 29 is reserved to more elaborate and complete examples for each chapter. This is the great thing on this book, it is example oriented and has dedicate chapters for examples. I will not comment the examples but recommend you to try them when you read, it is great for learning.