4
votes

I have an EJB with some JPA logic that I use in my java EE projects. Instead of copying the class in every project I'm trying to put it in a separate jar, so I have this structure:

  • Java EE project with EJB and WAR projects in it
  • JPALogic: JAR project with JPALogic class in it
  • RemoteServices: JAR project with beans interfaces
  • Services: EJB project with beans, including JPALogic and RemoteServices as libraries
  • Frontend: WAR project with frontend, including RemoteServices as library.

JPALogic is used only in the EJB project and there's no reference to it in other parts of the Java EE app. In JPALogic library I've my JPALogic bean:

@Stateless
@LocalBean
public class JPALogic {
  @Resource
  private EJBContext ejbContext;
  @Inject @ShardedPersistenceContext
  private EntityManager em;
  public JPALogic() {
  }
  [...lots of methods...]
}

It works perfect if JPALogic code is directly in the EJB project, but when I put it in the external library deployment become very unstable (netbeans 8 + glassfish 4) and almost every deploy fail with this error:

Exception while deploying the app [app] : Cannot resolve reference [Remote ejb-ref name=com.my.autenticacion.services.AutRolBackendServices/jpa,Remote 3.x interface =com.my.infraestructura.jpa.JPALogic,ejb-link=null,lookup=,mappedName=,jndi-name=,refType=Session] because there are [2] ejbs in the application with interface com.my.infraestructura.jpa.JPALogic. 

I've search but it seems this kind of error appear when an interface have more than one implementation, and this is not the case: there's only one bean named "JPALogic" and, inspecting the ear, JPALogic.jar appear one time only.

I'm doing something wrong?

1
Similar deployment time errors could be caused by misconfiguration in your web.xml descriptor. You might want to check your EJB project's web.xml for an optional ejb-ref tag (docs.oracle.com/cd/E14571_01/web.1111/e13712/…), which could have been added by your IDE during a creation of EJB. - Aleksandr Erokhin

1 Answers

1
votes

If you jar contains EJB annotations (@Singleton, @Stateless, @Stateful component-defining annotations), its not a simple jar, but an ejb-jar, and should be packaged as a module.

Solution:

  1. You should reference the JPALogic.jar in application.xml as an EJB module.
  2. You can also add a "Class-Path: JPALogic.jar" in the META-INF/MANIFEST.MF of the referencing modules to garantee visibility. It could be visibile, depending on the container.

Like this:

application.EAR
    META-INF/application.xml
        (must have a reference to the JPALogic.jar EJB module)
    JPALogic.jar (EJB-JAR)
    remoteservices.jar
    services.jar
        META-INF/MANITESF.MF Class-Path: JPALogic.jar
    remoteservices.jar
    frontend.war

For a more details, refer to the JAVA EE 6 specification, chapter EE.8:

  • EE.8.3.2 EJB Container Class Loading Requirements
  • EE.8.5.2 Deploying a Java EE Application