Run Java EE Tests on Docker using Arquillian Cube
Tech Tip #61 showed how to run Java EE 7 Hands-on Lab using Docker. The Dockerfile used there can be used to create a new image that can deploy any Java EE 7 WAR file to the WildFly instance running in the container.
For example github.com/arun-gupta/docker-images/blob/master/javaee7-test/Dockerfile can be copied to the root directory of javaee7-samples and be used to deploy jaxrs-client.war
file to the container. Of course, you first need to build the sample as:
1 | mvn -f jaxrs/jaxrs-client/pom.xml clean package -DskipTests |
The exact Dockerfile is shown here:
1 2 | FROM arungupta/wildfly-centos ADD jaxrs/jaxrs-client/target/jaxrs-client.war /opt/wildfly/standalone/deployments/ |
If you want to deploy another Java EE 7 application, then you need to do the following steps:
- Create the WAR file of the sample
- Change the Dockerfile
- Build the image
- Stop the previous container
- Start the new container
Now, if you want to run tests against this instance then mvn test
alone will not do it because either you need to bind the IP address of the Docker container statically, or dynamically find out the address and then patch it at runtime. Anyway, the repeated cycle is little too cumbersome. How do you solve it?
Meet Arquillian Cube!
Arquillian Cube allows you to control the lifecycle of Docker images as part of the test lifecyle, either automatically or manually.
The blog entry provide more details about getting started with Arquillian Cube, and this functionality has now been enabled in “docker” branch of javaee7-samples. Arquillian Cube Extension Alpha2 was recently released and is used to provide integration. Here are the key concepts:
- A new “wildfly-docker-arquillian” profile is being introduced
- The profile adds a dependency on:123456
<
dependency
>
<
groupId
>org.arquillian.cube</
groupId
>
<
artifactId
>arquillian-cube-docker</
artifactId
>
<
version
>1.0.0.Alpha2</
version
>
<
scope
>test</
scope
>
</
dependency
>
- Uses Docker REST API to talk to the container. Complete API docs shows the sample payloads and explains the query parameters and status codes.
- Uses WildFly remote adapter to talk to the application server running within the container
- Configuration for Docker image is specified as part of maven-surefire-plugin.:01020304050607080910111213141516171819
<
configuration
>
<
systemPropertyVariables
>
<
arquillian.launch
>wildfly-docker</
arquillian.launch
>
<
arq.container.wildfly-docker.configuration.username
>admin</
arq.container.wildfly-docker.configuration.username
>
<
arq.container.wildfly-docker.configuration.password
>Admin#70365</
arq.container.wildfly-docker.configuration.password
>
<
arq.extension.docker.serverVersion
>1.15</
arq.extension.docker.serverVersion
>
<
arq.extension.docker.dockerContainers
>
wildfly-docker:
image: arungupta/javaee7-samples-wildfly
exposedPorts: [8080/tcp, 9990/tcp]
await:
strategy: polling
sleepPollingTime: 50000
iterations: 5
portBindings: [8080/tcp, 9990/tcp]
</
arq.extension.docker.dockerContainers
>
</
systemPropertyVariables
>
</
configuration
>
Username and password are specified are for the WildFly in arungupta/javaee7-samples-wildfly image. All the configuration values can be overridden by arquillian.xml for each test case, as explained here.
How do you try out this functionality?
1 2 3 | git clone https: //github.com/javaee-samples/javaee7-samples.git git checkout docker mvn test -f servlet/simple-servlet/pom.xml -Pwildfly-docker-arquillian |
Here is a complete log of running simple-servlet test:
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 | Running org.javaee7.servlet.metadata.complete.SimpleServletTest SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder" . SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http: //www.slf4j.org/codes.html#StaticLoggerBinder for further details. Dec 04 , 2014 11 : 19 : 51 AM org.glassfish.jersey.filter.LoggingFilter log INFO: 1 * Sending client request on thread main 1 > GET http: //127.0.0.1:2375/v1.15/_ping Dec 04 , 2014 11 : 19 : 51 AM org.glassfish.jersey.filter.LoggingFilter log INFO: 2 * Client response received on thread main 2 < 200 2 < Content-Length: 2 2 < Content-Type: application/json; charset=utf- 8 2 < Date: Thu, 04 Dec 2014 19 : 19 : 51 GMT OK Dec 04 , 2014 11 : 19 : 51 AM org.glassfish.jersey.filter.LoggingFilter log INFO: 3 * Sending client request on thread main 3 > POST http: //127.0.0.1:2375/v1.15/containers/create?name=wildfly-docker 3 > Accept: application/json 3 > Content-Type: application/json { "name" : "wildfly-docker" , "Hostname" : "" , "User" : "" , "Memory" : 0 , "MemorySwap" : 0 , "CpuShares" : 0 , "AttachStdin" : false , "AttachStdout" : false , "AttachStderr" : false , "PortSpecs" : null , "Tty" : false , "OpenStdin" : false , "StdinOnce" : false , "Env" : null , "Cmd" : null , "Dns" : null , "Image" : "arungupta/javaee7-samples-wildfly" , "Volumes" :{}, "VolumesFrom" :[], "WorkingDir" : "" , "DisableNetwork" : false , "ExposedPorts" :{ "8080/tcp" :{}, "9990/tcp" :{}}} Dec 04 , 2014 11 : 19 : 51 AM org.glassfish.jersey.filter.LoggingFilter log INFO: 4 * Client response received on thread main 4 < 201 4 < Content-Length: 90 4 < Content-Type: application/json 4 < Date: Thu, 04 Dec 2014 19 : 19 : 51 GMT { "Id" : "d2fc85815256be7540ae85fef1ecb26a666a41a591e2adfae8aa6a32fde3393b" , "Warnings" : null } Dec 04 , 2014 11 : 19 : 51 AM org.arquillian.cube.impl.docker.DockerClientExecutor assignPorts INFO: Only exposed port is set and it will be used as port binding as well. 8080 /tcp Dec 04 , 2014 11 : 19 : 51 AM org.arquillian.cube.impl.docker.DockerClientExecutor assignPorts INFO: Only exposed port is set and it will be used as port binding as well. 9990 /tcp Dec 04 , 2014 11 : 19 : 52 AM org.glassfish.jersey.filter.LoggingFilter log INFO: 5 * Sending client request on thread main 5 > POST http: //127.0.0.1:2375/v1.15/containers/wildfly-docker/start 5 > Accept: application/json 5 > Content-Type: application/json { "containerId" : "wildfly-docker" , "Binds" :[], "Links" :[], "LxcConf" : null , "PortBindings" :{ "8080/tcp" :[{ "HostIp" : "" , "HostPort" : "8080" }], "9990/tcp" :[{ "HostIp" : "" , "HostPort" : "9990" }]}, "PublishAllPorts" : false , "Privileged" : false , "Dns" : null , "DnsSearch" : null , "VolumesFrom" : null , "NetworkMode" : "bridge" , "Devices" : null , "RestartPolicy" : null , "CapAdd" : null , "CapDrop" : null } Dec 04 , 2014 11 : 19 : 52 AM org.glassfish.jersey.filter.LoggingFilter log INFO: 6 * Client response received on thread main 6 < 204 6 < Date: Thu, 04 Dec 2014 19 : 19 : 52 GMT Dec 04 , 2014 11 : 19 : 52 AM org.glassfish.jersey.filter.LoggingFilter log INFO: 7 * Sending client request on thread main 7 > GET http: //127.0.0.1:2375/v1.15/containers/wildfly-docker/json 7 > Accept: application/json Dec 04 , 2014 11 : 19 : 52 AM org.glassfish.jersey.filter.LoggingFilter log INFO: 8 * Client response received on thread main 8 < 200 8 < Content-Type: application/json 8 < Date: Thu, 04 Dec 2014 19 : 19 : 52 GMT 8 < Transfer-Encoding: chunked { "Args" :[ "-b" , "0.0.0.0" , "-bmanagement" , "0.0.0.0" ], "Config" :{ "AttachStderr" : false , "AttachStdin" : false , "AttachStdout" : false , "Cmd" :[ "/opt/wildfly/bin/standalone.sh" , "-b" , "0.0.0.0" , "-bmanagement" , "0.0.0.0" ], "CpuShares" : 0 , "Cpuset" : "" , "Domainname" : "" , "Entrypoint" : null , "Env" :[ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" , "WILDFLY_VERSION=8.1.0.Final" , "JBOSS_HOME=/opt/wildfly" ], "ExposedPorts" :{ "8080/tcp" :{}, "9990/tcp" :{}}, "Hostname" : "d2fc85815256" , "Image" : "arungupta/javaee7-samples-wildfly" , "Memory" : 0 , "MemorySwap" : 0 , "NetworkDisabled" : false , "OnBuild" : null , "OpenStdin" : false , "PortSpecs" : null , "SecurityOpt" : null , "StdinOnce" : false , "Tty" : false , "User" : "wildfly" , "Volumes" : null , "WorkingDir" : "" }, "Created" : "2014-12-04T19:19:51.7226858Z" , "Driver" : "devicemapper" , "ExecDriver" : "native-0.2" , "HostConfig" :{ "Binds" :[], "CapAdd" : null , "CapDrop" : null , "ContainerIDFile" : "" , "Devices" : null , "Dns" : null , "DnsSearch" : null , "ExtraHosts" : null , "Links" : null , "LxcConf" : null , "NetworkMode" : "bridge" , "PortBindings" :{ "8080/tcp" :[{ "HostIp" : "" , "HostPort" : "8080" }], "9990/tcp" :[{ "HostIp" : "" , "HostPort" : "9990" }]}, "Privileged" : false , "PublishAllPorts" : false , "RestartPolicy" :{ "MaximumRetryCount" : 0 , "Name" : "" }, "VolumesFrom" : null }, "HostnamePath" : "/var/lib/docker/containers/d2fc85815256be7540ae85fef1ecb26a666a41a591e2adfae8aa6a32fde3393b/hostname" , "HostsPath" : "/var/lib/docker/containers/d2fc85815256be7540ae85fef1ecb26a666a41a591e2adfae8aa6a32fde3393b/hosts" , "Id" : "d2fc85815256be7540ae85fef1ecb26a666a41a591e2adfae8aa6a32fde3393b" , "Image" : "3d08e8466496412daadeba7bb35b5b64d29b32adedd64472ad775d6da5011913" , "MountLabel" : "system_u:object_r:svirt_sandbox_file_t:s0:c34,c113" , "Name" : "/wildfly-docker" , "NetworkSettings" :{ "Bridge" : "docker0" , "Gateway" : "172.17.42.1" , "IPAddress" : "172.17.0.7" , "IPPrefixLen" : 16 , "MacAddress" : "02:42:ac:11:00:07" , "PortMapping" : null , "Ports" :{ "8080/tcp" :[{ "HostIp" : "0.0.0.0" , "HostPort" : "8080" }], "9990/tcp" :[{ "HostIp" : "0.0.0.0" , "HostPort" : "9990" }]}}, "Path" : "/opt/wildfly/bin/standalone.sh" , "ProcessLabel" : "system_u:system_r:svirt_lxc_net_t:s0:c34,c113" , "ResolvConfPath" : "/var/lib/docker/containers/d2fc85815256be7540ae85fef1ecb26a666a41a591e2adfae8aa6a32fde3393b/resolv.conf" , "State" :{ "ExitCode" : 0 , "FinishedAt" : "0001-01-01T00:00:00Z" , "Paused" : false , "Pid" : 11406 , "Restarting" : false , "Running" : true , "StartedAt" : "2014-12-04T19:19:52.378418242Z" }, "Volumes" :{}, "VolumesRW" :{}} Dec 04 , 2014 11 : 20 : 44 AM org.xnio.Xnio <clinit> INFO: XNIO version 3.2 . 0 .Beta2 Dec 04 , 2014 11 : 20 : 44 AM org.xnio.nio.NioXnio <clinit> INFO: XNIO NIO Implementation Version 3.2 . 0 .Beta2 Dec 04 , 2014 11 : 20 : 44 AM org.jboss.remoting3.EndpointImpl <clinit> INFO: JBoss Remoting version (unknown) Tests run: 2 , Failures: 0 , Errors: 0 , Skipped: 0 , Time elapsed: 65.635 sec - in org.javaee7.servlet.metadata.complete.SimpleServletTest Dec 04 , 2014 11 : 20 : 54 AM org.glassfish.jersey.filter.LoggingFilter log INFO: 9 * Sending client request on thread main 9 > POST http: //127.0.0.1:2375/v1.15/containers/wildfly-docker/stop?t=10 9 > Accept: application/json 9 > Content-Type: application/json Dec 04 , 2014 11 : 21 : 04 AM org.glassfish.jersey.filter.LoggingFilter log INFO: 10 * Client response received on thread main 10 < 204 10 < Date: Thu, 04 Dec 2014 19 : 21 : 04 GMT Dec 04 , 2014 11 : 21 : 04 AM org.glassfish.jersey.filter.LoggingFilter log INFO: 11 * Sending client request on thread main 11 > DELETE http: //127.0.0.1:2375/v1.15/containers/wildfly-docker?v=0&force=0 11 > Accept: application/json Dec 04 , 2014 11 : 21 : 05 AM org.glassfish.jersey.filter.LoggingFilter log INFO: 12 * Client response received on thread main 12 < 204 12 < Date: Thu, 04 Dec 2014 19 : 21 : 05 GMT Results : Tests run: 2 , Failures: 0 , Errors: 0 , Skipped: 0 [INFO] [INFO] --- maven-surefire-plugin: 2.17 :test (spock-test) @ simple-servlet --- [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1 : 27 .831s [INFO] Finished at: Thu Dec 04 11 : 21 : 05 PST 2014 [INFO] Final Memory: 21M/59M [INFO] ------------------------------------------------------------------------ |
REST payload from the client to Docker server are shown here. This was verified on a Fedora 20 Virtual Box image. Here are some quick notes on setting it up there:
- Install the required packages12
yum install docker-io git maven
yum upgrade selinux-policy
- Configure Docker123
sudo vi /etc/sysconfig/docker
Change to
"OPTIONS=--selinux-enabled -H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock"
sudo service docker start
- Verify Docker TCP configuration0102030405060708091011
docker -H tcp:
//127.0.0.1:2375 version
Client version:
1.3
.
1
Client API version:
1.15
Go version (client): go1.
3.3
Git commit (client): 4e9bbfa/
1.3
.
1
OS/Arch (client): linux/amd64
Server version:
1.3
.
1
Server API version:
1.15
Go version (server): go1.
3.3
Git commit (server): 4e9bbfa/
1.3
.
1
Boot2docker on Mac still has issue #49, this is Alpha2 after all!
Try some other Java EE 7 tests and file bugs here.
Enjoy!
Reference: | Run Java EE Tests on Docker using Arquillian Cube from our JCG partner Arun Gupta at the Miles to go 2.0 … blog. |