2 Replies Latest reply on May 2, 2012 9:15 AM by david_kiss

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

    david_kiss

      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.j.allen

          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.

          1 of 1 people found this helpful
          • 2. Re: Arquillian test fails in an embedded Tomcat if there's a CDI Extension on test classpath
            david_kiss

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