Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Trouble With Crippled Java EE 6 APIs in Maven Repository And The Solution

DZone's Guide to

Trouble With Crippled Java EE 6 APIs in Maven Repository And The Solution

· Java Zone
Free Resource

Just released, a free O’Reilly book on Reactive Microsystems: The Evolution of Microservices at Scale. Brought to you in partnership with Lightbend.

If you try to load the javax.persistence.EntityManager class coming from standard java.net Repository you will get the following Exception:

java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/persistence/LockModeType
        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)

Loading a class is needed for mocking, so the following code will not run:

@Stateless
public class EJB3WithEntityManager {
    @PersistenceContext
    EntityManager em;
    
    public void save(AnEntity ae){
        em.persist(ae);
    }
}

public class EJB3WithEntityManagerTest {
    private EJB3WithEntityManager cut;
    @Before
    public void injectEntityManager(){
        this.cut = new EJB3WithEntityManager();
        this.cut.em = mock(EntityManager.class);
    }
    @Test
    public void testSomeMethod() {
        AnEntity ae = new AnEntity();
        this.cut.save(ae);
        verify(this.cut.em,times(1)).persist(ae);
    }
}

Instead of using

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

You should use alternative (geronimo, jboss etc.) dependencies:

<dependency>
       <groupId>org.apache.geronimo.specs</groupId>
       <artifactId>geronimo-ejb_3.1_spec</artifactId>
       <version>1.0</version>
       <scope>provided</scope>
   </dependency>
   <dependency>
       <groupId>org.apache.geronimo.specs</groupId>
       <artifactId>geronimo-jpa_2.0_spec</artifactId>
       <version>1.0</version>
       <scope>provided</scope>
   </dependency>

I cannot imagine any reasonable motivation behind removing the implementation of API-classes before uploading them into central maven repository, except political or licensing issues. This approach, however, has one advantage. You can tell whether a project is actually unit tested, or not, just by looking at the POM :-).

The whole example with workaround was checked into http://kenai.com/projects/javaee-patterns The name of the project is: MavenUnitTestWithCrippledAPI.

From http://www.adam-bien.com/roller/abien/entry/trouble_with_crippled_java_ee

Strategies and techniques for building scalable and resilient microservices to refactor a monolithic application step-by-step, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}