Concurrent access to Stateful Session Beans

Discussions

EJB design: Concurrent access to Stateful Session Beans

  1. Concurrent access to Stateful Session Beans (12 messages)

    I need to implement a WorkFlow synchronization logic within a J2EE application. In simple words multiple instances of the same Java class (the client) that run within the transaction context of an EJB component require access to an algorithm that executes synchronization of data required to complete the transaction.

    The component that should implement this data synchronization must serve one client at the time and should keep state of significant information during the application execution.

    After long discussions my team and I decided to opt for a single Stateful Session Bean instance, which should be offered to a different instance of the client at different times. I know that a Stateful Session Bean can only serve one client, and in fact this is what I am trying to implement. When one client instance is done with its transaction, he releases its reference to the EJBObject to let a new client reuse it. We are not concerned that this is going to be a bottleneck right now.

    I have resolved the problem of sharing the same instance of the SFSB without violating the EJB spec, making sure that only one client at the time has a component interface reference to it during a transaction. At runtime the first client creates the Bean, and then binds the component interface to JNDI. The other clients always lookup in JNDI for the component interface before recreating the bean (which should occur only if the bean times out).

    I wrapped the client call logic in a synchronized method within a Singleton Handler class which should prevent the Session Bean clients from trying to concurrently access the SFSB methods at the same time (Stateful Session beans can only have one thread of execution within it). This Handler class acts as a Business Delegate and Service Locator, hiding the complexity of instantiating and synchronizing the bean access to new clients at the same time.

    I thought it was a decent solution when I realized that the method in the Handler Class is synchronized only within one JVM, and that distributing the application over multiple servers (where the Handler would be executed on different JVMs) would defeat the purpose of having the Handler class controlling the access to the Bean. In simple words my synchronization mechanism would no longer work.
    On the other hand, I can’t have my clients calling the Session Bean directly, as this would fail because they would try to access it concurrently, which is forbidden by the spec.
    Even worse, if I decide to rewrite the business method directly in the Handler class (doing completely without the Session Bean), I would still have the same problem, unless I force the Application Server to run the Handler class on one JVM only, which makes it not scalable.

    Has anyone had to solve a similar problem before within a J2EE context ? Any tips or help that would put me on the right track would be highly appreciated.

    Thanks
    Stefano Gallo
  2. Here are some ideas:

    1) Are the clients aware of each other? If so, you can have each client in the workflow pass the EJB handle to the next client in the workflow. This eliminates the lookup and the need for synchronization.

    2) If the clients are unaware of each, and are contributing data to an extended transaction, would it be possible to use a messaging solution instead of a SFSB? This kind of asynchronous, uncoordinated communication is precisely what messaging is good for.

    If none of those options work for you, and you genuinely want your SFSB to be a global singleton in your network, you could implement an RMI service on a central server that returns the EJB handle, marking it as unavailable until client explicitly releases it. You can then use a business delegate client-side to invoke, lock and release the SFSB singleton within a synchronized method.
  3. Thanks for the ideas Paul.

    No. 1 is not possible as clients are not aware of each other, and run concurrently.

    Looking at your second idea, the data is already coming from a Message Bean's consumed message. The Message Bean itself would have to implement the logic to collect the rest of the data based on the message it has received. At the moment it does that by delegating this logic to a Java class. The idea is that this java class would try to use the Stateful Session Bean for data synchronization, which doesn't work. May be if you can elaborate a bit more on your idea, it could turn out to be a valid alternative.

    Your last idea is interesting, but I have the feeling that it would not solve the problem entirely. The client itself lives in the Container, and the synchronized method (provided that making the method synchronized is allowed, which I think it is not), would be synchronized only within a single JVM. Therefore, it would not be scalable.
  4. Looking at your second idea, the data is already coming from a Message Bean's consumed message. The Message Bean itself would have to implement the logic to collect the rest of the data based on the message it has received. At the moment it does that by delegating this logic to a Java class. The idea is that this java class would try to use the Stateful Session Bean for data synchronization, which doesn't work. May be if you can elaborate a bit more on your idea, it could turn out to be a valid alternative.
    Now I understand your situation a bit better. You are trying to use the SFSB to manage cross-MDB communication to coordinate a workflow.

    I think that there are better solutions using a pure messaging approach. Say you have MDB-1 to MDB-4 collecting client data, and MDB-F that completes the workflow. Rather than trying to store data in memory, MDB-1 to MDB-4 can store their data persistently, in temporary tables in the database. You can also write a WorkFlowChecker javabean with a method that returns true/false, depending on whether all the data is collected (which it determines by querying the database).

    Each time MDB-1 to MDB-4 receive a message, they:

    1) Save the incoming data.
    2) Invoke the WorkFlowChecker to see if all the data is collected.
    3) If true, send a message to MBD-F to complete the workflow.

    This is pretty robust: you are protected from server failures, making it possible to recover and continue the workflow after the server comes back up. Also, everything clusters nicely; there is no need for the MDB to be on one machine. You will probably also want to write a batch process that periodically checks for old, incomplete workflows and does cleanup.
  5. Hi
      If you use SLSB or MDB, you have to explicitly manage state of client in persistence storage will give performance problems, but without using this kind of mechanism(Entity or MDB) you can't make this as a scalable application.

      Alternative solutions could be make it the workflow logic SFSB as independent ejb module and deploy in primary server apart from your deployable application into diferent servers. You have to lookup this component either using remote inteface or local interface from your handler.
     
      
    Regards
    Lakshmana Rao AV
  6. It sounds interesting, but what would be the advantage of using Message Driven Beans to go to the database instead of a dedicated Entity Bean ?

    A couple of considerations on using Entity Beans:

    1) Perhaps the Entity Bean could try to cache the temporary result set and store only when it is a valid one. The transaction would be longer, but it is not that bad in our case, especially if we consider that that, should any of the steps involved in this logic fail, we would need to rollback.

    2) Having several transactions means that we would need to query a history table to reconstruct the data for the specific Activity if any of the steps fails. It is not that bad either, but could occur frequently.

    Regards
    Stefano
  7. A dedicated Entity bean would be fine. I was suggesting this:

    MDB -> JDBC -> Database

    But an Entity bean would give you even greater flexibility:

    MDB -> Entity -> Database

    I suggest you define an Entity to represent an on-going operation, using some kind of operation ID as its primary key.
  8. Hi,

    I have a similar need for synchronization of SFSB.

    For the moment I seem to have the possibility to tweak the AppServer (JBoss)
    as I dont need to be server independant, or implement the logic as BMT Entity Bean.

    Did you find a solution for your problem?

    Thomas

  9. In simple words multiple instances of the same Java class (the client) that run within the transaction context of an EJB component require access to an algorithm that executes synchronization of data required to complete the transaction.
    >>


    "require access to an algorithm"? I can't think of any reason why access to an algorithm would need to be synchronized. It's the *data* that needs to be protected.

    Some of the points in your post lead me to believe you may be attempting to misuse the J2EE framework. If you have some global data that needs to be accessed by multiple clients, it's best to stick it in a database (that's what they're there for.) You should use the synchronization mechanisms offered by your DBMS to ensure exclusive access to this critical data.

    Session EJB's (stateful or otherwise) are not intended to store global data, and this approach is not scalable anyway (as you point out.) Entity beans could be used for this purpose, but it is unclear from your description whether you would benefit from their use.

    One final point: I gather from your post that this "Handler" class might be executing within an EJB container. As you pointed out, this is not scalable -but you should also know that EJBs are forbidden by the spec to perform any synchronization internally.
  10. The idea was that there would be a synchronized method in the Handler class to control clients access the bean's method(s). This way, if the first client gets a reference to the Session Bean, the second client trying to invoke the same business method is blocked. But indeed, the Handler runs in the context of the container, so perhaps this is not a good idea.

    Just a personal thought, wouldn't it be nice if the spec allowed he container to block the second client, instead of throwing an exception ? Protection against concurrent access to the same business method would be guaranteed anyway.

    Entity beans ? We are thinking about it, although, as a solution it may be a bit overdone for a WorFlow activiy trying to collect valid incoming data before processing it. In a way, our "persistent store" is made of JMS queues that keep hold of messages carrying data until an instance of a Message Bean consumes it. That is where the data that needs to be synchronized is coming from.

    I don't see how the problem of data synchronization can be solved without making use of a persistent store, which is what I was trying to avoid. Perhaps it's the only solution...
  11. If the interface to your bean is a JSP then why wouldn't the isThreadSafe="false" directive be sufficient to prevent concurrent access to the same methods at the same times?
  12. I also save my stateful items as session objects using unique naming schemes so they don't stomp on each other.
  13. If the interface to your bean is a JSP then why wouldn't the isThreadSafe="false" directive be sufficient to prevent concurrent access to the same methods at the same times? <<<
    If by interface you mean the Client of the Session Bean, then, the clients are not JSPs, but a handler java class that lives in the Container context.