Stateful session beans unexpected behaviour when packaged in a war and packaged in an ear->jar
Asked Answered
C

1

1

I am new to ejbs. I wrote a stateful session bean scoped @SessionScoped. Then I injected the ejb into my servlet.

@Local
@SessionScoped
@Statueful
public class CartServiceImpl implements CartService {

    private int i = 0;

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

In my servlet

@Inject
private CartService cartService;
.
.
.
out.print(cartService.getI());

Then I opened two browsers (IE, FF) and have hit the servlet. In IE I see output starting from 0 to n. In firefox also I see the output starting from 0 to n.

Then I created created an ear which has a jar and a war. The jar contains all ejbs. war contains the servlets.

This is how I injected the ejb into the servlet

@Resource(lookup = "java:app/ejb-beginner-ejb/CartServiceImpl")
private CartService cartService; 

Then I tried requesting the same servlet from IE and FF and I get unexpected output.

The output is as follows

In IE I requested for first time and I get 0 as output. Then I refreshed the page and I get 1 as output. Then I move to FF, send the request for first time and I get 2 as output instead of 0. Then I move to IE and refresh the page and I get 3 as output instead of 2.

What I understood is the app server is creating only one instance of the stateful ejb. How can I fix this?

What is the difference between packaging the ejbs in the war and packaging them separately in a jar module?

Creodont answered 31/1, 2014 at 8:43 Comment(3)
Interesting. Apparently when you packaged it as part of the war, session scoped literally meant part of the HTTP session while when you packaged it in an EJB module, that is of course no longer related to any HTTP session and it was apparently managed based on the IP of the client. That's what I deduce from your test results anyway. Stateful beans are mysterious beasts to me.Overburdensome
Okay. In this case when will the stateful session bean expire? When the stateful session bean is binded with the http session, it is expired as soon as the client terminates (for example Closing the browser) In case an http session is not binded and the stateful session bean uses ip of the client, when is it removed/terminated? Is it when the client changes his ip? Is it when the client restarts his machine?Creodont
If you find out, let me know!Overburdensome
E
1

I think it has to do with the fact that the @SessionScoped annotation is meant to be used only in a web context, otherwise, like in your your second case, it doesn't make sense and you should assume that it will be ignored and your stateful ejb will behave like an old regular stateful ejb, and in general, you shouldn't inject stateful resources into stateless ones because usually the results are unpredictable and dependent on the container implementation. Having said that, servlets are stateless components, and the container is not required by the spec to create one instance per request or session, from the Servlet 3.0 spec (Sec. 2.2):

For a servlet not hosted in a distributed environment (the default), the servlet container must use only one instance per servlet declaration. However, for a servlet implementing the SingleThreadModel interface, the servlet container may instantiate multiple instances to handle a heavy request load and serialize requests to a particular instance.

however you shouldn't even rely on the fact that there's only one servlet instance since in fact many containers use servlet pooling to increase performance, on the other hand, when you look up or inject a stateful EJB into a stateless component it's your responsibility to take care of the scope of that particular instance so that it can work as it's supposed to, in this case, since you don't have control over the instantiation of your servlet instances, neither you have it over your ejb instances.

EDIT

I would use session scoped beans in my web app, but if you definitely have to use stateful EJBs (because you need some of the services provided by them) than you could, in the servlet, lookup the ejb when needed and associate it to the user HttpSession to make it session scoped, in this case, you should be careful and make sure that if the session expires the ejb gets removed by implementing session lifecycle listeners, check this

other implications you should consider here

Educational answered 31/1, 2014 at 16:25 Comment(3)
I understood only little from your explanation. My understanding is, one should never inject stateful beans into a servlet/stateless bean. So what should I do to use stateful beans then? Should I create the instance of the stateful bean in the doGet or doPost method of servlet? Is my understanding right?Creodont
I am sorry, I still cant understand. Can you please provide me a code snippet regarding what do you mean by looking up the ejb and associating with the user HttpSession.Creodont
I injected a SFSB into my servlet and opened 2 browsers and I can see two different session. My SFSB is session scoped. Its working fine. I used jboss to test.Creodont

© 2022 - 2024 — McMap. All rights reserved.