Maven + JUnit + ClassFormatError: Absent Code attribute in method that is not native or abstract in class file

Once in a while one stumbles upon an error message like this

java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/mail/Session

This happens if your code compiles against incomplete classes, like the JavaEE6 Api and your Unit tests try to access code thats not there. JUnit will simply fail and mark the test as error, printing something like this

Tests in error: 
  initializationError(com.dominikdorn.dc.passwordReset.SimplePasswordResetServiceTest)

and the corresponding surefire text file starts like this:

-------------------------------------------------------------------------------
Test set: com.dominikdorn.dc.passwordReset.SimplePasswordResetServiceTest
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.022 sec <<< FAILURE!
initializationError(com.dominikdorn.dc.passwordReset.SimplePasswordResetServiceTest)  Time elapsed: 0.005 sec  <<< ERROR!
java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/mail/Session
        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)
....

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<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>

If you are deploying your App on an Appserver like Glassfish or JBoss AS, leave the scope of javax.mail:mail as provided to prevent the inclusion of the jar in the final webapp.

I now list required dependencies for various Absent Code Errors I've encountered and still encountering. This post will be updated every time I solve another of these problems.

JavaMail: javax/mail/Session

1
2
3
4
5
6
7
8
9
10
11
<project ...>
...
    <dependencies>
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

Servlet 3.0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<project ...>
...
    <dependencies>
               <dependency>
                       <groupId>org.glassfish</groupId>
                       <artifactId>javax.servlet</artifactId>
                       <version>3.0</version>
                       <scope>provided</scope>
               </dependency>
...
    </dependencies>
....   
    <repositories>
               <!-- Required until the Servlet 3.0 API can be resolved in Central -->     
               <repository>
                       <id>Glassfish</id>
                       <name>Glassfish Maven2 Repository</name>
                       <url>http://download.java.net/maven/glassfish/</url>
               </repository>
    </repositories>
 </project>

JPA2: javax/persistence/PersistenceException

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<dependencies>...
        <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>javax.persistence</artifactId>
            <version>2.0.0</version>
            <scope>provided</scope>
        </dependency>
...</dependencies>
..
<repositories>
...
    <repositories>
...
        <repository>
            <id>eclipse</id>
            <name>Eclipse Maven Repository</name>
            <url>http://www.eclipse.org/downloads/download.php?r=1&amp;nf=1&amp;file=/rt/eclipselink/maven.repo</url>
        </repository>
    </repositories>

JAX-RS: javax/ws/rs/core/UriBuilder

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-core</artifactId>
            <version>1.1.5</version>
            <scope>provided</scope>
        </dependency>
<!-- for json support -->
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-json</artifactId>
            <version>1.1.5</version>
            <scope>provided</scope>
        </dependency>
<!-- for testing --> 
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-test-framework</artifactId>
            <version>1.1.5.1</version>
            <scope>test</scope>
        </dependency>

more to come soon!

Join the Conversation

4 Comments

  1. Maven is so intuitive. Anyone could have figured out the solution to this problem. Everything just works with Maven. Great!

  2. Did you encounter this one ?

    java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/ejb/RemoveException

    my dependencies are :

    javax
    javaee-api
    jar
    compile
    6.0

    org.glassfish.appclient
    gf-client
    3.0
    runtime

    com.sun.corba
    glassfish-corba-orb
    3.0.1-b002
    runtime

    I “need to” reference GF Client, because I’m writing a java.main() that reach glasshfish and query an EJB.
    InitialContext jndiContext = new InitialContext(getJndiConfig());

    JNDI config being :
    env.put(Context.INITIAL_CONTEXT_FACTORY, “com.sun.enterprise.naming.impl.SerialInitContextFactory”);
    env.put(“org.omg.CORBA.ORBInitialHost”, “localhost”);
    env.put(“org.omg.CORBA.ORBInitialPort”, “3700”);

    I “need” gf client at runtime so that SerialInitContextFactory (and callees) is found.

    I tried to find a javax.ejb to place first, but haven’t.
    If you have any idea, I take gladly 🙂

    Thanks in advance.

  3. If you cope this problem with JUnit + Eclispe, just simple re-order the library “javaee-api” to make sure that it is the last library in the classpath. The reason of this is that this library contains some interfaces that need to be implemented by some other library like Glassfish App Server, or Java Persistent API, … More details could be found here: http://forum.springsource.org/showthread.php?t=57108

Leave a comment

Your email address will not be published. Required fields are marked *