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:
- 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.
- 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.
- Life of SLSB ends when container decides to adjust size of the pool
Life of stateful session bean (SFSB) is roughly follows:
- New instance is created by container when JNDI lookup or injection happens.
- 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.
- 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;
}
}