Celebrating a public holiday in middle of the week finally gave me some extra time to play around with OpenShift.
If you are just starting with Arquillian to test persistence this article might come in handy:
http://arquillian.org/guides/testing_java_persistence/
Use Arquillian to test directly in OpenShift
You can use Arquillian to test your application directly in OpenShift. Lets go through the common issues and how to get around them.
You need to treat OpenShift's AS instance as remote container. In your projects pom.xml add a dependency to jboss-as-arquillian-container-remote:
<dependency> <groupId>org.jboss.as</groupId> <artifactId>jboss-as-arquillian-container-remote</artifactId> <scope>test</scope> </dependency>
(just use parent's pom dependency management take care of the version)
If you try to run this configuration while running rhc client tool port forwarding you will run into the following exception (pasting here if anyone is googling for it):
May 08, 2013 3:53:24 PM org.jboss.shrinkwrap.impl.base.exporter.zip.JdkZipExporterDelegate$1 call WARNING: Exception encountered during export of archive org.jboss.shrinkwrap.api.exporter.ArchiveExportException: Failed to write asset to output: /junit/extensions/TestDecorator.class at org.jboss.shrinkwrap.impl.base.exporter.StreamExporterDelegateBase$3.handle(StreamExporterDelegateBase.java:272) at org.jboss.shrinkwrap.impl.base.io.IOUtil.closeOnComplete(IOUtil.java:219) at org.jboss.shrinkwrap.impl.base.exporter.StreamExporterDelegateBase.processNode(StreamExporterDelegateBase.java:233) at org.jboss.shrinkwrap.impl.base.exporter.AbstractExporterDelegate.processNode(AbstractExporterDelegate.java:105) at org.jboss.shrinkwrap.impl.base.exporter.AbstractExporterDelegate.processNode(AbstractExporterDelegate.java:109) at org.jboss.shrinkwrap.impl.base.exporter.AbstractExporterDelegate.processNode(AbstractExporterDelegate.java:109) at org.jboss.shrinkwrap.impl.base.exporter.AbstractExporterDelegate.doExport(AbstractExporterDelegate.java:95) at org.jboss.shrinkwrap.impl.base.exporter.StreamExporterDelegateBase.access$001(StreamExporterDelegateBase.java:50) at org.jboss.shrinkwrap.impl.base.exporter.StreamExporterDelegateBase$1.call(StreamExporterDelegateBase.java:121) at org.jboss.shrinkwrap.impl.base.exporter.StreamExporterDelegateBase$1.call(StreamExporterDelegateBase.java:116) at org.jboss.shrinkwrap.impl.base.exporter.zip.JdkZipExporterDelegate$1.call(JdkZipExporterDelegate.java:124) at org.jboss.shrinkwrap.impl.base.exporter.zip.JdkZipExporterDelegate$1.call(JdkZipExporterDelegate.java:118) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) at java.util.concurrent.FutureTask.run(FutureTask.java:166) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:722) Caused by: java.io.IOException: Pipe closed at java.io.PipedInputStream.checkStateForReceive(PipedInputStream.java:261) at java.io.PipedInputStream.receive(PipedInputStream.java:227) at java.io.PipedOutputStream.write(PipedOutputStream.java:149) at java.util.zip.DeflaterOutputStream.deflate(DeflaterOutputStream.java:253) at java.util.zip.ZipOutputStream.closeEntry(ZipOutputStream.java:238) at org.jboss.shrinkwrap.impl.base.exporter.zip.JdkZipExporterDelegate.closeEntry(JdkZipExporterDelegate.java:84) at org.jboss.shrinkwrap.impl.base.exporter.zip.JdkZipExporterDelegate.closeEntry(JdkZipExporterDelegate.java:40) at org.jboss.shrinkwrap.impl.base.exporter.StreamExporterDelegateBase$2.execute(StreamExporterDelegateBase.java:265) at org.jboss.shrinkwrap.impl.base.exporter.StreamExporterDelegateBase$2.execute(StreamExporterDelegateBase.java:233) at org.jboss.shrinkwrap.impl.base.io.IOUtil.closeOnComplete(IOUtil.java:217) ... 15 more
This is because ARQ failed to authenticate with the server. You will need to add a management user.
Creating a management user
Unfortunately, your instance in OpenShift does not come with the necessary scripting (add-user.sh script). So lets run it locally on your instance and add a user:
[rhusar@x220 jboss-eap-6.0]$ ./bin/add-user.sh
and feed it with your user details. This will generate a password hash which you need to feed to your OpenShift's container configuration:
[rhusar@x220 jboss-eap-6.0]$ cat standalone/configuration/mgmt-users.properties | grep admin admin=c7817ab300e18384b8217c6f7669814f
Now, you can SSH into your OpenShift instance add the generated user to the server's mgmt-users.properties file (there is probably a better way to do this via the git repository). You will find instructions how to ssh in the web console:
https://openshift.redhat.com/app/console/applications/myapplication
Afterwards, you will need to restart the server, click on the restart icon from the console and wait a few minutes.
Update arquillian.xml
Now, configure arquillian.xml in your project to pick up these credentials:
<!-- Remote on OpenShift with port-forwarding --> <container qualifier="openshift-eap6" default="true"> <configuration> <property name="managementAddress">127.0.0.1</property> <property name="managementPort">9999</property> <property name="username">admin</property> <property name="password">mL8oA4sctCe2epf</property> </configuration> </container>
Now run your tests (mvn test) and voila!
[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 45.172s [INFO] Finished at: Wed May 08 15:52:43 CEST 2013 [INFO] Final Memory: 33M/332M [INFO] ------------------------------------------------------------------------
Err, that was not so fast!
Oops, 45 seconds with sample application with 1 deployment? That doesn't seem useful in all cases.
What if we could test only with the database in OpenShift?
So how about you want to test your persistence layer, not necessarily testing in OpenShift's container, but use database running in OpenShift? The client tooling makes this feasible.
First, start the port forwarding client:
[rhusar@x220 myapplication]$ rhc port-forward myapplication Checking available ports ... done Forwarding ports ... To connect to a service running on OpenShift, use the Local address Service Local OpenShift ------- -------------- ---- ---------------- java 127.0.0.1:3528 => 127.5.190.1:3528 java 127.0.0.1:4447 => 127.5.190.1:4447 java 127.0.0.1:5445 => 127.5.190.1:5445 java 127.0.0.1:5455 => 127.5.190.1:5455 java 127.0.0.1:8080 => 127.5.190.1:8080 java 127.0.0.1:9990 => 127.5.190.1:9990 java 127.0.0.1:9999 => 127.5.190.1:9999 mysqld 127.0.0.1:3306 => 127.5.190.1:3306 Press CTRL-C to terminate port forwarding
This is pretty neat! The rhc client is forwarding all ports, which is useful in most cases but if you want to run your container on the same ports, you will run into:
The server is already running! Managed containers does not support connecting to running server instances due to the possible harmful effect of connecting to the wrong server. Please stop server before running or change to another type of container.(..)
Since rhc client does not support selective forwarding of ports, we will need to switch to a different port for our local managed instance. Just tell the configuration to offset the ports by a constant number like this:
<!-- Managed --> <container qualifier="local-eap6-managed" default="true"> <configuration> <property name="jbossHome">target/jboss-eap-6.0</property> <!-- Do not overlap ports with port forward --> <property name="javaVmArguments">-Djboss.socket.binding.port-offset=100</property> <property name="managementPort">10099</property> </configuration> </container>
Now, the same test with starting and stopping of the AS instance took only few seconds:
[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 14.033s [INFO] Finished at: Wed May 08 16:20:36 CEST 2013 [INFO] Final Memory: 30M/343M [INFO] ------------------------------------------------------------------------
Also, make sure that you bundled a persistence.xml or data source with the port forwarded host and port.
Happy persistence testing!