今天在学习EJB3的时候发现了一个问题。我所使用的环境是GLASSFISH V3. 实现了一个简单的stateless session bean作为练习如下:
business interface 如下:
@Local
public interface FirstLocalSessionBeanInterface {
public String getHelloMessage();
}
Session bean 如下:
@Stateless
public class FirstLocalSessionBean implements FirstLocalSessionBeanInterface {
public String getHelloMessage() {
return "Hello! This is a Local StateLessSessionBean!";
}
}
然后在同一个ear项目里建立web project来调用该EJB, 我使用JSP调用一个POJO类, 原本打算在该POJO类里直接注入EJB, 代码如下:
public class LocalSessionBeanDelegate {
@EJB
private FirstLocalSessionBeanInterface bean;
public String getEJBMessage(){
return bean.getHelloMessage();
}
我在jsp中调用该类的时候,却总是报bean空指针,这说明@EJB并没有成功的注入该属性。
后来我在java.net的glassfish forum上找到了答案。原来GLASSFISH下的EJB资源注入只支持受容器管理的对象,如EJB,SERVLET,JSF等等。而对于普通POJO是不支持的。要在这些POJO里使用EJB,还得使用传统的JNDI查询方式。
我之后尝试了一下servlet的情形,代码如下:
public class LocalSessionBeanServlet extends HttpServlet {
@EJB
private FirstLocalSessionBeanInterface bean;
/**
* Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
System.out.println(bean.getHelloMessage());
request.setAttribute("message", bean.getHelloMessage());
}
// <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
/**
* Handles the HTTP <code>GET</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
request.getRequestDispatcher("./localBeanTest.jsp").forward(request, response);
}
/**
* Handles the HTTP <code>POST</code> method.
* @param request servlet request
* @param response servlet response
* @throws ServletException if a servlet-specific error occurs
* @throws IOException if an I/O error occurs
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
request.getRequestDispatcher("./localBeanTest.jsp").forward(request, response);
}
/**
* Returns a short description of the servlet.
* @return a String containing servlet description
*/
@Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}
经测试,该代码可以正常的实现EJB注入。
经过该例,发现在GLASSFISH下EJB注入只能在容器管理的组件中实现。我不知道这是否是EE规范中得到规定还是GLASSFISH的实现是这样要求。哪位大虾可以告知一下,不胜感谢。
注:之后查阅了JEE5规范,发现确实在其中有对于这方面的规定。JEE支持DI的组件主要有以下几种:
Servlet: servlets/servlet filters/event listeners
JSP: tag handlers/tag library event listeners
JSF: scoped managed beans
JAX-WS: service endpoints/handlers
EJB; beans/interceptors
Java EE platform: main class (static)/login callback handler