문제

I am quite new to EJB. I need stateful bean in my EAR application. I have created simple stateful session bean in an ejb module:

@Stateful
public class Test {

    public Test() {
    }

    private int i;

    @PostConstruct
    public void initialize() {
        i = 0;
    }

    public int getI() {
        return i++;
    }
}

And I call it from servlet in a war module:

public class TestServlet extends HttpServlet {

    @EJB
    Test test;

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        HttpSession session = request.getSession(true);

        out.println("<html>");
        out.println("<head>");
        out.println("<title></title>");            
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>" + test.getI() + "</h1>");
        out.println("</body>");
        out.println("</html>");         
        out.close();
    }
...
}

When I run it, the number gets bigger with each refresh of a browser.

0, 1, 2, ...

But when I run it in another browser, the number doesn't start from 0 but continues the session from the previous browser. It behaves like singleton.

3, 4, 5, ...

Why wasn't a new instance of the bean created? I tried to put the session bean into the war module, or annotate it with SessionScoped but result is the same.

Can you help me to create a new instance of the stateful bean for each http session?

도움이 되었습니까?

해결책

A single servlet is created to service all requests. You're injecting an instance of a single stateful session bean into the servlet, so all requests will use that same stateful session bean. It is rarely useful to inject stateful session beans.

You need to create a per-HttpSession instance of the stateful session bean:

// Declare the reference without injection...
@EJB(name="ejb/test" beanInterface=Test.class)
public class TestServlet extends HttpServlet {
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        HttpSession session = request.getSession(true);
        Test bean = session.getAttribute(BEAN);
        if (bean == null) {
            try {
                // ...and then create an instance by looking it up from java:comp/env
                bean = (Test)new InitialContext().lookup("java:comp/env/ejb/test");
            } catch (NamingException ex) { ... }
            session.setAttribute(BEAN, bean);
        }

        ...
    }
}

Alternatively, if you have CDI, you could mark your stateful session bean as @SessionScoped and use @Inject for injection rather than @EJB.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top