Using Maven, how to properly deploy WAR depending

2019-01-26 00:59发布

问题:

I'm creating a modular Maven project. Project is deployed on Glassfish 3.1. Project (webapp) consists of three modules:

  • "Common", consisting of core functionality (persistence, authentication logic, etc.), built into a JAR
  • "User", depending on Common, built into a WAR
  • "Admin", also depending on Common and WARred

Both WAR use heavy annotated (@Entity, @Inject, @EJB, ...) classes from Common. Currently Common is a JAR, but it's not a requirement. The question is: How to properly deploy such project?

By my current (google and stackoverflow influenced) knowledge:

  • Common cannot be a JAR, because .jar file is put into WEB-INF\lib directory inside JAR. This makes deploy-time initialization, because Glassfish expects .classes and produces an "Unsatisfied dependencies" error, resulting in failed deployment.

  • Common cannot be a WAR, because with WAR overlay copying ocurrs after build -- resulting in build depending on itself...

EDIT

As Mike Decks comment suggests setup is ok, I assume supplying a full error message would be useful:

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

What would that mean? What could be the cause?

EDIT2

I'm enclosing relevant classes (trimmed a bit, i.e. not get/set methods, imports, etc.)

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() {}
}

and:

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

回答1:

Problem was solved by adding empty META-INF/beans.xml and META-INF/faces-config.xml. Empty files imply default configuration, among other things letting Glassfish know that it should look for classes needed for @Inject, while lack of them does not.



回答2:

From the error message it seems that this is a problem with CDI. It is unable to find a proper implementation for type 'Authentication' when it attempts to initialize your LoginFilter. Check whether the implementation class of type 'Authentication' is available in your JAR file.

Like @Mike has mentioned, you are supposed to put your dependencies into your lib folder as JAR files, so that should not be a issue. I guess this is not a problem with Maven.



回答3:

Use an EAR to package EJB-jars and WARs.