11 Replies Latest reply on Feb 26, 2010 6:43 AM by marcgemis

    Error with super simple weld arquillian test

    sboscarine

      Hello,
      I have tried to create a Hello World example using Arquillian Weld.  It worked for awhile and started failing without any changes on my part.  Does anyone have troubleshooting suggestions?  I'm building Arquillian from trunk, so I have the latest version.

       

      Thanks,
      Steven

       

      Here's my error:

       

      java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/faces/component/UIComponent
          at java.lang.ClassLoader.defineClass1(Native Method)
          at java.lang.ClassLoader.defineClass(ClassLoader.java:621)
          at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
          at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
          at java.net.URLClassLoader.access$000(URLClassLoader.java:56)
          at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
          at java.security.AccessController.doPrivileged(Native Method)
          at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
          at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
          at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
          at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
          at org.jboss.weld.resources.DefaultResourceLoader.classForName(DefaultResourceLoader.java:46)
          at org.jboss.weld.util.ApiAbstraction.classForName(ApiAbstraction.java:103)
          at org.jboss.weld.jsf.JsfApiAbstraction.<init>(JsfApiAbstraction.java:43)
          at org.jboss.weld.bootstrap.WeldBootstrap.getImplementationServices(WeldBootstrap.java:305)
          at org.jboss.weld.bootstrap.WeldBootstrap.startContainer(WeldBootstrap.java:272)
          at org.jboss.arquillian.weld.WeldSEContainer.deploy(WeldSEContainer.java:99)
          at org.jboss.arquillian.impl.container.ContainerDeployer.deploy(ContainerDeployer.java:46)
          at org.jboss.arquillian.testng.Arquillian.createAndDeployArtifact(Arquillian.java:74)
          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.testng.internal.MethodHelper.invokeMethod(MethodHelper.java:609)
          at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:421)
          at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:158)
          at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:89)
          at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:169)
          at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:106)
          at org.testng.TestRunner.runWorkers(TestRunner.java:759)
          at org.testng.TestRunner.privateRun(TestRunner.java:592)
          at org.testng.TestRunner.run(TestRunner.java:486)
          at org.testng.SuiteRunner.runTest(SuiteRunner.java:332)
          at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:327)
          at org.testng.SuiteRunner.privateRun(SuiteRunner.java:299)
          at org.testng.SuiteRunner.run(SuiteRunner.java:204)
          at org.testng.TestNG.createAndRunSuiteRunners(TestNG.java:912)
          at org.testng.TestNG.runSuitesLocally(TestNG.java:876)
          at org.testng.TestNG.run(TestNG.java:784)
          at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:62)
          at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:141)
          at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
          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.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:345)
          at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1009)

       


      Here's my POM:

       

              <dependency>
                  <groupId>org.jboss.arquillian</groupId>
                  <artifactId>arquillian-weld-embedded</artifactId>
                  <version>1.0.0-SNAPSHOT</version>

                  <scope>test</scope>
              </dependency>
              <dependency>
                  <groupId>org.jboss.arquillian</groupId>
                  <artifactId>arquillian-testng</artifactId>
                  <version>1.0.0-SNAPSHOT</version>

                  <scope>test</scope>
              </dependency>

       

      Here's the class:
      package org.bogus;

       

      import javax.inject.Inject;
      import javax.inject.Named;

       

      @Named
      public class SimpleDIExample {
          @Inject
          private SimpleDIExChild child;

       

          public SimpleDIExChild getChild() {
              return child;
          }

       

          public void setChild(SimpleDIExChild child) {
              this.child = child;
          }

       

          @Named
          public static class SimpleDIExChild {
              private String text = "hello world";

       

              public String getText() {
                  return text;
              }
          }
      }

       

       


      Here's the test:

       

       

       

      package org.bogus;

       

      import javax.inject.Inject;

       

      import org.jboss.arquillian.api.Deployment;
      import org.jboss.arquillian.testng.Arquillian;
      import org.jboss.shrinkwrap.api.Archives;
      import org.jboss.shrinkwrap.api.Paths;
      import org.jboss.shrinkwrap.api.spec.JavaArchive;
      import org.jboss.shrinkwrap.impl.base.asset.ByteArrayAsset;
      import org.testng.Assert;
      import org.testng.annotations.Test;

       

      public class SimpleDIExampleTest extends Arquillian {
          @Deployment
          public static JavaArchive createDeployment() {
              return Archives.create("test.jar", JavaArchive.class).addClasses(SimpleDIExample.class).addManifestResource(
                      new ByteArrayAsset("<beans/>".getBytes()), Paths.create("beans.xml"));
          }

       

          @Test(enabled = false)
          public void simpleDependencyInjectionTest() {
              SimpleDIExample constructedFromJava = new SimpleDIExample();
              // child should initialize to null if constructed directly with Java
              // constructor;
              Assert.assertNull(constructedFromJava.getChild());
              // make sure your bean was injected.
              Assert.assertNotNull(injectedFromCDI, "Is your CDI integration configured correctly?");
              // when injected, child should be populated.
              Assert.assertNotNull(injectedFromCDI.getChild(), "Was your bean constructed properly in CDI?");
              // this test is redundant.
              Assert.assertEquals(injectedFromCDI.getChild().getText(), "hello world", "");
          }

       

          @Inject
          private SimpleDIExample injectedFromCDI;
      }

       

       

      Just to confirm that I don't have a CDI error, I used the following page in Glassfish to confirm I had wired things correctly:

       

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
      <html xmlns="http://www.w3.org/1999/xhtml"
         xmlns:f="http://java.sun.com/jsf/core"
         xmlns:h="http://java.sun.com/jsf/html">
         <h:head>
            <title>Java EE 6 Starter Application</title>
         </h:head>
         <h:body>
            <h1>Hello World!</h1>
            <p>My CDI bean says <span style="color: red;">#{simpleDIExample.child.text}</span> using the Unified EL.</p>
         </h:body>
      </html>

        • 1. Re: Error with super simple weld arquillian test
          aslak

          I believe it's the use of @Name that triggers some JSF integration in Weld that is not supported in Weld-SE.

           

          I'll check with some of the Weld guys if this is expected behaviour, or maybe something Weld-SE should handle.

           

          I'll also upgrade to the latest Weld-SE v. just released a couple of days ago.

          • 2. Re: Error with super simple weld arquillian test
            dan.j.allen

            At first a couldn't duplicate the problem. But something about the problem sounded familiar. I recalled having a recent discussion about problems with absent code and dug up the e-mail. You wouldn't happen to be using the following dependency, would you?

             

            <dependency>
               <groupId>javax</groupId>
               <artifactId>javaee-api</artifactId>
               <version>6.0</version>
               <scope>provided</scope>
            </dependency>
            

             

            (Even if you are not using this exact dependency, you are likely using one that has the same problem).

             

            Believe it or not, I found out that when Sun published these APIs to the Maven repository, they stripped out the code from classes that are classified as "implementations". So all the interfaces are code complete, yet any abstract class or implementation class has no code in it. So any attempt to use that class will likely blow up. While Weld doesn't need the JSF class in question, it likely tries to read it to determine what version of JSF is present.

             

            Here is an excerpt from the argument as to why Sun did this:

            When one compiles, they want to run as well. By the way, we have been promoting full set of Java EE APIs which can only be used for compilation - they are stripped off method details. That way, user can't take those artifacts and try to use it in runtime.

             

            As you are discovering, there is gray area about using them at runtime. Technically, you aren't try to use JSF, but Weld's reflection on the JSF APIs has the consequence of using them at runtime. So I should say this is a bug in Weld, but only because Sun is doing a really dangerous thing stripping code from classes which are present.

             

            The workaround is to not use javax.javaee-api but rather use the individual, "real" artifacts that you need. Annoying, I know.

            • 3. Re: Error with super simple weld arquillian test
              dan.j.allen
              The problem is exacerbated by the fact that JSF has virtually no interfaces.
              • 4. Re: Error with super simple weld arquillian test
                dan.j.allen

                I filed the root cause of this problem as an issue: WELD-434 and fixed it. It will be included in the Weld 1.0.1 release next week.

                 

                Basically, Weld was checking for JSF 2.0 by detecting the presence of a method on FacesContext (isPostback). It's safer to stick to class detection. There are plenty of new classes in JSF 2.0. I even went for an interface

                • 5. Re: Error with super simple weld arquillian test
                  aslak

                  Excellent! Thanks Dan

                  • 6. Re: Error with super simple weld arquillian test
                    sboscarine

                    That fixed it.

                     

                    I had a POM generated from the Weld Archetypes and added the javaee-api dependency.  Once I commented out the javaee-api dependency, the test worked.

                     

                    Thank you!

                    • 7. Re: Error with super simple weld arquillian test
                      marcgemis

                      Dan,

                       

                      I'm using Weld 1.0.1-Final and still have the same problem.

                      • 8. Re: Error with super simple weld arquillian test
                        dan.j.allen
                        Can you post the stacktrace up to the arquillian calls (no need for the whole thing). Also, can you print the result of "mvn dependency:tree".(trim the general build output).
                        • 9. Re: Error with super simple weld arquillian test
                          marcgemis

                          Dan,

                           

                          thanks for the fast response. As you can see I have the javaee-api dependency. I got the stacktrace1.txt then.  I adapted the javaee-api a bit and excluded all JSF stuff. (classifier nojsf). As you can see  from the stacktraces I am not using arquillian, but just weld in testng, but the problem occurs in exact the same spot

                           

                          m.

                          • 10. Re: Error with super simple weld arquillian test
                            aslak

                            The fix is to not have the javaee-api from java.net on the runtime classpath at all. It is only meant for compile time and will fail if any classes from it are loaded.

                             

                            If you need runtime libs, depend directly on the apis, ie javax.enterprise:cdi-api:1.0

                             

                            ..and with Maven, it is not possible to have compile time dependencies only, provided scope will still be a part of the test runtime classpath.

                             

                            • 11. Re: Error with super simple weld arquillian test
                              marcgemis
                              ok, thanks, I'll do that