Frage

With EJB (3.x) you have a choice of Session Beans: @Stateful and @Stateless. If I understand the basics behind these two options:

  • @Stateful - Each user/client gets their own and is thus typically not pooled; maintains state across multiple requests
  • @Stateless - Does not maintain state between requests and thus is usually pooled so each new client request gets a fresh bean

My core question here is quite simply, however there are several mini-questions that I have that are tangential to it: how does my POJO design differ between @Stateful beans vs. @Stateless? In other words, if I have a HelloWorld bean that implements the Hello interface, how does that POJO's design change depending on whether I want it to be stateful or not?

Tangential to this:

  • What different restrictions does the app container (in my case GlassFish) impose upon the EJB depending on whether it is stateful or not?
  • In the case of @Stateful, how does a client-side request from the same user/client get mapped to the correct bean (the one maintaining the client's state from a previous request)?
  • When do session beans die? I assume its immediately after the request is done for @Stateless, but no clue for @Stateful.

Thanks in advance for any clarity here.

War es hilfreich?

Lösung

Regarding the core question "how does my POJO design differ between @Stateful beans vs. @Stateless":

Your hello world example is an excellent example of a @Stateless session bean: the implementation has no state (no class instance variables). It makes no assumptions about state. If you do need "more information" in a @Stateless bean look it up, (re)compute it, etc. If you break this rule and define instance variables on the bean, you have no assurance that the information will be what you expect it to be on each invocation of the bean: don't do it.

Your design of a @Stateful bean would keep internal state (class instance variables) that the container will preserve for the life of the bean; the bean must be Serializable. There are very real run-times costs (memory, and managing the issues around your second tangential question, particularly in a clustered environment) associated with keeping the bean around for the life of the session - so use this only as appropriate (which justifies the existence of @Stateless beans).

For example, consider a simple sign-up page: enter user name, email address, etc, followed by "are you sure"? A @Stateful bean can preserve this temp information until you're ready to submit it to a back end.

Google for examples; here's one: http://docs.redhat.com/docs/en-US/JBoss_Enterprise_Application_Platform/6/html/Beta_Documentation/Stateful_Session_Bean_Example.html

HOW the client-side gets mapped to the correct @Stateful bean is truly implementation dependent (not spec'd), however you can expect that it's managed analogous to how your Servlet Session information is maintained. That said, don't confuse the Servlet Session with a @Stateful session - they're not the same thing at all.

For Java EE 5/6 in your @Stateful bean annotate one method with @Remove, and when your client calls that method it'll be released back to the ether. Outside of that, as long as you hold a reference to the @Stateful bean (i.e. in your Servlet Session) you can expect that @Stateful bean to be around when you need it.

See also: http://docs.oracle.com/javaee/5/tutorial/doc/bnbmt.html

Andere Tipps

1) Your EJB/Pojo really doesn't know the difference. You as a developer do, but at the code level, a Stateless bean looks pretty much like a Stateful bean. The life cycles and callbacks are effectively the same, the distinction is that the client has more control over that lifecycle, whereas with a Stateless bean the container has control over that lifecycle.

2) Your client simply maintains a copy of the Session Bean instance. So, for example, in a web container you can simply stuff the instance in to the session. What you don't want to do is simply continually inject a Stateful Session bean (using @EJB) for every request as this will create a new one each time. It's better to check your session, if it does not exists, then look it up normally.

3) Stateful beans can have a method annotated with @Remove. When you call this method, the bean is destroyed. If you do not call this method, the container has a timeout facility that will reap the session beans automatically after some configured duration. There is no expectation of a Stateful bean surviving a server restart (though that contract may well be different in a clustered environment).

There's also a bunch of legacy EJB 2 behavior that mostly works, you just have to jump through hoops to get to it, the modern stuff is easier.

  • If you have instance variables in a Stateless Session Bean, their values will be meaningless (practically speaking). This is because you never know which instance of a Stateless Session Bean will be retrieved from the instance pool to service a request.

  • Stateless Session Beans only die when the container decides to kill them. They are instantiated as needed, and will only be destroyed if the container decides to destroy them (for example if it decides to make the instance pool smaller). You say that you assume they are destroyed after the request, but this is incorrect. After the request they are returned to the instance pool and remain ready to service the next request.

Because questions are wide, I will try to answer shortly and provide links to additional information.

What different restrictions does the app container (in my case GlassFish) impose upon the EJB depending on whether it is stateful or not?

Main difference in your case is told with following quotation from specification:

Stateless session beans are session beans whose instances have no conversational state. This means that all bean instances are equivalent when they are not involved in servicing a client-invoked method. The term “stateless” signifies that an instance has no state for a specific client. However, the instance variables of the instance can contain the state across client-invoked method calls. Examples of such state include an open database connection and an object reference to an enterprise bean object.

In the case of @Stateful, how does a client-side request from the same user/client get mapped to the correct bean (the one maintaining the client's state from a previous request)?

In client side you have to store reference to business interface of stateful session bean. This object you got from the EJB container. It is container created object that contains details about how to locate server side object. Some information about these proxies in GlassFish can be found from:

When do session beans die? I assume its immediately after the request is done for @Stateless, but no clue for @Stateful.

No, stateless session bean (SLSB) do not die after request. Life of stateless session bean is:

  1. It is created when container decides so. This happens naturally in some point before it is used, but otherwise it is in the hands of container. After SLSB is created, it is placed to pool.
  2. When some client needs to call method in SLSB, one instance is taken away from pool for duration of method call. After method call is finished, instance is returned to pool. Then this instance (amoung others) is ready to serve next client.
  3. Life of SLSB ends when container decides to adjust size of the pool

Life of stateful session bean (SFSB) is roughly follows:

  1. New instance is created by container when JNDI lookup or injection happens.
  2. During its life time SFSB can server multiple method calls. It can also be passivated (basically stored to disc to save resources) and activated again.
  3. Life of SFSB ends when remove method is called or timeout (SFSB was not in use for some duration of time) happens. Containers usually have implementation specific default timeout and timeout can be also adjusted. In Java EE 6 (EJB 3.1) this timeout can be adjusted per bean basis via StatefulTimeout.

Additionally instance of session bean is discarded when system exception occurs. System exception is RuntimeException (that is not marked as application exception) or java.rmi.RemoteException. Fact that instance of SLSB is discarded is transparent to client. Next call will be for sure served by other instance of SLSB. In the case of SFSB all possible future business method calls will fail, because server side instance of SFSB does not exist anymore. Details can be found from EJB 3.1 specification chapter 14.

Definitive and detailed description of life cycle can be found from EJB 3.1 specification (4.6, 4.7). Description more detailed than above and with graphs is available in Java EE 6 Tutorial.

And what is the main effect to the design of Hello service:

@Stateless
public class HelloStateless implements HelloRemote {
    @Override
    public String getGreeting(String name) {
        return "Hi " + name;
    }
}


/**
 * This design is not possible for Stateless, because
 * subsequent calls to setName and getGreeting can be
 * handled by two different instances. For stateful it 
 * is fine, because we use one exclusively one instance.
 */
@Stateful
public class HelloStateful {

    private String name;
    public void setName(String name) {
        this.name = name;
    }

    public String getGreeting() {
        return "Hi " + name;
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top