简体   繁体   中英

Unable to inject @Stateless EJB into CDI bean (multi-module) Jakarta EE 8

Migrating a legacy project to Jakarta EE 8 (Maven EAR build on Wildly 26) I am struggling to get the dependancy injection working from my Entities module (EJB packaging) to WAR module, the maven project structure is:

-WebApp.ear
    -WebApp-entities.jar
    -WebApp-ejb.jar
    -WebApp-web.war
    -WebApp-mobile.war
    -WebApp-api.war

The structure was created based on the wildfly-jakartaee8-with-tools archetype

My DAO to be injected is a @Stateless bean that uses @LocalBean no-interface eg.

@Named
@LocalBean
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class UserDAO extends GenericDAOBean<User,Long> {

    @PersistenceContext(unitName="ReadOnlyDatabase")  private EntityManager readOnlyEntityManager;
    
    /**
     * Default constructor
     */
    public UserDAO() {
        //Super call to construct AbstractDAO
        super();
    }
    
    public User findNonDeletedByEmail(String email){
        String s = "from User where email = :email and disabled = false";
        Query query = this.getEntityManager().createQuery(s);
        query.setParameter("email", email);
        try{
            return (User)query.getSingleResult();
        }catch(NoResultException nre){
            return null;
        }catch(Exception e){
            return null;
        }
    }
    
}

My CDI bean is a standard @RequestScoped bean in the WAR module that is attempting to inject the DAO to perform login

@Named
@RequestScoped
public class LoginBean implements Serializable {


private static final long serialVersionUID = 1504441323094295359L;

@Inject private SecurityContext securityContext;
@Inject private UserDAO userDAO;
@Inject private FacesContext facesContext;
@Inject private ExternalContext externalContext;

private String username, password;

public void login() throws IOException {
  
    Credential credential = new UsernamePasswordCredential(username, new Password(password));
  
    User user = userDAO.findByEmailForUserLogin(username);
   AuthenticationStatus status = securityContext.authenticate(
           getRequest(facesContext),
           getResponse(facesContext),
           AuthenticationParameters.withParams()
                   .credential(credential));
  
   switch (status) {
       case SEND_CONTINUE:
           facesContext.responseComplete();
           break;
       case SEND_FAILURE:
           facesContext.addMessage(null,
                   new FacesMessage(FacesMessage.SEVERITY_ERROR, "Login failed", null));
           break;
       case SUCCESS:
           facesContext.addMessage(null,
                   new FacesMessage(FacesMessage.SEVERITY_INFO, "Login succeed", null));
           externalContext.redirect(externalContext.getRequestContextPath() + "/user/home.xhtml");
           break;
       case NOT_DONE:
   }
  
}

private static HttpServletResponse getResponse(FacesContext context) {
   return (HttpServletResponse) context
       .getExternalContext()
       .getResponse();
}

private static HttpServletRequest getRequest(FacesContext context) {
   return (HttpServletRequest) context
       .getExternalContext()
       .getRequest();
}

public String getUsername() {
    return username;
}

public void setUsername(String username) {
    this.username = username;
}

public String getPassword() {
    return password;
}

public void setPassword(String password) {
    this.password = password;
}

}

When I call the login() method from JSF page I get the following error:

Target Unreachable, identifier 'loginBean' resolved to null: javax.el.PropertyNotFoundException

If I comment out the userDAO injection the method calls ok so I know its the UserDAO causing the problem, there are no other errors

In the server startup logs I can see that UserDAO is registered ok eg:

    java:global/WebApp/Web-entities/UserDAO!com.webapp.dao.beans.UserDAO
java:app/Web-entities/UserDAO!com.webapp.dao.beans.UserDAO
java:module/UserDAO!com.webapp.dao.beans.UserDAO
java:global/WebApp/Web-entities/UserDAO
java:app/Web-entities/UserDAO
java:module/UserDAO

I have beans.xml defined in /web-inf/beans.xml (war) and /meta-inf/beans.xml (jar) both with bean-discovery-mode="annotated"

My EJB module is included as a maven dependancy in the WAR.pom with <scope>provided</scope>

I have also tried injecting using @EJB have the same error

UPDATE:

I found that by setting <ear-subdeployments-isolated>false</ear-subdeployments-isolated> in boss-deployment-structure.xml allows injection to work however this then creates issues with dependancies being duplicated across modules and class-path errors so I don't think its the right solution (our legacy EE 6 project had EAR deployments isolated and the DI worked ok)

Eventually got this working by adding module dependancies to the EJB and Entity modules in jboss-deployment-structure.xml as below...

<sub-deployment name="WebApp-web.war">
    <dependencies>
        <module name="deployment.WebApp.ear.WebApp-entities.jar" />
        <module name="deployment.WebApp.ear.WebApp-ejb.jar" />
    </dependencies>
  </sub-deployment>

Injection into the WAR now works ok, this was not required in the legacy EE 6 / JBoss 7 app so the class loading behaviour must have changed

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM