【问题标题】:Unable to inject @Stateless EJB into CDI bean (multi-module) Jakarta EE 8无法将 @Stateless EJB 注入 CDI bean(多模块)Jakarta EE 8
【发布时间】:2023-01-26 23:44:51
【问题描述】:

将遗留项目迁移到 Jakarta EE 8(Maven EAR 在 Wildly 26 上构建)

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

该结构是基于 wildfly-jakartaee8-with-tools 原型创建的

我要注入的 DAO 是一个 @Stateless bean,它使用 @LocalBean 无接口,例如。

@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;
        }
    }
    
}

我的 CDI bean 是 WAR 模块中的标准 @RequestScoped bean,它试图注入 DAO 以执行登录

@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;
}

}

当我从 JSF 页面调用 login() 方法时,出现以下错误:

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

如果我注释掉 userDAO 注入,方法调用正常,所以我知道是 UserDAO 导致了问题,没有其他错误

在服务器启动日志中,我可以看到 UserDAO 已正确注册,例如:

    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

我在 /web-inf/beans.xml (war) 和 /meta-inf/beans.xml (jar) 中定义了 beans.xml,它们都带有 bean-discovery-mode="annotated"

我的 EJB 模块作为 Maven 依赖包含在 WAR .pom 中,&lt;scope&gt;provided&lt;/scope&gt;

我也试过使用@EJB注入有同样的错误

更新:

我发现通过在 boss-deployment-structure.xml 中设置 &lt;ear-subdeployments-isolated&gt;false&lt;/ear-subdeployments-isolated&gt; 允许注入工作但是这会产生跨模块重复依赖和类路径错误的问题所以我认为它不是正确的解决方案(我们的遗留 EE 6 个项目已隔离 EAR 部署并且 DI 工作正常)

【问题讨论】:

  • 这里的问题是 JSF 和 EL 找不到 loginBean - 而不是 LoginBean 找不到 UserDao,对吧?
  • 而且,如果是这样,您是否尝试过this 的方法?
  • 您也可以提供进口产品吗?很多时候错误的@RequestScoped-annotation 被用于@Named
  • 嗨@NikosParaskevopoulos 当我删除 Inject UserDAO 时,没有 loginBean 工作正常所以它不是 LoginBean 的问题,我现在已经设法让它工作,请参阅下面的答案......

标签: java jakarta-ee wildfly cdi java-ee-8


【解决方案1】:

最终通过将模块依赖项添加到 jboss-deployment-structure.xml 中的 EJB 和实体模块来实现这一点,如下所示......

<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>

注入 WAR 现在可以正常工作,这在旧版 EE 6 / JBoss 7 应用程序中不是必需的,因此类加载行为必须已更改

【讨论】:

  • 嗨@DaveB,好人。我建议您将自己的答案标记为已接受,以便人们很容易知道这实际上已得到回答。
猜你喜欢
  • 2013-06-30
  • 1970-01-01
  • 2011-03-31
  • 2015-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-13
  • 1970-01-01
相关资源
最近更新 更多