if I understand it right a @Stateful bean saves the state. If the client does a request again it comes back to the same instance. So it's possible to save class-attributes, what's not possible in @Stateless. In an other thread here someone wrote "it's like a classical java instance, every injection gets it's own instance of this bean".
But I don't understand how the mapping of the request to the @Stateful bean works - what is to do that it works? This question goes out for two cases:
This question is not for the technical process of the container / server-software, it's for the specific doing at the development. Thank you for your support.
Greetings
That's unfortunately not the way web services work. The stateful bean is only stateful for the stateless bean. And not for a client. And that's very dangerous for several reasons:
-The stateless bean saves state of a call in its stateful reference. But the next call of the stateless bean can be happen in another context/by another client.
-The stateful bean can be destroyed by the container while the stateless is still alive/in the pool.
You can use stateful beans with remote-calls or in web applications but not in the context of webservices.
A webservice is per definition without any application state. The Java EE-Servlet listens for the requests and call one stateless bean implementation from a pool of instances.
If you really want to implement stateful web services, you must do it on your own. The following example will work in a Java EE 6-container:
/// Client depended values(your statefull bean)
public class SessionValues {
private final List<String> values = new ArrayList<String>();
public void addValue(String s){
values.add(s);
}
public List<String> loadValues(){
return Collections.unmodifiableList(values);
}
}
You can store the sessions in a singleton(your own pool)
@Singleton
@Startup
public class StatefullSingleton {
private final Map<String, SessionValues> sessions = new Hashtable<String, SessionValues>();
@Lock(LockType.READ)
public void addValue(String sessionId, String value) {
if (!sessions.containsKey(sessionId))
sessions.put(sessionId, new SessionValues());
SessionValues p = sessions.get(sessionId);
p.addValue(value);
}
@Lock(LockType.READ)
public List<String> loadValues(String sessionId) {
if (sessions.containsKey(sessionId))
return sessions.get(sessionId).loadValues();
else
return new ArrayList<String>();
}
}
and inject the singleton in the stateless webservice beans(the pool, the singleton and the calls of the singleton are managed by the Java EE-Container):
@Stateless
@WebService
public class WebserviceBean {
@Inject
private StatefullSingleton ejb;
public void addvalue(String sessionId, String value) {
ejb.addValue(sessionId, value);
}
public List<String> loadValues(String sessionId) {
return ejb.loadValues(sessionId);
}
}
The example above is only a pattern. You must be very carefully with the session-id and the multithreading if you want to implement it in production.
Edit: remove the unnecessary @localBean