2 Replies Latest reply: May 2, 2012 9:15 AM by David Kiss RSS

Arquillian test fails in an embedded Tomcat if there's a CDI Extension on test classpath

David Kiss Newbie

When Weld is starting up in the embedded Tomcat, it looks for CDI Extension classes based on META-INF/services/javax.enterprise.inject.spi.Extension files in the classpath.

If these files are not added to the Shrinkwrap archive, you'll get an exception similar to the one below.

 

Issue can be reproduced just by adding dependency org.jboss.seam.faces:seam-faces:3.0.2.Final to the tomcat-embedded-6 project (https://github.com/arquillian/arquillian-container-tomcat/tree/master/tomcat-embedded-6) and then running its TomcatEmbeddedInContainerTestCase test.

 

I was expecting Arquillian to only use classes and libraries added to the ShrinkWrap archive. Is there a workaround for that other than adding all maven dependencies with CDI Extension classes to the Deployment artifact?

 

Thanks,

David

 

java.lang.RuntimeException: Service class org.jboss.seam.faces.component.FormValidationTypeOverrideExtension didn't implement the Extension interface

          at org.jboss.weld.util.ServiceLoader.loadClass(ServiceLoader.java:225)

          at org.jboss.weld.util.ServiceLoader.loadService(ServiceLoader.java:205)

          at org.jboss.weld.util.ServiceLoader.loadServiceFile(ServiceLoader.java:177)

          at org.jboss.weld.util.ServiceLoader.reload(ServiceLoader.java:149)

          at org.jboss.weld.util.ServiceLoader.iterator(ServiceLoader.java:292)

          at org.jboss.weld.bootstrap.ExtensionBeanDeployer.addExtensions(ExtensionBeanDeployer.java:84)

          at org.jboss.weld.bootstrap.WeldBootstrap.startInitialization(WeldBootstrap.java:311)

          at org.jboss.weld.environment.servlet.Listener.contextInitialized(Listener.java:151)

          at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4206)

          at org.apache.catalina.core.StandardContext.start(StandardContext.java:4705)

          at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:799)

          at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:779)

          at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:601)

          at org.jboss.arquillian.container.tomcat.embedded_6.TomcatContainer.deploy(TomcatContainer.java:200)

          at org.jboss.arquillian.container.impl.client.container.ContainerDeployController$3.call(ContainerDeployController.java:156)

          at org.jboss.arquillian.container.impl.client.container.ContainerDeployController$3.call(ContainerDeployController.java:123)

          at org.jboss.arquillian.container.impl.client.container.ContainerDeployController.executeOperation(ContainerDeployController.java:266)

          at org.jboss.arquillian.container.impl.client.container.ContainerDeployController.deploy(ContainerDeployController.java:122)

          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

          at java.lang.reflect.Method.invoke(Method.java:597)

          at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:90)

          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:39)

          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

          at java.lang.reflect.Method.invoke(Method.java:597)

          at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:90)

          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:39)

          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

          at java.lang.reflect.Method.invoke(Method.java:597)

          at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:90)

          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:39)

          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

          at java.lang.reflect.Method.invoke(Method.java:597)

          at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:90)

          at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:88)

          at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:134)

          at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:114)

          at org.jboss.arquillian.core.impl.EventImpl.fire(EventImpl.java:67)

          at org.jboss.arquillian.container.impl.client.container.ContainerDeployController$1.perform(ContainerDeployController.java:90)

          at org.jboss.arquillian.container.impl.client.container.ContainerDeployController$1.perform(ContainerDeployController.java:79)

          at org.jboss.arquillian.container.impl.client.container.ContainerDeployController.forEachDeployment(ContainerDeployController.java:258)

          at org.jboss.arquillian.container.impl.client.container.ContainerDeployController.forEachManagedDeployment(ContainerDeployController.java:234)

          at org.jboss.arquillian.container.impl.client.container.ContainerDeployController.deployManaged(ContainerDeployController.java:78)

          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

          at java.lang.reflect.Method.invoke(Method.java:597)

          at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:90)

          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:134)

          at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:114)

          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:39)

          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

          at java.lang.reflect.Method.invoke(Method.java:597)

          at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:90)

          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:75)

          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

          at java.lang.reflect.Method.invoke(Method.java:597)

          at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:90)

          at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:88)

          at org.jboss.arquillian.test.impl.TestContextHandler.createSuiteContext(TestContextHandler.java:60)

          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

          at java.lang.reflect.Method.invoke(Method.java:597)

          at org.jboss.arquillian.core.impl.ObserverImpl.invoke(ObserverImpl.java:90)

          at org.jboss.arquillian.core.impl.EventContextImpl.proceed(EventContextImpl.java:88)

          at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:134)

          at org.jboss.arquillian.core.impl.ManagerImpl.fire(ManagerImpl.java:114)

          at org.jboss.arquillian.test.impl.EventTestRunnerAdaptor.beforeClass(EventTestRunnerAdaptor.java:80)

          at org.jboss.arquillian.junit.Arquillian$2.evaluate(Arquillian.java:182)

          at org.jboss.arquillian.junit.Arquillian.multiExecute(Arquillian.java:314)

          at org.jboss.arquillian.junit.Arquillian.access$100(Arquillian.java:46)

          at org.jboss.arquillian.junit.Arquillian$3.evaluate(Arquillian.java:199)

          at org.junit.runners.ParentRunner.run(ParentRunner.java:236)

          at org.jboss.arquillian.junit.Arquillian.run(Arquillian.java:147)

          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:467)

          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)

          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)

          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

  • 1. Re: Arquillian test fails in an embedded Tomcat if there's a CDI Extension on test classpath
    Dan Allen Master

    This is yet another case of The danger of embedded containers.

     

    Please know that I'm not saying you are wrong to expect this to work. It's just that the problem is a lot more complex than it would appear on the surface. The problem is lack of Java modularity.

     

    The issue here isn't that Arquillian is looking for classes outside of the ShrinkWrap archive. In fact, Arquillian doesn't really even have a role to play here, nor does ShrinkWrap. When you deploy an archive to a "deployable" container like Tomcat (even in embedded mode), it's just a war (or jar or ear) file. The same exact thing would happen if you created a main class in your application and started Tomcat and deployed a war with Weld Servlet in it.

     

    The issue is that your project classpath is trickling down into Tomcat. The classpath includes everything. When Weld starts scanning, the Java 6 ServiceLoader picks up the resource. Weld, on the other hand, has a built-in visibility narrowing mechanism (per the CDI spec). It only acknowledges classes in the same classpath entry as beans.xml, so it doesn't see the matching extension class.

     

    There's no easy solution (yes, there are hard ones) other than don't use an embedded container. Switch to managed. You get nearly the same startup time without any of the headaches. Try embedded again only if managed doesn't deliver, but at least give it a shot.

  • 2. Re: Arquillian test fails in an embedded Tomcat if there's a CDI Extension on test classpath
    David Kiss Newbie

    Thanks for your quick reply. I'll give a shot to the managed container.