在我的简单jsp页面上调用EJB bean时出现了这样的错误:
WARNING: StandardWrapperValve[jsp]: PWC1406: Servlet.service() for servlet jsp threw
exception java.lang.NullPointerException
at appjpa.ejb.UsersFacade.findAllStudents(UsersFacade.java:65)
at org.apache.jsp.Students_jsp._jspService(Students_jsp.java from :75)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:111)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:403)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:492)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:378)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1539)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98)
at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:330)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:174)
at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:828)
at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:725)
at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019)
at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
at java.lang.Thread.run(Thread.java:662)
我的jsp页面的代码如下:
<%@page import="appjpa.entities.Users"%>
<%@page import="java.util.ArrayList"%>
<%@page import="socnet2.Student"%> <!-- class Student emulates real student -->
<%@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>
<jsp:useBean class="appjpa.ejb.UsersFacade" id="dao" scope="application"></jsp:useBean>
<p><b>List of all students:</b></p>
<form action="/AppJPA/Edit" method="POST">
<jsp:scriptlet>
int counter = 0; if (dao != null){
for (Users s : dao.findAllStudents()) {
</jsp:scriptlet>
<p> <jsp:expression> s.getName() + " " + s.getSurname()</jsp:expression></p>
<input type="submit" name="Edit_<%=counter%>" value="Edit" />
<input type="submit" name="Delete_<%=counter%>" value ="Delete"/>
<jsp:scriptlet>
counter++;
}}
</jsp:scriptlet>
<input type="submit" name="Add_new_student" value ="Add new student"/>
</form>
</body>
用于用户的NetBeans 7.0.1向导实体类自动生成的内容如下所示:
@Entity
@Table(name = "USERS")
@NamedQueries({
@NamedQuery(name = "Users.findAll", query = "SELECT u FROM Users u"),
@NamedQuery(name = "Users.findById", query = "SELECT u FROM Users u WHERE u.id = :id"),
@NamedQuery(name = "Users.findByName", query = "SELECT u FROM Users u WHERE u.name = :name"),
@NamedQuery(name = "Users.findBySurname", query = "SELECT u FROM Users u WHERE u.surname = :surname"),
@NamedQuery(name = "Users.findByLogin", query = "SELECT u FROM Users u WHERE u.login = :login"),
@NamedQuery(name = "Users.findByPassword", query = "SELECT u FROM Users u WHERE u.password = :password"),
@NamedQuery(name = "Users.findByRole", query = "SELECT u FROM Users u WHERE u.role = :role")})
public class Users implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
// @NotNull
@Column(name = "ID")
private Integer id;
@Size(max = 40)
@Column(name = "NAME")
private String name;
@Size(max = 40)
@Column(name = "SURNAME")
private String surname;
@Size(max = 40)
@Column(name = "LOGIN")
private String login;
@Size(max = 40)
@Column(name = "PASSWORD")
private String password;
@Size(max = 40)
@Column(name = "ROLE")
private String role;
@ManyToMany(mappedBy = "usersList")
private List<SubjectGroup> subjectGroupList;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "idCreator")
private List<SubjectGroup> subjectGroupList1;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "idSender")
private List<Messages> messagesList;
public Users() {
}
public Users(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public List<SubjectGroup> getSubjectGroupList() {
return subjectGroupList;
}
public void setSubjectGroupList(List<SubjectGroup> subjectGroupList) {
this.subjectGroupList = subjectGroupList;
}
public List<SubjectGroup> getSubjectGroupList1() {
return subjectGroupList1;
}
public void setSubjectGroupList1(List<SubjectGroup> subjectGroupList1) {
this.subjectGroupList1 = subjectGroupList1;
}
public List<Messages> getMessagesList() {
return messagesList;
}
public void setMessagesList(List<Messages> messagesList) {
this.messagesList = messagesList;
}
@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.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 Users)) {
return false;
}
Users other = (Users) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "appjpa.entities.Users[ id=" + id + " ]";
}
}
最后,类Usersfacade是这样的:
@Stateless
public class UsersFacade extends AbstractFacade<Users> implements UsersFacadeLocal {
@PersistenceContext(unitName = "AppJPAPU")
private EntityManager em;
protected EntityManager getEntityManager() {
return em;
}
public UsersFacade() {
super(Users.class);
}
@Override
public Users checkInBase(String login, String password) {
Users u = (Users)(em.createNamedQuery("Users.findByLogin").setParameter("login", login).getSingleResult());
return u;
}
@Override
public void removeUserFromSubjectGroup(Users user, SubjectGroup group) {
Users u = em.find(Users.class, user.getId());
SubjectGroup g = em.find(SubjectGroup.class, group.getId());
if (u != null && g != null) {
user.getSubjectGroupList().remove((SubjectGroup)group);
group.getUsersList().remove(user);
em.merge(user);
em.merge(group);
}
}
@Override
public void addUserToSubjectGroup(Users user, SubjectGroup group) {
Users u = em.find(Users.class, user.getId());
SubjectGroup g = em.find(SubjectGroup.class, group.getId());
if (u != null && g != null) {
user.getSubjectGroupList().add((SubjectGroup)group);
group.getUsersList().add(user);
em.merge(user);
em.merge(group);
}
}
@Override
public List<Users> findAllStudents() {
String role = new String("student");
List<Users> students = (List<Users>)(em.createNamedQuery("SELECT u FROM Users u WHERE u.role = :role").setParameter("role", role).getResultList());
if (students == null){
System.out.println("Students are null!!!");
}
return students;
}
@Override
public boolean deleteStudent(Users user) {
Users u = em.find(Users.class, user.getId());
em.remove(user);
return true;
}
@Override
public boolean updateStudent(Users studentToEdit, String newName, String newSurname, String newLogin, String newPassword) {
Users u = em.find(Users.class, studentToEdit.getId());
u.setName(newName);
u.setSurname(newSurname);
u.setLogin(newLogin);
u.setPassword(newPassword);
em.merge(studentToEdit);
return true;
}
@Override
public void insertStudenttoDB(Users student, String newName, String newSurname, String newLogin, String newPassword) {
em.persist(student);
Users u = em.find(Users.class, student.getId());
if (u != null) {
student.setName(newName);
student.setSurname(newSurname);
student.setLogin(newLogin);
student.setPassword(newPassword);
em.merge(student);
}
}
}
我对EJB很新,也许我没有正确使用它们。我尝试在其他页面上调用UsersFaced中的其他方法,但收到了同样的错误。请解释我做错了什么......
答案 0 :(得分:1)
如果您通过@PersistenceContext
手动将EJB类实例化为JSP中的简单java bean而不是<jsp:useBean>
获取容器托管实例,则不会注入@EJB
。我不知道你是如何以及在哪里学习编写JSP的,但它无疑是基于一本过时的书籍/教程。您需要对当前的模型 - 视图 - 无控制器方法进行重大更改。您需要添加一个控制器。抛弃所有<jsp:xxx>
标签并创建一个充当真实控制器的Servlet。
E.g。
@WebServlet("/students")
public class StudentsServlet extends HttpServlet {
@EJB
private UsersFacade usersFacade;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("users", usersFacade.findAllStudents());
request.getRequestDispatcher("/WEB-INF/students.jsp").forward(request, response);
}
}
请注意,我将您的JSP移动到/WEB-INF
文件夹中,因此无法在不调用servlet的情况下有目的或无意中调用它。
现在,按如下方式更改JSP:
<%@page pageEncoding="UTF-8" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<h4>List of all students:</h4>
<form action="${pageContext.request.contextPath}/edit" method="post">
<c:forEach items="${users}" var="user" varStatus="loop">
<p><c:out value="${user.name} ${user.surname}" /></p>
<input type="submit" name="Edit_${loop.index}" value="Edit" />
<input type="submit" name="Delete_${loop.index}" value ="Delete"/>
</c:forEach>
<input type="submit" name="Add_new_student" value ="Add new student"/>
</form>
</body>
</html>
通过servlet的网址http://localhost:8080/AppJPA/students打开它,以便其doGet()
能够找到合适的工作,并且JSTL <c:forEach>
会相应地迭代users
。
顺便说一句,我对你如何命名按钮的方式表示怀疑。识别所选用户将非常笨拙。但这是一个不同的问题。
答案 1 :(得分:0)
如果这是你的整个命名查询包,我想这个代码:
List<Users> students = (List<Users>)(em.createNamedQuery(
"SELECT u FROM Users u WHERE u.role = :role").setParameter("role", role)
.getResultList());
搞砸了。您正在尝试创建命名查询,其名称等于SELECT u FROM Users u WHERE u.role = :role
。
您已在Users
注释中定义了命名查询,而您尝试使用的是这一个:
@NamedQuery(name = "Users.findByRole",
query = "SELECT u FROM Users u WHERE u.role = :role")})
因此你应该使用它的名字 - Users.findByRole
。此外,您不需要转换为List<Users>
,因为有appropriate method parameter来定义结果类型。应该是:
List<Users> students = em.createNamedQuery("Users.findByRole", Users.class)
.setParameter("role", role).getResultList();
您的代码中几乎没有不良做法,例如:
User
而不是Users
,<jsp:scriptlet>
并没有让它变得更好。