Testing Liferay plugins is not an easy task. Nowadays, integration tests in Liferay are easier using Arquillian. Arquillian is an innovative and highly extensible testing platform for the JVM that enables developers to easily create automated integration, functional and acceptance tests for Java middleware. In this post we are going to write the steps you need to follow in order to Arquillian works and we will also describe some of the errors that you could find.
Basically, you have to take into account:
- Review your Tomcat
- Is JMX enabled on Tomcat?
- Is tomcat-users configured?
- Is tomcat's manager installed?
- Review your plugin
- Does the arquillian.xml exist in the plugin's test classpath?
- Does the arquillian.xml point to the tomcat (URL and port)?
- Is IVY resolving arquillian dependencies, and putting them into your classpath?
- Do you have "SDK/portlets/my-portlet/test/integration" as folder structure?
- Before testing your plugin, is Tomcat running?
Firstly, you have to configure our Tomcat. In theory, you can configure your Tomcat running ant setup-testable-tomcat on root folder of plugins SDK, only the first time you start with sdk. However, I have to say that it didn't work for me, and it was difficult to find this ant task. I had to look for it on the Internet and when I run it I got several errors. In the end, I had to set up each file manually.
For enabling JMX on Tomcat, go to TOMCAT_HOME/bin directory and add this line after original CATALINA_OPTS definition:
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.port=8099 -Dcom.sun.management.jmxremote.ssl=false
If you prefer, you can also, change directly your setenv.sh (or setenv.bat) and add
JMX_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.port=8099 -Dcom.sun.management.jmxremote.ssl=false"
CATALINA_OPTS="$CATALINA_OPTS -Dfile.encoding=UTF8 -Djava.net.preferIPv4Stack=true -Dorg.apache.catalina.loader.WebappClassLoader.ENABLE_CLEAR_REFERENCES=false -Duser.timezone=GMT -Xmx1024m -XX:MaxPermSize=256m $JMX_OPTS"
However, because I work with Eclipse Liferay IDE, I put this line in the configuration of my Liferay Server (clicking on Open launch configuration).
Secondly, you need to configure tomcat's manager users and roles. Modify your tomcat-users.xml with this
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="tomcat"/>
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<role rolename="manager-jmx"/>
<role rolename="manager-status"/>
<user password="tomcat" roles="tomcat,manager-gui,manager-script,manager-jmx,manager-status" username="tomcat"/>
</tomcat-users>
Thirdly, you have to install Tomcat's manager as web application under webapps. You can download it from here.
Then you have to untar the file under webapps directory. The result is:
x manager/
x manager/status.xsd
x manager/WEB-INF/
x manager/WEB-INF/jsp/
x manager/WEB-INF/jsp/401.jsp
x manager/WEB-INF/jsp/403.jsp
x manager/WEB-INF/jsp/sessionsList.jsp
x manager/WEB-INF/jsp/404.jsp
x manager/WEB-INF/jsp/sessionDetail.jsp
x manager/WEB-INF/web.xml
x manager/images/
x manager/images/update.gif
x manager/images/docs.gif
x manager/images/asf-logo.gif
x manager/images/fix.gif
x manager/images/code.gif
x manager/images/add.gif
x manager/images/tomcat.gif
x manager/images/design.gif
x manager/images/void.gif
x manager/xform.xsl
x manager/index.jsp
x manager/META-INF/
x manager/META-INF/context.xml
Arquillian communicates with this application to deploy your tests on the container.
Now check that manager application works. For that, go to http://localhost:8080/manager and use the credential tomcat/tomcat. If everything is ok, you will a list of yourt applications in your Tomcat.
If something is wrong with manager application, when you test your plugin, you can get an error similar to:
org.jboss.arquillian.container.spi.client.container.DeploymentException: Unable to deploy an archive arquillian-test-portlet.war
at org.jboss.arquillian.container.tomcat.remote_7.TomcatRemoteContainer.deploy(TomcatRemoteContainer.java:123)
at org.jboss.arquillian.container.impl.client.container.ContainerDeployController$3.call(ContainerDeployController.java:161)
at org.jboss.arquillian.container.impl.client.container.ContainerDeployController$3.call(ContainerDeployController.java:128)
at org.jboss.arquillian.container.impl.client.container.ContainerDeployController.executeOperation(ContainerDeployController.java:271)
at org.jboss.arquillian.container.impl.client.container.ContainerDeployController.deploy(ContainerDeployController.java:127)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94)
at org.jboss.arquillian.core.impl.EventContextImpl.invokeObservers(EventContextImpl.java:99)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:81)
at org.jboss.arquillian.container.impl.client.container.DeploymentExceptionHandler.verifyExpectedExceptionDuringDeploy(DeploymentExceptionHandler.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:88)
at org.jboss.arquillian.container.impl.client.ContainerDeploymentContextHandler.createDeploymentContext(ContainerDeploymentContextHandler.java:78)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:88)
at org.jboss.arquillian.container.impl.client.ContainerDeploymentContextHandler.createContainerContext(ContainerDeploymentContextHandler.java:57)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:88)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:145)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:116)
at org.jboss.arquillian.core.impl.EventImpl.fire(EventImpl.java:67)
at org.jboss.arquillian.container.impl.client.container.ContainerDeployController$1.perform(ContainerDeployController.java:95)
at org.jboss.arquillian.container.impl.client.container.ContainerDeployController$1.perform(ContainerDeployController.java:80)
at org.jboss.arquillian.container.impl.client.container.ContainerDeployController.forEachDeployment(ContainerDeployController.java:263)
at org.jboss.arquillian.container.impl.client.container.ContainerDeployController.forEachManagedDeployment(ContainerDeployController.java:239)
at org.jboss.arquillian.container.impl.client.container.ContainerDeployController.deployManaged(ContainerDeployController.java:79)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94)
at org.jboss.arquillian.core.impl.EventContextImpl.invokeObservers(EventContextImpl.java:99)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:81)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:145)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:116)
at org.jboss.arquillian.core.impl.EventImpl.fire(EventImpl.java:67)
at org.jboss.arquillian.container.test.impl.client.ContainerEventController.execute(ContainerEventController.java:101)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94)
at org.jboss.arquillian.core.impl.EventContextImpl.invokeObservers(EventContextImpl.java:99)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:81)
at org.jboss.arquillian.test.impl.TestContextHandler.createClassContext(TestContextHandler.java:92)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:88)
at org.jboss.arquillian.test.impl.TestContextHandler.createSuiteContext(TestContextHandler.java:73)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:88)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:145)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:116)
at org.jboss.arquillian.test.impl.EventTestRunnerAdaptor.beforeClass(EventTestRunnerAdaptor.java:87)
at org.jboss.arquillian.junit.Arquillian$2.evaluate(Arquillian.java:201)
at org.jboss.arquillian.junit.Arquillian.multiExecute(Arquillian.java:422)
at org.jboss.arquillian.junit.Arquillian.access$200(Arquillian.java:54)
at org.jboss.arquillian.junit.Arquillian$3.evaluate(Arquillian.java:218)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.jboss.arquillian.junit.Arquillian.run(Arquillian.java:166)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.io.IOException: Error writing request body to server
at sun.net.www.protocol.http.HttpURLConnection$StreamingOutputStream.checkError(HttpURLConnection.java:3205)
at sun.net.www.protocol.http.HttpURLConnection$StreamingOutputStream.write(HttpURLConnection.java:3188)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:122)
at org.jboss.arquillian.container.tomcat.IOUtil.copy(IOUtil.java:140)
at org.jboss.arquillian.container.tomcat.CommonTomcatManager.execute(CommonTomcatManager.java:224)
at org.jboss.arquillian.container.tomcat.CommonTomcatManager.deploy(CommonTomcatManager.java:92)
at org.jboss.arquillian.container.tomcat.remote\_7.TomcatRemoteContainer.deploy(TomcatRemoteContainer.java:119)
... 87 more
Reviewing your plugin
You have to configure your pluging to use arquillian, executing ant setup-arquillian on root folder of your plugin. I didn't do that. You can configure your plugin manually or, better, you can create your plugin using Liferay IDE wizard. When you create a plugin with Liferay IDE (version 2.2.5-ga5), the wizard
- will create for you the archive arquillian.xml under /test/integration, to define the credentials to log in the tomcat's manager
- and will add Arquillian dependencies in ivy.xml
The arquillian.xml should be similiar to:
<?xml version="1.0"?>
<arquillian
xmlns="http://jboss.org/schema/arquillian"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian\_1\_0.xsd"
>
<container default="true" qualifier="tomcat">
<configuration>
<property name="jmxPort">8099</property>
<property name="pass">tomcat</property>
<property name="user">tomcat</property>
</configuration>
</container>
</arquillian>
Perhaps you need add host and httpPort properties if your tomcat is not at localhost:8080.
By default, your ivy.xml will have the following dependencies:
<dependency conf="test->default" name="arquillian-junit-container" org="org.jboss.arquillian.junit" rev="1.1.6.Final" />
<dependency conf="test->default" name="arquillian-tomcat-remote-7" org="org.jboss.arquillian.container" rev="1.0.0.CR6" />
<dependency conf="test->default" name="com.liferay.ant.arquillian" org="com.liferay" rev="1.0.0-SNAPSHOT" />
However, you must upgrade arquillian version to 1.0.1 or 1.0.2. For example, your ivy.xml should be
<dependency conf="test->default" name="arquillian-junit-container" org="org.jboss.arquillian.junit" rev="1.1.8.Final" />
<dependency conf="test->default" name="arquillian-tomcat-remote-7" org="org.jboss.arquillian.container" rev="1.0.0.CR7" />
<dependency conf="test->default" name="com.liferay.ant.arquillian" org="com.liferay" rev="1.0.2" />
If you don't upgrade arquillian version, you will get an error similar to:
java.lang.NoSuchMethodError: com.liferay.portal.kernel.process.ProcessUtil.execute(Lcom/liferay/portal/kernel/process/OutputProcessor;\[Ljava/lang/String;)Lcom/liferay/portal/kernel/concurrent/NoticeableFuture;
at com.liferay.ant.arquillian.WebArchiveBuilder.build(WebArchiveBuilder.java:41)
at com.liferay.ant.arquillian.generator.AntDeploymentScenarioGenerator.generate(AntDeploymentScenarioGenerator.java:47)
at org.jboss.arquillian.container.test.impl.client.deployment.DeploymentGenerator.generateDeployment(DeploymentGenerator.java:79)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94)
at org.jboss.arquillian.core.impl.EventContextImpl.invokeObservers(EventContextImpl.java:99)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:81)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:145)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:116)
at org.jboss.arquillian.core.impl.EventImpl.fire(EventImpl.java:67)
at org.jboss.arquillian.container.test.impl.client.ContainerEventController.execute(ContainerEventController.java:100)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94)
at org.jboss.arquillian.core.impl.EventContextImpl.invokeObservers(EventContextImpl.java:99)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:81)
at org.jboss.arquillian.test.impl.TestContextHandler.createSuiteContext(TestContextHandler.java:65)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:88)
at org.jboss.arquillian.test.impl.TestContextHandler.createClassContext(TestContextHandler.java:84)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:88)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:145)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:116)
at org.jboss.arquillian.test.impl.EventTestRunnerAdaptor.beforeClass(EventTestRunnerAdaptor.java:86)
at org.jboss.arquillian.junit.Arquillian$2.evaluate(Arquillian.java:199)
at org.jboss.arquillian.junit.Arquillian.multiExecute(Arquillian.java:377)
at org.jboss.arquillian.junit.Arquillian.access$200(Arquillian.java:52)
at org.jboss.arquillian.junit.Arquillian$3.evaluate(Arquillian.java:216)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.jboss.arquillian.junit.Arquillian.run(Arquillian.java:164)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Needless to say, you will need a JUnit dependency such as, for example,
<dependency conf="test->default" name="junit" org="junit" rev="4.12"/>
Creating a test class under test/integration folder
A regular class to be tested with Arquillian could be
package com.lostinsoftware.arquillian.test;
import org.jboss.arquillian.junit.Arquillian;
import org.junit.Test;
import org.junit.runner.RunWith;
import com.liferay.counter.service.CounterLocalServiceUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.model.User;
import com.liferay.portal.service.UserLocalServiceUtil;
@RunWith(Arquillian.class)
public class ArquillianPortletTest
{
@Test
public void testUserLocalService() throws Exception
{
User user = UserLocalServiceUtil.createUser( CounterLocalServiceUtil.increment() );
if (Validator.isNotNull(user))
assert(true);
else
assert(false);
}
}
Notice you need @RunWith(Arquillian.class). You don't need to use @Deployment annotation in any method. Before testing your class, Tomcat must be running. Don't deploy your plugin: Arquillian will deploy and undeploy it for you.
After starting up Tomcat, check that port JMX 8099 is open and listing
LostInSoftware:liferay-plugins-sdk-6.2-ce-ga6 lostinsoftware$ lsof -i -P | grep -i LISTEN
mysqld 970 lostinsoftware 10u IPv4 0x1d2d222596b45c9f 0t0 TCP \*:3306 (LISTEN)
httpd 996 lostinsoftware 7u IPv6 0x1d2d22258e69e5bf 0t0 TCP \*:80 (LISTEN)
httpd 997 lostinsoftware 7u IPv6 0x1d2d22258e69e5bf 0t0 TCP \*:80 (LISTEN)
httpd 998 lostinsoftware 7u IPv6 0x1d2d22258e69e5bf 0t0 TCP \*:80 (LISTEN)
httpd 999 lostinsoftware 7u IPv6 0x1d2d22258e69e5bf 0t0 TCP \*:80 (LISTEN)
httpd 1010 lostinsoftware 7u IPv6 0x1d2d22258e69e5bf 0t0 TCP \*:80 (LISTEN)
httpd 1015 lostinsoftware 7u IPv6 0x1d2d22258e69e5bf 0t0 TCP \*:80 (LISTEN)
httpd 1016 lostinsoftware 7u IPv6 0x1d2d22258e69e5bf 0t0 TCP \*:80 (LISTEN)
httpd 1017 lostinsoftware 7u IPv6 0x1d2d22258e69e5bf 0t0 TCP \*:80 (LISTEN)
httpd 1018 lostinsoftware 7u IPv6 0x1d2d22258e69e5bf 0t0 TCP \*:80 (LISTEN)
eclipse 4129 lostinsoftware 183u IPv6 0x1d2d22259d72299f 0t0 TCP \*:53703 (LISTEN)
httpd 7896 lostinsoftware 7u IPv6 0x1d2d22258e69e5bf 0t0 TCP \*:80 (LISTEN)
java 8361 lostinsoftware 30u IPv4 0x1d2d22259e42bc9f 0t0 TCP \*:55775 (LISTEN)
java 8361 lostinsoftware 31u IPv4 0x1d2d2225a06cd54f 0t0 TCP \*:8099 (LISTEN)
java 8361 lostinsoftware 32u IPv4 0x1d2d22259292e54f 0t0 TCP \*:55776 (LISTEN)
java 8361 lostinsoftware 75u IPv4 0x1d2d222590353c9f 0t0 TCP \*:8080 (LISTEN)
java 8361 lostinsoftware 76u IPv4 0x1d2d22259e42654f 0t0 TCP \*:8009 (LISTEN)
java 8361 lostinsoftware 80u IPv4 0x1d2d2225923c5c9f 0t0 TCP localhost:8005 (LISTEN)
When you run your test from Eclipse
in Tomcat's console the log is similar to
21:20:55,261 INFO \[http-bio-8080-exec-35\]\[HotDeployEvent:145\] Plugin arquillian-test-portlet requires marketplace-portlet
21:20:55,273 INFO \[http-bio-8080-exec-35\]\[PortletHotDeployListener:525\] Unregistering portlets for arquillian-test-portlet
21:20:55,274 INFO \[http-bio-8080-exec-35\]\[PortletHotDeployListener:560\] 1 portlet for arquillian-test-portlet was unregistered
21:20:55,275 INFO \[http-bio-8080-exec-35\]\[HookHotDeployListener:982\] Hook for arquillian-test-portlet was unregistered
ene 15, 2016 9:20:55 PM org.apache.catalina.core.ApplicationContext log
INFORMACIÓN: Closing Spring root WebApplicationContext
21:20:55,276 INFO \[http-bio-8080-exec-35\]\[PluginPackageUtil:1016\] Reading plugin package for arquillian-test-portlet
ene 15, 2016 9:20:55 PM org.apache.catalina.startup.HostConfig undeploy
INFORMACIÓN: Repliegue (undeploy) de la aplicación web que tiene como trayectoria de contexto /arquillian-test-portlet
ene 15, 2016 9:22:51 PM org.apache.catalina.startup.HostConfig deployWAR
INFORMACIÓN: Despliegue del archivo /Applications/Liferay/ce-ga6/liferay-portal-6.2-ce-ga6/tomcat-7.0.62/webapps/arquillian-test-portlet.war de la aplicación web
ene 15, 2016 9:22:53 PM org.apache.catalina.startup.TldConfig execute
INFORMACIÓN: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
21:22:53,627 INFO \[http-bio-8080-exec-39\]\[HotDeployEvent:145\] Plugin arquillian-test-portlet requires marketplace-portlet
21:22:53,643 INFO \[http-bio-8080-exec-39\]\[HotDeployImpl:217\] Deploying arquillian-test-portlet from queue
21:22:53,643 INFO \[http-bio-8080-exec-39\]\[PluginPackageUtil:1016\] Reading plugin package for arquillian-test-portlet
ene 15, 2016 9:22:54 PM org.apache.catalina.core.ApplicationContext log
INFORMACIÓN: Initializing Spring root WebApplicationContext
21:22:54,018 INFO \[http-bio-8080-exec-39\]\[HookHotDeployListener:709\] Registering hook for arquillian-test-portlet
21:22:54,021 INFO \[http-bio-8080-exec-39\]\[HookHotDeployListener:851\] Hook for arquillian-test-portlet is available for use
21:22:54,022 INFO \[http-bio-8080-exec-39\]\[PortletHotDeployListener:344\] Registering portlets for arquillian-test-portlet
21:22:54,052 INFO \[http-bio-8080-exec-39\]\[PortletHotDeployListener:492\] 1 portlet for arquillian-test-portlet is available for use
21:22:54,579 INFO \[StartupListener:50\] Context initialized for contextPath=\[/arquillian-test-portlet\]
21:22:54,589 INFO \[StartupListener:77\] Copied input-editor.jsp from LiferayFaces JAR to context path file=\[/Applications/Liferay/ce-ga6/liferay-portal-6.2-ce-ga6/tomcat-7.0.62/temp/9-arquillian-test-portlet/resources/liferay-ui/jsp/input-editor.jsp\]
21:22:54,589 INFO \[BridgeSessionListener:96\] Context initialized for contextPath=\[/arquillian-test-portlet\]
ene 15, 2016 9:22:54 PM org.apache.catalina.startup.HostConfig deployWAR
INFORMACIÓN: Deployment of web application archive /Applications/Liferay/ce-ga6/liferay-portal-6.2-ce-ga6/tomcat-7.0.62/webapps/arquillian-test-portlet.war has finished in 2.969 ms
21:23:20,754 INFO \[http-bio-8080-exec-45\]\[HotDeployEvent:145\] Plugin arquillian-test-portlet requires marketplace-portlet
21:23:20,755 INFO \[http-bio-8080-exec-45\]\[PortletHotDeployListener:525\] Unregistering portlets for arquillian-test-portlet
21:23:20,756 INFO \[http-bio-8080-exec-45\]\[PortletHotDeployListener:560\] 1 portlet for arquillian-test-portlet was unregistered
21:23:20,756 INFO \[http-bio-8080-exec-45\]\[HookHotDeployListener:982\] Hook for arquillian-test-portlet was unregistered
ene 15, 2016 9:23:20 PM org.apache.catalina.core.ApplicationContext log
INFORMACIÓN: Closing Spring root WebApplicationContext
21:23:20,758 INFO \[http-bio-8080-exec-45\]\[PluginPackageUtil:1016\] Reading plugin package for arquillian-test-portlet
ene 15, 2016 9:23:21 PM org.apache.catalina.startup.HostConfig undeploy
INFORMACIÓN: Repliegue (undeploy) de la aplicación web que tiene como trayectoria de contexto /arquillian-test-portlet
and the log in our JUnit console is
ene 15, 2016 10:22:54 PM org.jboss.arquillian.container.tomcat.ProtocolMetadataParser connect
INFORMACIÓN: Connecting to JMX at service:jmx:rmi:///jndi/rmi://localhost:8099/jmxrmi
Testing on Windows
If you are testing your Liferay plugins on Windows you may get the following error
java.lang.RuntimeException: java.io.IOException: Cannot run program "ant": CreateProcess error=2, The system cannot find the file specified
at com.liferay.ant.arquillian.WebArchiveBuilder.build(WebArchiveBuilder.java:59)
at com.liferay.ant.arquillian.generator.AntDeploymentScenarioGenerator.generate(AntDeploymentScenarioGenerator.java:46)
at org.jboss.arquillian.container.test.impl.client.deployment.DeploymentGenerator.generateDeployment(DeploymentGenerator.java:79)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94)
at org.jboss.arquillian.core.impl.EventContextImpl.invokeObservers(EventContextImpl.java:99)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:81)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:145)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:116)
at org.jboss.arquillian.core.impl.EventImpl.fire(EventImpl.java:67)
at org.jboss.arquillian.container.test.impl.client.ContainerEventController.execute(ContainerEventController.java:100)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94)
at org.jboss.arquillian.core.impl.EventContextImpl.invokeObservers(EventContextImpl.java:99)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:81)
at org.jboss.arquillian.test.impl.TestContextHandler.createClassContext(TestContextHandler.java:92)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:88)
at org.jboss.arquillian.test.impl.TestContextHandler.createSuiteContext(TestContextHandler.java:73)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:94)
at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:88)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:145)
at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:116)
at org.jboss.arquillian.test.impl.EventTestRunnerAdaptor.beforeClass(EventTestRunnerAdaptor.java:87)
at org.jboss.arquillian.junit.Arquillian$2.evaluate(Arquillian.java:201)
at org.jboss.arquillian.junit.Arquillian.multiExecute(Arquillian.java:422)
at org.jboss.arquillian.junit.Arquillian.access$200(Arquillian.java:54)
at org.jboss.arquillian.junit.Arquillian$3.evaluate(Arquillian.java:218)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.jboss.arquillian.junit.Arquillian.run(Arquillian.java:166)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.io.IOException: Cannot run program "ant": CreateProcess error=2, El sistema no puede encontrar el archivo especificado
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1047)
at com.liferay.ant.arquillian.WebArchiveBuilder.build(WebArchiveBuilder.java:43)
... 49 more
Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessImpl.create(Native Method)
at java.lang.ProcessImpl.<init>(ProcessImpl.java:385)
at java.lang.ProcessImpl.start(ProcessImpl.java:136)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1028)
... 50 more
The method in WebArchiveBuilder class where the exception is thrown is
public static WebArchive build() {
File tempDir = new File(System.getProperty("java.io.tmpdir"));
try {
Future<ObjectValuePair<Void, Void>> future = ProcessUtil.execute(
ProcessUtil.LOGGING\_OUTPUT\_PROCESSOR, "ant", "direct-deploy",
"-Dapp.server.deploy.dir=" + tempDir.getAbsolutePath(),
"-Dauto.deploy.unpack.war=false");
future.get();
}
catch (Exception e) {
throw new RuntimeException(e);
}
Project project = \_getProject();
File warFile = new File(
tempDir.getAbsolutePath(),
project.getProperty("plugin.name") + ".war");
return ShrinkWrap.createFromZipFile(WebArchive.class, warFile);
}
The error occurs because in Windows does not exist ant.exe executable file; there is only the ant.bat file. If you don't specify a file extension, ProcessUtil.execute will only run archives with extension .exe. So you need to convert your ant.bat into ant.exe and, obviously, ant.exe must be in your path (environment variable). For this conversion, you can use several programs, such as http://www.battoexeconverter.com/
Files under a standard apache-ant-1.9.1/bin directory, with a new ant.exe file.
IMHO, I think that the method build() in WebArchiveBuilder class should check the current operating system. If the os is Windows, ProcessUtil.execute should run ant.exe instance of ant.
More information
You can get more information at the following links:
https://www.youtube.com/watch?v=-Qh9a1exhEo
https://www.liferay.com/es/web/jardineworks/blog/-/blogs/arquillian-maven
https://www.youtube.com/watch?v=dO1-Q5TXY8s https://www.youtube.com/watch?v=jPiAymZBGGo
https://www.liferay.com/es/community/forums/-/message_boards/message/39503379
https://www.liferay.com/es/community/forums/-/message_boards/message/49496026