Skip to content

Latest commit

 

History

History
191 lines (154 loc) · 8.6 KB

docker-javaee7.adoc

File metadata and controls

191 lines (154 loc) · 8.6 KB

Deploy Java EE 7 Application

Java EE 7 Movieplex is a standard multi-tier enterprise application that shows design patterns and anti-patterns for a typical Java EE 7 application.

javaee7 hol
Figure 1. Java EE 7 Application Architecture

This section explains how this application can be deployed in a Docker container using a pre-built WAR in two different ways:

  1. Using in-memory database in WildFly

  2. Using container linking to link WildFly and MySQL database

And then it will cover how to test such applications.

Deploy Using Pre-Built WAR

Pull the Docker image that contains WildFly and pre-built Java EE 7 application WAR file as shown:

docker pull arungupta/javaee7-hol

The javaee7-hol Dockerfile is based on jboss/wildfly and adds the movieplex7 application as war file.

Run it:

docker run -it -p 8080:8080 arungupta/javaee7-hol

See the application in action at http://dockerhost:8080/movieplex7/. The output is shown:

javaee7 movieplex7
Figure 2. Java EE 7 Application Output

This uses an in-memory database with WildFly application server as shown in the image:

javaee7 hol in memory database
Figure 3. In-memory Database

Only two changes are required to the standard jboss/wildfly image:

  1. By default, WildFly starts in Web platform. This Java EE 7 application uses some capabilities from the Full Platform and so WildFly is started in that mode instead as:

    CMD ["/opt/jboss/wildfly/bin/standalone.sh", "-c", "standalone-full.xml", "-b", "0.0.0.0"]
  2. WAR file is copied to the standalone/deployments directory as:

    RUN curl -L https://github.com/javaee-samples/javaee7-hol/raw/master/solution/movieplex7-1.0-SNAPSHOT.war -o /opt/jboss/wildfly/standalone/deployments/movieplex7-1.0-SNAPSHOT.war

Deploy Using Container Linking

Deploy Java EE 7 Application explained how to use an in-memory database with the application server. This gets you started rather quickly but becomes a bottleneck soon as the database is only in-memory. This means that any changes made to your schema and data are lost when the application server shuts down. In this case, you need to use a database server that resides outside the application server. For example, MySQL as the database server and WildFly as the application server.

javaee7 hol container linking
Figure 4. Two Containers On Same Docker Host

This section will show how Docker Container Linking can be used to connect to a service running inside a Docker container via a network port.

  1. Start MySQL server as:

    docker run --name mysqldb -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_DATABASE=sample -e MYSQL_ROOT_PASSWORD=supersecret -p 3306:3306 -d mysql

    -e define environment variables that are read by the database at startup and allow us to access the database with this user and password.

  2. Start WildFly and deploy Java EE 7 application as:

    docker run -it --name mywildfly --link mysqldb:db -p 8080:8080 arungupta/wildfly-mysql-javaee7

    --link takes two parameters - first is name of the container we’re linking to and second is the alias for the link name.

    Note
    Container Linking

    Creating a link between two containers creates a conduit between a source container and a target container and securely transfer information about source container to target container.

    In our case, target container (WildFly) can see information about source container (MySQL). When containers are linked, information about a source container can be sent to a recipient container. This allows the recipient to see selected data describing aspects of the source container. For example, IP address of MySQL server is expoed at $DB_PORT_3306_TCP_ADDR and port of MySQL server is exposed at $DB_PORT_3306_TCP_PORT. These are then used to create the JDBC resource.

    See more about container communication on the Docker website Linking Containers Together

  3. See the output as:

    > curl http://dockerhost:8080/employees/resources/employees
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection><employee><id>1</id><name>Penny</name></employee><employee><id>2</id><name>Sheldon</name></employee><employee><id>3</id><name>Amy</name></employee><employee><id>4</id><name>Leonard</name></employee><employee><id>5</id><name>Bernadette</name></employee><employee><id>6</id><name>Raj</name></employee><employee><id>7</id><name>Howard</name></employee><employee><id>8</id><name>Priya</name></employee></collection>

Test Java EE 7 Application

Testing Java EE applications is a very important aspect. Especially when it comes to in-container tests, JBoss Arquillian is well known to make this very easy for Java EE application servers. Picking up where unit tests leave off, Arquillian handles all the plumbing of container management, deployment and framework initialization so you can focus on the task at hand, writing your tests.

With Arquillian, you can use WildFly remote container adapter and connect to any WildFly instance running in a Docker container. But this wouldn’t help with the Docker container lifycycle management.

Arquillian Cube, an extension of Arquillian, allows you to control the lifecycle of Docker images as part of the test lifecyle, either automatically or manually. This extension allows to start a Docker container with a server installed, deploy the required deployable file within it and execute Arquillian tests.

The key point here is that if Docker is used as deployable platform in production, your tests are executed in a the same container as it will be in production, so your tests are even more real than before.

  1. Check out the workspace:

    git clone http://github.com/javaee-samples/javaee-arquillian-cube
  2. Edit src/test/resources/arquillian.xml file and change the IP address specified in serverUri property value to point to your Docker host’s IP. This can be found out as:

    docker-machine ip lab
  3. Run the tests as:

    mvn test

    This will create a container using the image defined in src/test/resources/wildfly/Dockerfile. The container qualifier in arquillian.xml defines the directory name in src/test/resources directory.

    Note

    A pre-built image can be used by specifying:

    wildfly:
      image: jboss/wildfly

    instead of

    wildfly:
      buildImage:
        dockerfileLocation: src/test/resources/wildfly

    By default, the “cube” profile is activated and this includes all the required dependencies.

    The result is shown as:

    Running org.javaee7.sample.PersonDatabaseTest
    Jun 16, 2015 9:23:04 AM org.jboss.arquillian.container.impl.MapObject populate
    WARNING: Configuration contain properties not supported by the backing object org.jboss.as.arquillian.container.remote.RemoteContainerConfiguration
    Unused property entries: {target=wildfly:8.1.0.Final:remote}
    Supported property names: [managementAddress, password, managementPort, managementProtocol, username]
    Jun 16, 2015 9:23:13 AM org.xnio.Xnio <clinit>
    INFO: XNIO version 3.2.0.Beta4
    Jun 16, 2015 9:23:13 AM org.xnio.nio.NioXnio <clinit>
    INFO: XNIO NIO Implementation Version 3.2.0.Beta4
    Jun 16, 2015 9:23:13 AM org.jboss.remoting3.EndpointImpl <clinit>
    INFO: JBoss Remoting version (unknown)
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 16.406 sec - in org.javaee7.sample.PersonDatabaseTest
    
    Results :
    
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
    
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
  4. In arquillian.xml, add the following property:

    <property name="connectionMode">STARTORCONNECT</property>

    This bypasses the create/start Cube commands if a Docker Container with the same name is already running on the target system.

    This allows you to prestart the containers manually during development and just connect to them to avoid the extra cost of starting the Docker Containers for each test run. This assumes you are not changing the actual definition of the Docker Container itself.