Problem z DI EJB 3.0, JSF 1.2

0

Witam,
Aplikacje uruchamiam na serwerze Glassfish 2.1.1. Deployuje się dobrze z poziomu NetBeans 7.4. Projekt został utworzony jako Enterprise Application (EJB + web application), domyślnie użyta wesja JSF 1.2 z serwera.

Stack trace:

exception

javax.servlet.ServletException: com.sun.enterprise.InjectionException: Exception attempting to inject Unresolved Ejb-Ref lux.controllers.UserController/userDao@jndi: lux.facade.UserDAO@[email protected]@Session@null into class lux.controllers.UserController

root cause

com.sun.faces.spi.InjectionProviderException: com.sun.enterprise.InjectionException: Exception attempting to inject Unresolved Ejb-Ref lux.controllers.UserController/userDao@jndi: lux.facade.UserDAO@[email protected]@Session@null into class lux.controllers.UserController

root cause

com.sun.enterprise.InjectionException: Exception attempting to inject Unresolved Ejb-Ref lux.controllers.UserController/userDao@jndi: lux.facade.UserDAO@[email protected]@Session@null into class lux.controllers.UserController

root cause

javax.naming.NameNotFoundException: lux.facade.UserDAO#lux.facade.UserDAO not found

Wniosek: nie wstrzykuje prawidłowo zależności do EJB (nie znajduje klasy?). Będę wdzięczny za pomoc w znalezieniu bebecha.

Projekt EJB (klasa autowygenerowana):

Pakiet lux domain

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package lux.domain;

import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;

@Entity
@Table(name = "users")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Users.findAll", query = "SELECT u FROM Users u"),
    @NamedQuery(name = "Users.findByUserId", query = "SELECT u FROM Users u WHERE u.userId = :userId"),
    @NamedQuery(name = "Users.findByUsername", query = "SELECT u FROM Users u WHERE u.username = :username"),
    @NamedQuery(name = "Users.findByFistName", query = "SELECT u FROM Users u WHERE u.fistName = :fistName"),
    @NamedQuery(name = "Users.findByLastName", query = "SELECT u FROM Users u WHERE u.lastName = :lastName"),
    @NamedQuery(name = "Users.findByPassword", query = "SELECT u FROM Users u WHERE u.password = :password")})

public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="users_seq_generator")
    @SequenceGenerator(name="users_seq_generator", sequenceName="users_user_id_seq", allocationSize=1)
    @Basic(optional = false)
    @Column(name = "user_id")
    private Integer userId;
    @Basic(optional = false)
    @Column(name = "username")
    private String username;
    @Column(name = "fist_name")
    private String fistName;
    @Column(name = "last_name")
    private String lastName;
    @Basic(optional = false)
    @Column(name = "password")
    private String password;

    public User() {
    }

    public User(Integer userId) {
        this.userId = userId;
    }

    public User(Integer userId, String username, String password) {
        this.userId = userId;
        this.username = username;
        this.password = password;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

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

    public String getFistName() {
        return fistName;
    }

    public void setFistName(String fistName) {
        this.fistName = fistName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getPassword() {
        return password;
    }

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

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (userId != null ? userId.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof User)) {
            return false;
        }
        User other = (User) object;
        if ((this.userId == null && other.userId != null) || (this.userId != null && !this.userId.equals(other.userId))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "lux.domain.Users[ userId=" + userId + " ]";
    }
    
}

Pakiet lux.facade:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package lux.facade;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import lux.domain.User;

@Stateless
public class UserDAO implements UserDAOLocal, UserDAORemote {
   
   @PersistenceContext
   private EntityManager em;
   
   public User getUser(int UserId) {
    User u;
    u = em.find(User.class, UserId);
    return u;
  }
 
  public List<User> getAllUsers() {
    Query q = em.createQuery("SELECT u FROM User u");
    List<User> users = q.getResultList();
    return users;
  }
 
  public void createUser(User u) {
    String hashedPw = hashPassword(u.getPassword());
    u.setPassword(hashedPw);
    em.persist(u);
  }
 
  public void updateUser(User u) {
    String hashedPw = hashPassword(u.getPassword());
    u.setPassword(hashedPw);
    em.merge(u);
  }
 
  public void deleteUser(User u) {
    em.remove(u);
  }
 
  private String hashPassword(String password) {
    StringBuilder sb = new StringBuilder();
    try {
      MessageDigest messageDigest = MessageDigest.getInstance("SHA");
      byte[] bs;
      bs = messageDigest.digest(password.getBytes());
      for (int i = 0; i < bs.length; i++) {
        String hexVal = Integer.toHexString(0xFF & bs[i]);
        if (hexVal.length() == 1) {
          sb.append("0");
        }
        sb.append(hexVal);
      }
    } catch (NoSuchAlgorithmException ex) {
      Logger.getLogger(UserDAO.class.getName()).log(Level.SEVERE, null, ex);
    }
    return sb.toString();
  }
}

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package lux.facade;

import javax.ejb.Local;
import lux.domain.User;
import java.util.List;

@Local
public interface UserDAOLocal {
    public User getUser(int UserId);
    public void createUser(User u);
    public void updateUser(User u);
    public void deleteUser(User u);
    public List<User> getAllUsers();
}

package lux.facade;

import javax.ejb.Remote;

@Remote
public interface UserDAORemote {
    
}

Aplikacja internetowa, pakiet lux.controllers:

import javax.ejb.EJB;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import lux.domain.User;
import lux.facade.UserDAO;

public class UserController {
    @EJB
    UserDAO userDao;
    
    private User user;
    private DataModel model;
    
    public String createUser() {
     user = new User();
     return "create_new_user";
   }
   public String saveUser() {
     String r = "success";
     try {
       userDao.createUser(user);
     } catch (Exception e) {
       e.printStackTrace();
       r = "failed";
     }
     return r;
   }

   public DataModel getUsers() {
     model = new ListDataModel(userDao.getAllUsers());
     return model;
   }

   public User getUser() {
     return user;
   }

   public void setUser(User user) {
     this.user = user;
   }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>faces/index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

faces-config.xml

<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="1.2" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
    
    <managed-bean>
        <managed-bean-name>user</managed-bean-name>
        <managed-bean-class>lux.controllers.UserController</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
    </managed-bean>
    
    <navigation-rule>
        <from-view-id>/faces/index.jsp</from-view-id>
        <navigation-case>
            <from-outcome>create_new_user</from-outcome>
            <to-view-id>/faces/adduser.jsp</to-view-id>
        </navigation-case>
    </navigation-rule>
    <navigation-rule>
        <from-view-id>/faces/adduser.jsp</from-view-id>
        <navigation-case>
            <from-outcome>failed</from-outcome>
            <to-view-id>/faces/failed.jsp</to-view-id>
        </navigation-case>
        <navigation-case>
            <from-outcome>success</from-outcome>
            <to-view-id>/faces/index.jsp</to-view-id>
        </navigation-case>
    </navigation-rule>
</faces-config>

index.jsp

<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
 
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
 
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>User Listing</title>
    </head>
    <body>
        <f:view>
            <h:form>
                <h1><h:outputText value="User Listing"/></h1>
                <p><h:commandLink action="#{user.createUser}" value="Create a user"/></p>
                <h:dataTable value="#{user.users}"
                             var="dataTableItem" border="1" cellpadding="2" cellspacing="2">
                    <h:column>
                        <f:facet name="header">
                            <h:outputText  value="Username"/>
                        </f:facet>
                        <h:outputText value="#{dataTableItem.username}" />
                    </h:column>
                    <h:column>
                        <f:facet name="header">
                            <h:outputText  value="First name"/>
                        </f:facet>
                        <h:outputText value="#{dataTableItem.firstName}" />
                    </h:column>
                    <h:column>
                        <f:facet name="header">
                            <h:outputText  value="Last name"/>
                        </f:facet>
                        <h:outputText value="#{dataTableItem.lastName}" />
                    </h:column>
                </h:dataTable>
            </h:form>
        </f:view>
    </body>
</html>

widok failed.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <h1>Save failed!</h1>
    </body>
</html>

adduser.jsp

<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
 
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
 
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>New user</title>
    </head>
    <body>
        <f:view>
            <h:form>
                <h:messages/>
                <h:panelGrid columns="2">
                    <h:outputText value="Username"/>
                    <h:inputText
                        label="Username"
                        value="#{user.user.username}"
                        required="true"/>
                    <h:outputText value="First name"/>
                    <h:inputText
                        label="First name"
                        value="#{user.user.firstName}" />
                    <h:outputText value="Last name"/>
                    <h:inputText
                        label="Last name"
                        value="#{user.user.lastName}" />
                    <h:outputText value="Password" />
                    <h:inputSecret
                        label="Password"
                        value="#{user.user.password}"
                        required="true" />
                    <h:panelGroup/>
                    <h:commandButton
                        action="#{user.saveUser}"
                        value="Save"/>
                </h:panelGrid>
            </h:form>
        </f:view>
    </body>
</html>

Zastanawia mnie co nie tak z moim DI. Klasy wyglądają dosyć sensownie. Będę wdzięczny za podpowiedzi. Widoki są w dobrym katalogu, bo index.jsp wyświetla się po usunięciu managed-bean z faces-config.xml.

Pozdrawiam,

0
import javax.ejb.EJB;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import lux.domain.User;
import lux.facade.UserDAO;
 
public class UserController {
    @EJB
    UserDAO userDao;
}

Nie jestem pewien, ale wydaje mi się, że tutaj powinien być interfejs zadeklarowany a nie klasa, np:

public class UserController {
    @EJB
    UserDAOLocal userDao;
}
0

To co mówisz wydaje się nie mieć sensu albo ja czegoś nie rozumiem. UserController to klasa typu ManagedBean do GUI i musi jedynie implementować interfejs Serializable i wybrać przestrzeń nazw np. session (czyli te ziarenka będą dostępne w danej sesji z poziomu widoków JSF/JSP).

Poprzednio nie miałem implements Serializable, teraz mam wciąż występuje problem.

Wydaje mi się, że problem dotyczy wstrzyknięcia dataSource (czyli usługi) udostępniającej bazę danych z EJB.

0

Tak, miałeś rację olek1 - wstrzykuje się interfejs.

1 użytkowników online, w tym zalogowanych: 0, gości: 1