0

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:

  1. I call @Stateful by a webservice by the client software. Is it an ID I have to send with it? But what is the ID and how do the container knows that this is the identify-attribut and routes it to the right @Stateful bean?
  2. I call @Stateful out of an @Stateless bean. As example if the client first calls a @Stateless bean and is redirect to his @Stateful bean.

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

Gersee
  • 806
  • 3
  • 15
  • 30

1 Answers1

0

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

Jan Piel
  • 540
  • 2
  • 6
  • Just wondering, why did you feel the need to add `@LocalBean` to your code? What do you think it gets you and what will be different if you leave it out? – Arjan Tijms Mar 01 '15 at 16:10
  • 1
    You are right, the LocalBean-Annotaion is not necessary. It was added by Eclipse, removed it. – Jan Piel Mar 04 '15 at 11:27