When InfoQ first broke news of Restfuse, I was very excited to try it out seeing as how I'd begun experimenting with the likes of Jersey and CXF at work. Given the 1.0.0 release status, it was my hope that plugging this thing into an existing project via Maven would take the whole of 5 minutes, but things just never work like that in the real world. Running a basic test similar to the snippet provided on the framework homepage produced the following result:
java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/mail/MessagingException
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
at java.lang.Class.getDeclaredMethods(Class.java:1791)
at com.sun.jersey.core.reflection.MethodList.getAllDeclaredMethods(MethodList.java:70)
at com.sun.jersey.core.reflection.MethodList.(MethodList.java:64)
at com.sun.jersey.core.spi.component.ComponentConstructor.getPostConstructMethod(ComponentConstructor.java:126)
at com.sun.jersey.core.spi.component.ComponentConstructor.(ComponentConstructor.java:120)
at com.sun.jersey.core.spi.component.ProviderFactory.__getComponentProvider(ProviderFactory.java:165)
at com.sun.jersey.core.spi.component.ProviderFactory.getComponentProvider(ProviderFactory.java:137)
at com.sun.jersey.core.spi.component.ProviderServices.getComponent(ProviderServices.java:256)
at com.sun.jersey.core.spi.component.ProviderServices.getServices(ProviderServices.java:160)
at com.sun.jersey.core.spi.factory.MessageBodyFactory.initReaders(MessageBodyFactory.java:176)
at com.sun.jersey.core.spi.factory.MessageBodyFactory.init(MessageBodyFactory.java:162)
at com.sun.jersey.api.client.Client.init(Client.java:342)
at com.sun.jersey.api.client.Client.access$000(Client.java:118)
at com.sun.jersey.api.client.Client$1.f(Client.java:191)
at com.sun.jersey.api.client.Client$1.f(Client.java:187)
at com.sun.jersey.spi.inject.Errors.processWithErrors(Errors.java:193)
at com.sun.jersey.api.client.Client.(Client.java:187)
at com.sun.jersey.api.client.Client.(Client.java:159)
at com.sun.jersey.api.client.Client.create(Client.java:669)
at com.eclipsesource.restfuse.internal.InternalRequest.createRequest(InternalRequest.java:130)
at com.eclipsesource.restfuse.internal.InternalRequest.get(InternalRequest.java:72)
at com.eclipsesource.restfuse.internal.HttpTestStatement.callService(HttpTestStatement.java:83)
at com.eclipsesource.restfuse.internal.HttpTestStatement.sendRequest(HttpTestStatement.java:70)
at com.eclipsesource.restfuse.internal.BasicStatement.evaluate(BasicStatement.java:30)
at com.eclipsesource.restfuse.internal.HttpTestStatement.evaluate(HttpTestStatement.java:55)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
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)
Not very encouraging. Attempts to rectify the problem by adding javax.mail.mail to the list of dependencies were proving futile until I found this little gem (corollary to Wisdom of the Ancients?):
This happens if your code compiles against incomplete classes, like the JavaEE6 Api and your Unit tests try to access code thats not there.
....
The Solution
You have to compile against real-implementations of the classes. You do that by adding those dependencies before the most generic dependency in your pom.xml
As example, we add javax.mail BEFORE javaee6-api like this
<project ...>
...
<dependencies>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
</project>
Lowe and behold: green bar.