49

I write an addition to JAX-RS and included the Java EE 6 API as a Maven dependency.

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

Then I have a little test case:

  @Test
  public void testIsWriteable() {
    class SpecialViewable extends Viewable {
      public SpecialViewable() {
        super("test");
      }
    }
    FreeMarkerViewProcessor processor = new FreeMarkerViewProcessor(null);
    assertTrue(processor.isWriteable(SpecialViewable.class, null, null,
            MediaType.WILDCARD_TYPE));
  }

But I get an error:

java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/ws/rs/core/MediaType
    ...

If I include Jersey as a JAX-RS implementation instead of the Java EE API everything is fine.

Thanks to BalusC's hint I know what I had guessed: Java EE 6 is only an API without method bodies: From the java.net blog

You can compile you code with this jar, but of course you cannnot run your application with it since it contains only the Java EE 5 APIs and does not contain any method bodies. If you try to run, you would get this exception:

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

In order to execute a Java EE 5 application, you'll still need a Java EE 5 container, like for example the GlassFish application server.

I've tried to add Jersy with test scope but it didn't work.

<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>6.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-server</artifactId>
    <version>${jersey-version}</version>
    <scope>test</scope>
</dependency>

How can I test software that depends only on the official Java EE API?

Solution

The provider (Jersey) needs to be placed before the API (javeee-api) in the pom.xml.

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-server</artifactId>
    <version>${jersey-version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>6.0</version>
    <scope>provided</scope>
</dependency>
deamon
  • 89,107
  • 111
  • 320
  • 448
  • 5
    Here are some related problems with insightful answers: http://www.google.com/search?q=%22java.lang.ClassFormatError%3A+Absent+Code+attribute+in+method+that+is+not+native+or+abstract+in+class+file%22 – BalusC Aug 06 '10 at 13:34
  • I was really gnawing my nails with this problem before I ran into this question. Thanks! – Denys Kniazhev-Support Ukraine Mar 29 '11 at 14:03

3 Answers3

30

Not sure this will solve your problem but GlassFish Embedded provides a Java EE 6 implementation. Add this to your pom.xml:

<project>
  ...
  <repositories>
    <repository>
      <id>glassfish-extras-repository</id>
      <url>http://download.java.net/maven/glassfish/org/glassfish/extras</url>
    </repository>
  </repositories>
  ...
  <dependencies>
    <dependency>
      <groupId>org.glassfish.extras</groupId>
      <artifactId>glassfish-embedded-all</artifactId>
      <version>3.0.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>6.0</version>
      <scope>provided</scope>
    </dependency>
    ...
  </dependencies>
  ...
</project>

It's important to declare the glassfish-embedded-all artifact before the javaee-api.

Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
  • 1
    Maybe also try with the `jersey-server` artifact (but declare it **before** the `javaee-api`). – Pascal Thivent Aug 06 '10 at 15:06
  • I don't need a full application server like GlassFish, but your hint to place the provider (GlassFish or, in my case, Jersy) before the API was the solution! – deamon Aug 06 '10 at 16:32
  • Just a note that the repository URL should actually be http://download.java.net/maven/glassfish/ – hohonuuli May 22 '11 at 23:24
  • Is there an embedded glassfish for Java EE 5? – Sebi Jul 27 '12 at 15:49
  • See http://mvnrepository.com/artifact/org.glassfish.main.extras/glassfish-embedded-all/3.1.2.2 – demaniak Dec 20 '13 at 06:45
  • 1
    The problem with this is that they seem to have exploded a bunch of jars and packaged them back together inside `glassfish-embedded-all`. You better hope you're using the same slf4j version they packaged in there, because they didn't give a way to exclude what they give you. There has got to be a better way. – Daniel Kaplan May 01 '14 at 23:26
8

As for me, JBoss' implementation is smaller than the whole Glassfish, so I'm using:

    <dependency>
        <groupId>org.jboss.spec</groupId>
        <artifactId>jboss-javaee-6.0</artifactId>
        <version>${version.jboss-javaee-6.0}</version>
        <type>pom</type>
    </dependency>

<scope>test</scope> should also do no harm.

Victor Sergienko
  • 13,115
  • 3
  • 57
  • 91
1

An alternative that is JSR provider agnostic is

<dependency>
  <groupId>javax.ws.rs</groupId>
  <artifactId>jsr311-api</artifactId>
  <scope>provided</scope>
</dependency>
<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>6.0</version>
    <scope>provided</scope>
</dependency>

This allows you to swap Jersey with a different provider. For Glassfish 3.1.2, it uses jersey-server 1.11, which uses jsr311 version 1.1 according to the jersey pom.

Snekse
  • 15,474
  • 10
  • 62
  • 77