【问题标题】:Using Maven, how to properly deploy WAR depending on J2EE/JPA JAR?使用 Maven,如何根据 J2EE/JPA JAR 正确部署 WAR?
【发布时间】:2011-05-27 22:05:44
【问题描述】:

我正在创建一个模块化的 Maven 项目。项目部署在 Glassfish 3.1 上。项目(webapp)由三个模块组成:

  • “通用”,由核心功能(持久性、身份验证逻辑等)组成,内置在 JAR 中
  • “用户”,取决于 Common,内置在 WAR 中
  • “Admin”,也取决于 Common 和 WARred

两个 WAR 都使用来自 Common 的重注释(@Entity、@Inject、@EJB、...)类。目前 Common 是一个 JAR,但这不是必需的。问题是:如何正确部署这样的项目?

根据我目前(受谷歌和 stackoverflow 影响)的知识:

  • Common 不能是 JAR,因为 .jar 文件放在 JAR 内的 WEB-INF\lib 目录下。这会在部署时进行初始化,因为 Glassfish 需要 .classes 并产生“不满足的依赖项”错误,从而导致部署失败。

  • Common 不能是 WAR,因为在构建之后会发生 WAR 覆盖复制——导致构建依赖于自身...

编辑

正如 Mike Decks 的评论所暗示的,设置是好的,我认为提供完整的错误消息会很有用:

Deployment Error for module: User: Error occurred during deployment: 
Exception while loading the app : WELD-001408 Unsatisfied dependencies 
for type [Authentication] with qualifiers [@Default] at injection point
[[field] @Inject xxx.xxx.servlets.LoginFilter.authentication].

这意味着什么? 可能是什么原因?

EDIT2

我附上了相关的类(修剪了一下,即不是获取/设置方法、导入等)

public class LoginFilter implements Filter {

    @Inject
    Authentication authentication;

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        LoginBean login = (LoginBean) httpRequest.getSession().getAttribute("loginBean");
        if((login == null || !login.isAuthenticated())) {
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            String requestUrl = httpRequest.getRequestURI().toString();
            authentication.setNavigateAfterLogin(requestUrl);
            httpResponse.sendRedirect("./../login.html");
        }       
        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig fConfig) throws ServletException {}

    @Override
    public void destroy() {}
}

和:

@SessionScoped  
public class Authentication implements Serializable {   
    @Inject
    private UserDatabaseController userDb;
    private ShopUser user;
    private String navigateAfterLogin;
    private String login;
    private String password;

    public boolean doLogin(String username, String password) {
        List<ShopUser> users = userDb.getUsers();
        for(ShopUser shopUser : users) {
            if(shopUser.getLogin().equals(username) && shopUser.getPassword().equals(password)) {
                setUser(shopUser);
                return true;
            }
        }
        return false;
    }

    public void doLogout() {
        setUser(null);
    }   

    public boolean isAuthenticated() {
        return getUser() != null;
    }
}

【问题讨论】:

  • Common 可以而且应该是一个 JAR。我不确定为什么您的部署失败,但 WEB-INF/lib 绝对是为了容纳 WAR 的 JAR 文件依赖项。听起来您已经进行了正确的基本设置,您真正需要做的是解决部署错误。

标签: java maven glassfish war


【解决方案1】:

通过添加 empty META-INF/beans.xmlMETA-INF/faces-config.xml 解决了问题。空文件意味着默认配置,其中包括让 Glassfish 知道它应该寻找 @Inject 所需的类,而缺少它们则不会。

【讨论】:

    【解决方案2】:

    从错误消息看来,这是 CDI 的问题。当它尝试初始化您的 LoginFilter 时,它无法找到类型“身份验证”的正确实现。检查您的 JAR 文件中是否存在“Authentication”类型的实现类。

    就像@Mike 提到的那样,您应该将依赖项作为 JAR 文件放入您的 lib 文件夹中,因此这应该不是问题。我想这不是 Maven 的问题。

    【讨论】:

    • 类型“身份验证”存在于 JAR 中。也许它是@Injected 的事实与错误有关?可能是什么原因和/或如何解决这个问题?
    • 什么是“身份验证”(例如 EJB)?是容器可以注入的东西吗?
    • 身份验证是注入到 LoginFilter 类 (@Inject) 中的 @SessionScoped (javax.enterprise.context.SessionScoped) 托管 bean。
    • 那么肯定是有资格被容器注入的。你能把你的 Authentication 类和 LoginFilter 类的来源放上来让我们看看吗?
    • 添加了类的相关部分。
    【解决方案3】:

    使用 EAR 打包 EJB-jar 和 WAR。

    【讨论】:

    • Java EE 6 的一项进步是“简化打包”,它允许开发人员将 EJB 作为类 (WEB-INF/classes) 或库 (WEB-INF/lib) 直接集成到 WAR 文件中。创建一个耳朵来解决这个问题可能是一种解决方法,但它应该是最后一件事......因为它可能无论如何都无法解决这种情况。
    猜你喜欢
    • 2013-03-27
    • 1970-01-01
    • 1970-01-01
    • 2014-05-22
    • 2017-01-27
    • 1970-01-01
    • 2018-06-28
    • 1970-01-01
    • 2014-05-30
    相关资源
    最近更新 更多