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
2
3
|
mvn -f jaxrs/jaxrs-client/pom.xml clean package -DskipTests
|
The exact Dockerfile is shown here:
1
2
3
4
|
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:
12345678<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.:
123456789101112131415161718192021<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.serverUri>http://127.0.0.1:2375</arq.extension.docker.serverUri><arq.extension.docker.dockerContainers>wildfly-docker:image: arungupta/javaee7-samples-wildflyexposedPorts: [8080/tcp, 9990/tcp]await:strategy: pollingsleepPollingTime: 50000iterations: 5portBindings: [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
4
5
|
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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
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 packages
1234yum install docker-io git mavenyum upgrade selinux-policy - Configure Docker
12345sudo vi /etc/sysconfig/dockerChange to "OPTIONS=--selinux-enabled -H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock"sudo service docker start - Verify Docker TCP configuration
12345678910111213docker -H tcp://127.0.0.1:2375 versionClient version: 1.3.1Client API version: 1.15Go version (client): go1.3.3Git commit (client): 4e9bbfa/1.3.1OS/Arch (client): linux/amd64Server version: 1.3.1Server API version: 1.15Go version (server): go1.3.3Git 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!
One thought on “Run Java EE Tests on Docker using Arquillian Cube (Tech Tip #62)”