You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomee.apache.org by Dain Sundstrom <da...@iq80.com> on 2008/08/26 19:41:58 UTC

Re: Stateful Session Bean Caching

I shelved this work for a few weeks, but got back on it last night.   
To start with, I merged the StatefulInstanceManager and  
SessionSynchronizationCoordinator into the Stateful container.  In my  
opinion, this vastly simplifies the code and because all bean call  
backs and the general EJB lifecycle is much more visible (and  
readable).  Then I extracted a simple cache interface from the  
container:

public interface Cache<K, V> {
     /**
      * Add a new entry to the cache.  The entry is marked checked-out  
and can
      * not be accessed again until checked-in.
      *
      * @IllegalStateException if an value is already associated with  
the key
      */
     void add(K key, V value);

     /**
      * Marks the entry checked-out, so this entry can not be accessed  
until
      * checked-in.
      *
      * @throws IllegalStateException if the entry is already checked  
out.
      * @throws Exception if an entry is loaded and the afterLoad  
method threw an
      * exception
      */
     V checkOut(K key) throws Exception;

     /**
      * Marks the entry available, so it can be accessed again.
      *
      * @throws IllegalStateException if the entry is not checked out.
      */
     void checkIn(K key);

     /**
      * Removes the entry from the cache.
      */
     V remove(K key);

     /**
      * Removes all of th entries that match the specified filter.
      */
     void removeAll(CacheFilter<V> filter);

     /**
      * Callback listener for cache events.
      */
     public interface CacheListener<V> {
         /**
          * Called after an entry is loaded from a store.
          *
          * @throws Exception if there is a problem with the instance
          */
         void afterLoad(V value) throws Exception;

         /**
          * Called before an entry is written to a store.
          *
          * @throws Exception if there is a problem with the instance
          */
         void beforeStore(V value) throws Exception;

         /**
          * Called when an instance has been removed from the cache  
due to a
          * time-out.
          */
         void timedOut(V value);
     }

     /**
      * CacheFileter is used to select values to remove during a  
removeAll
      * invocation.
      */
     public interface CacheFilter<V> {
         /**
          * True if the filter matches the value.
          */
         boolean matches(V v);
     }
}

Generally, the container checks out an instance when a method is  
invoked, and checks it back in when the transaction completes.  This  
behavior is due to the Stateful specification that an instance can not  
be passivated (e.g., written to disk, distributed across a cluster,  
etc.)  while in a transaction.  The container is notified when the  
cache loads or stores an instance so it can make the proper  
ejbActivate/ejbPassivate calls.

I believe this interface is simple enough that we can adapt it to a  
great verity of cache implementations, but we won't know until we  
write some :)

-dain

On Jul 2, 2008, at 3:39 PM, Dain Sundstrom wrote:

> Hi all,
>
> I've been thinking about SFSB caching, and have a few ideas about  
> cache implements I'd like to experiment with like using Java5  
> concurrent collections, ehCache, ServletSession and maybe  
> Terracotta.  Before I start experimenting, I'm going to try to  
> simplify the interface between the StatefulContainer and  
> StatefulInstanceManager (the cache).  Right now, if you want to  
> plugin in a new cache, you have to either write a lot of EJB  
> specific logic or subclass from our the existing  
> StatefulInstanceManager, which sucks.  My goal is to extract a  
> simple interface with just a few Map like operations that one would  
> need to implement to introduce a new cache.
>
> Anyway, just a heads up.  I'll post again when I have a initial  
> draft of the interface available.  I'll also try to keep the  
> existing extensions of StatefulInstanceManager in Geronimo working.
>
> -dain teracotta


Re: Stateful Session Bean Caching

Posted by Dain Sundstrom <da...@iq80.com>.
My bad.  I thought this call was rerouting:

    manager.contextualise(invocation);

You may want to add some more docs to that.

BTW, I don't think you need to subclass anymore.  The cache  
implementation is chosen by the stateful container property "Cache"  
and gets built using xbean-reflect like the container.  If you still  
need to intercept the invocation calls, you can use a  
RpcContainerWrapper.  This will keep you and me from having to update  
this class as the internals of the StatefulContainer change.  It will  
also allow you to work with any future alternative implementations of  
a stateful container.  One final thing, you may want to change the  
container name to WadiStatefulContainer so people know it is for Wadi.

-dain

On Aug 27, 2008, at 6:13 AM, Gianny Damour wrote:

> Hi Dain,
>
> Thanks for having updated the WADI integration code. Over the week- 
> end, I will have a closer look to the change; update the test; and  
> perform couple of end-to-end tests within Geronimo.
>
> I agree: invocations cannot be migrated to other servers. It may not  
> look like it but the code will migrate the session bean instance to  
> the call. There is indeed some code in WADI which does the reverse  
> however it is never entered.
>
> Thanks,
> Gianny
>
> On 27/08/2008, at 7:53 AM, Dain Sundstrom wrote:
>
>> Gianny,
>>
>> I recently made some pretty big changes to the interface between  
>> the StatefulContainer and the Cache.  I updated the Geronimo  
>> integration to the best of my abilities, but I would really  
>> appreciate a review of the changes.  The biggest thing that needs  
>> attention is the WadiCacheTest.  I was unable to fully convert this  
>> test, because I don't really understand how the invocation ordering  
>> is checked.
>>
>> One thing I did see while reading the code in Geronimo is the sub- 
>> class of StatefulContainer is redirecting invocations to a remote  
>> server when the instance has been migrated to another server.  (For  
>> everyone else reading along, most cache systems will migrate the  
>> session bean instance (the state) to the call instead of migrating  
>> the call to the state as Wadi is doing here).  This strategy won't  
>> work properly in OpenEJB because we rely on thread local data such  
>> as the ThreadContext and the current Transaction in the  
>> TransactionManager.  The ThreadContext can contain data that is not  
>> serializable (TransactionPolicy) and data that should not be  
>> relocated (Security identity).  The real show-stopper is  
>> Transaction which you can not relocate without a distributed  
>> TransactionManager implementation.
>>
>> Is there a way to migrate the session back to the call?  Otherwise,  
>> you'll have to throw an exception stating that the instance has  
>> been migrated.
>>
>> -dain
>>
>> On Aug 26, 2008, at 2:38 PM, Dain Sundstrom wrote:
>>
>>> It is committed. Check it out :)
>>>
>>> -dain
>>>
>>> On Aug 26, 2008, at 10:41 AM, Dain Sundstrom wrote:
>>>
>>>> I shelved this work for a few weeks, but got back on it last  
>>>> night.  To start with, I merged the StatefulInstanceManager and  
>>>> SessionSynchronizationCoordinator into the Stateful container.   
>>>> In my opinion, this vastly simplifies the code and because all  
>>>> bean call backs and the general EJB lifecycle is much more  
>>>> visible (and readable).  Then I extracted a simple cache  
>>>> interface from the container:
>>>>
>>>> public interface Cache<K, V> {
>>>>  /**
>>>>   * Add a new entry to the cache.  The entry is marked checked- 
>>>> out and can
>>>>   * not be accessed again until checked-in.
>>>>   *
>>>>   * @IllegalStateException if an value is already associated with  
>>>> the key
>>>>   */
>>>>  void add(K key, V value);
>>>>
>>>>  /**
>>>>   * Marks the entry checked-out, so this entry can not be  
>>>> accessed until
>>>>   * checked-in.
>>>>   *
>>>>   * @throws IllegalStateException if the entry is already checked  
>>>> out.
>>>>   * @throws Exception if an entry is loaded and the afterLoad  
>>>> method threw an
>>>>   * exception
>>>>   */
>>>>  V checkOut(K key) throws Exception;
>>>>
>>>>  /**
>>>>   * Marks the entry available, so it can be accessed again.
>>>>   *
>>>>   * @throws IllegalStateException if the entry is not checked out.
>>>>   */
>>>>  void checkIn(K key);
>>>>
>>>>  /**
>>>>   * Removes the entry from the cache.
>>>>   */
>>>>  V remove(K key);
>>>>
>>>>  /**
>>>>   * Removes all of th entries that match the specified filter.
>>>>   */
>>>>  void removeAll(CacheFilter<V> filter);
>>>>
>>>>  /**
>>>>   * Callback listener for cache events.
>>>>   */
>>>>  public interface CacheListener<V> {
>>>>      /**
>>>>       * Called after an entry is loaded from a store.
>>>>       *
>>>>       * @throws Exception if there is a problem with the instance
>>>>       */
>>>>      void afterLoad(V value) throws Exception;
>>>>
>>>>      /**
>>>>       * Called before an entry is written to a store.
>>>>       *
>>>>       * @throws Exception if there is a problem with the instance
>>>>       */
>>>>      void beforeStore(V value) throws Exception;
>>>>
>>>>      /**
>>>>       * Called when an instance has been removed from the cache  
>>>> due to a
>>>>       * time-out.
>>>>       */
>>>>      void timedOut(V value);
>>>>  }
>>>>
>>>>  /**
>>>>   * CacheFileter is used to select values to remove during a  
>>>> removeAll
>>>>   * invocation.
>>>>   */
>>>>  public interface CacheFilter<V> {
>>>>      /**
>>>>       * True if the filter matches the value.
>>>>       */
>>>>      boolean matches(V v);
>>>>  }
>>>> }
>>>>
>>>> Generally, the container checks out an instance when a method is  
>>>> invoked, and checks it back in when the transaction completes.   
>>>> This behavior is due to the Stateful specification that an  
>>>> instance can not be passivated (e.g., written to disk,  
>>>> distributed across a cluster, etc.)  while in a transaction.  The  
>>>> container is notified when the cache loads or stores an instance  
>>>> so it can make the proper ejbActivate/ejbPassivate calls.
>>>>
>>>> I believe this interface is simple enough that we can adapt it to  
>>>> a great verity of cache implementations, but we won't know until  
>>>> we write some :)
>>>>
>>>> -dain
>>>>
>>>> On Jul 2, 2008, at 3:39 PM, Dain Sundstrom wrote:
>>>>
>>>>> Hi all,
>>>>>
>>>>> I've been thinking about SFSB caching, and have a few ideas  
>>>>> about cache implements I'd like to experiment with like using  
>>>>> Java5 concurrent collections, ehCache, ServletSession and maybe  
>>>>> Terracotta.  Before I start experimenting, I'm going to try to  
>>>>> simplify the interface between the StatefulContainer and  
>>>>> StatefulInstanceManager (the cache).  Right now, if you want to  
>>>>> plugin in a new cache, you have to either write a lot of EJB  
>>>>> specific logic or subclass from our the existing  
>>>>> StatefulInstanceManager, which sucks.  My goal is to extract a  
>>>>> simple interface with just a few Map like operations that one  
>>>>> would need to implement to introduce a new cache.
>>>>>
>>>>> Anyway, just a heads up.  I'll post again when I have a initial  
>>>>> draft of the interface available.  I'll also try to keep the  
>>>>> existing extensions of StatefulInstanceManager in Geronimo  
>>>>> working.
>>>>>
>>>>> -dain teracotta
>>>>
>>>
>>
>


Re: Stateful Session Bean Caching

Posted by Gianny Damour <gi...@optusnet.com.au>.
Hi Dain,

Thanks for having updated the WADI integration code. Over the week- 
end, I will have a closer look to the change; update the test; and  
perform couple of end-to-end tests within Geronimo.

I agree: invocations cannot be migrated to other servers. It may not  
look like it but the code will migrate the session bean instance to  
the call. There is indeed some code in WADI which does the reverse  
however it is never entered.

Thanks,
Gianny

On 27/08/2008, at 7:53 AM, Dain Sundstrom wrote:

> Gianny,
>
> I recently made some pretty big changes to the interface between  
> the StatefulContainer and the Cache.  I updated the Geronimo  
> integration to the best of my abilities, but I would really  
> appreciate a review of the changes.  The biggest thing that needs  
> attention is the WadiCacheTest.  I was unable to fully convert this  
> test, because I don't really understand how the invocation ordering  
> is checked.
>
> One thing I did see while reading the code in Geronimo is the sub- 
> class of StatefulContainer is redirecting invocations to a remote  
> server when the instance has been migrated to another server.  (For  
> everyone else reading along, most cache systems will migrate the  
> session bean instance (the state) to the call instead of migrating  
> the call to the state as Wadi is doing here).  This strategy won't  
> work properly in OpenEJB because we rely on thread local data such  
> as the ThreadContext and the current Transaction in the  
> TransactionManager.  The ThreadContext can contain data that is not  
> serializable (TransactionPolicy) and data that should not be  
> relocated (Security identity).  The real show-stopper is  
> Transaction which you can not relocate without a distributed  
> TransactionManager implementation.
>
> Is there a way to migrate the session back to the call?  Otherwise,  
> you'll have to throw an exception stating that the instance has  
> been migrated.
>
> -dain
>
> On Aug 26, 2008, at 2:38 PM, Dain Sundstrom wrote:
>
>> It is committed. Check it out :)
>>
>> -dain
>>
>> On Aug 26, 2008, at 10:41 AM, Dain Sundstrom wrote:
>>
>>> I shelved this work for a few weeks, but got back on it last  
>>> night.  To start with, I merged the StatefulInstanceManager and  
>>> SessionSynchronizationCoordinator into the Stateful container.   
>>> In my opinion, this vastly simplifies the code and because all  
>>> bean call backs and the general EJB lifecycle is much more  
>>> visible (and readable).  Then I extracted a simple cache  
>>> interface from the container:
>>>
>>> public interface Cache<K, V> {
>>>   /**
>>>    * Add a new entry to the cache.  The entry is marked checked- 
>>> out and can
>>>    * not be accessed again until checked-in.
>>>    *
>>>    * @IllegalStateException if an value is already associated  
>>> with the key
>>>    */
>>>   void add(K key, V value);
>>>
>>>   /**
>>>    * Marks the entry checked-out, so this entry can not be  
>>> accessed until
>>>    * checked-in.
>>>    *
>>>    * @throws IllegalStateException if the entry is already  
>>> checked out.
>>>    * @throws Exception if an entry is loaded and the afterLoad  
>>> method threw an
>>>    * exception
>>>    */
>>>   V checkOut(K key) throws Exception;
>>>
>>>   /**
>>>    * Marks the entry available, so it can be accessed again.
>>>    *
>>>    * @throws IllegalStateException if the entry is not checked out.
>>>    */
>>>   void checkIn(K key);
>>>
>>>   /**
>>>    * Removes the entry from the cache.
>>>    */
>>>   V remove(K key);
>>>
>>>   /**
>>>    * Removes all of th entries that match the specified filter.
>>>    */
>>>   void removeAll(CacheFilter<V> filter);
>>>
>>>   /**
>>>    * Callback listener for cache events.
>>>    */
>>>   public interface CacheListener<V> {
>>>       /**
>>>        * Called after an entry is loaded from a store.
>>>        *
>>>        * @throws Exception if there is a problem with the instance
>>>        */
>>>       void afterLoad(V value) throws Exception;
>>>
>>>       /**
>>>        * Called before an entry is written to a store.
>>>        *
>>>        * @throws Exception if there is a problem with the instance
>>>        */
>>>       void beforeStore(V value) throws Exception;
>>>
>>>       /**
>>>        * Called when an instance has been removed from the cache  
>>> due to a
>>>        * time-out.
>>>        */
>>>       void timedOut(V value);
>>>   }
>>>
>>>   /**
>>>    * CacheFileter is used to select values to remove during a  
>>> removeAll
>>>    * invocation.
>>>    */
>>>   public interface CacheFilter<V> {
>>>       /**
>>>        * True if the filter matches the value.
>>>        */
>>>       boolean matches(V v);
>>>   }
>>> }
>>>
>>> Generally, the container checks out an instance when a method is  
>>> invoked, and checks it back in when the transaction completes.   
>>> This behavior is due to the Stateful specification that an  
>>> instance can not be passivated (e.g., written to disk,  
>>> distributed across a cluster, etc.)  while in a transaction.  The  
>>> container is notified when the cache loads or stores an instance  
>>> so it can make the proper ejbActivate/ejbPassivate calls.
>>>
>>> I believe this interface is simple enough that we can adapt it to  
>>> a great verity of cache implementations, but we won't know until  
>>> we write some :)
>>>
>>> -dain
>>>
>>> On Jul 2, 2008, at 3:39 PM, Dain Sundstrom wrote:
>>>
>>>> Hi all,
>>>>
>>>> I've been thinking about SFSB caching, and have a few ideas  
>>>> about cache implements I'd like to experiment with like using  
>>>> Java5 concurrent collections, ehCache, ServletSession and maybe  
>>>> Terracotta.  Before I start experimenting, I'm going to try to  
>>>> simplify the interface between the StatefulContainer and  
>>>> StatefulInstanceManager (the cache).  Right now, if you want to  
>>>> plugin in a new cache, you have to either write a lot of EJB  
>>>> specific logic or subclass from our the existing  
>>>> StatefulInstanceManager, which sucks.  My goal is to extract a  
>>>> simple interface with just a few Map like operations that one  
>>>> would need to implement to introduce a new cache.
>>>>
>>>> Anyway, just a heads up.  I'll post again when I have a initial  
>>>> draft of the interface available.  I'll also try to keep the  
>>>> existing extensions of StatefulInstanceManager in Geronimo working.
>>>>
>>>> -dain teracotta
>>>
>>
>


Re: Stateful Session Bean Caching

Posted by David Jencks <da...@yahoo.com>.
On Aug 26, 2008, at 2:53 PM, Dain Sundstrom wrote:

> Gianny,
>
> I recently made some pretty big changes to the interface between the  
> StatefulContainer and the Cache.  I updated the Geronimo integration  
> to the best of my abilities, but I would really appreciate a review  
> of the changes.  The biggest thing that needs attention is the  
> WadiCacheTest.  I was unable to fully convert this test, because I  
> don't really understand how the invocation ordering is checked.
>
> One thing I did see while reading the code in Geronimo is the sub- 
> class of StatefulContainer is redirecting invocations to a remote  
> server when the instance has been migrated to another server.  (For  
> everyone else reading along, most cache systems will migrate the  
> session bean instance (the state) to the call instead of migrating  
> the call to the state as Wadi is doing here).  This strategy won't  
> work properly in OpenEJB because we rely on thread local data such  
> as the ThreadContext and the current Transaction in the  
> TransactionManager.  The ThreadContext can contain data that is not  
> serializable (TransactionPolicy) and data that should not be  
> relocated (Security identity).  The real show-stopper is Transaction  
> which you can not relocate without a distributed TransactionManager  
> implementation.

I would expect there would be some way to migrate the security  
identity.... hopefully all the servers in a cluster have the same idea  
about authentication, and this ought to be shareable.

I would expect it to be a lot faster to migrate data than a  
transaction, but.... I'm having trouble thinking of how this situation  
could arise.  What if there's a transaction started where the data  
is?  When can this happen?

thanks
david jencks

>
>
> Is there a way to migrate the session back to the call?  Otherwise,  
> you'll have to throw an exception stating that the instance has been  
> migrated.
>
> -dain
>
> On Aug 26, 2008, at 2:38 PM, Dain Sundstrom wrote:
>
>> It is committed. Check it out :)
>>
>> -dain
>>
>> On Aug 26, 2008, at 10:41 AM, Dain Sundstrom wrote:
>>
>>> I shelved this work for a few weeks, but got back on it last  
>>> night.  To start with, I merged the StatefulInstanceManager and  
>>> SessionSynchronizationCoordinator into the Stateful container.  In  
>>> my opinion, this vastly simplifies the code and because all bean  
>>> call backs and the general EJB lifecycle is much more visible (and  
>>> readable).  Then I extracted a simple cache interface from the  
>>> container:
>>>
>>> public interface Cache<K, V> {
>>>  /**
>>>   * Add a new entry to the cache.  The entry is marked checked-out  
>>> and can
>>>   * not be accessed again until checked-in.
>>>   *
>>>   * @IllegalStateException if an value is already associated with  
>>> the key
>>>   */
>>>  void add(K key, V value);
>>>
>>>  /**
>>>   * Marks the entry checked-out, so this entry can not be accessed  
>>> until
>>>   * checked-in.
>>>   *
>>>   * @throws IllegalStateException if the entry is already checked  
>>> out.
>>>   * @throws Exception if an entry is loaded and the afterLoad  
>>> method threw an
>>>   * exception
>>>   */
>>>  V checkOut(K key) throws Exception;
>>>
>>>  /**
>>>   * Marks the entry available, so it can be accessed again.
>>>   *
>>>   * @throws IllegalStateException if the entry is not checked out.
>>>   */
>>>  void checkIn(K key);
>>>
>>>  /**
>>>   * Removes the entry from the cache.
>>>   */
>>>  V remove(K key);
>>>
>>>  /**
>>>   * Removes all of th entries that match the specified filter.
>>>   */
>>>  void removeAll(CacheFilter<V> filter);
>>>
>>>  /**
>>>   * Callback listener for cache events.
>>>   */
>>>  public interface CacheListener<V> {
>>>      /**
>>>       * Called after an entry is loaded from a store.
>>>       *
>>>       * @throws Exception if there is a problem with the instance
>>>       */
>>>      void afterLoad(V value) throws Exception;
>>>
>>>      /**
>>>       * Called before an entry is written to a store.
>>>       *
>>>       * @throws Exception if there is a problem with the instance
>>>       */
>>>      void beforeStore(V value) throws Exception;
>>>
>>>      /**
>>>       * Called when an instance has been removed from the cache  
>>> due to a
>>>       * time-out.
>>>       */
>>>      void timedOut(V value);
>>>  }
>>>
>>>  /**
>>>   * CacheFileter is used to select values to remove during a  
>>> removeAll
>>>   * invocation.
>>>   */
>>>  public interface CacheFilter<V> {
>>>      /**
>>>       * True if the filter matches the value.
>>>       */
>>>      boolean matches(V v);
>>>  }
>>> }
>>>
>>> Generally, the container checks out an instance when a method is  
>>> invoked, and checks it back in when the transaction completes.   
>>> This behavior is due to the Stateful specification that an  
>>> instance can not be passivated (e.g., written to disk, distributed  
>>> across a cluster, etc.)  while in a transaction.  The container is  
>>> notified when the cache loads or stores an instance so it can make  
>>> the proper ejbActivate/ejbPassivate calls.
>>>
>>> I believe this interface is simple enough that we can adapt it to  
>>> a great verity of cache implementations, but we won't know until  
>>> we write some :)
>>>
>>> -dain
>>>
>>> On Jul 2, 2008, at 3:39 PM, Dain Sundstrom wrote:
>>>
>>>> Hi all,
>>>>
>>>> I've been thinking about SFSB caching, and have a few ideas about  
>>>> cache implements I'd like to experiment with like using Java5  
>>>> concurrent collections, ehCache, ServletSession and maybe  
>>>> Terracotta.  Before I start experimenting, I'm going to try to  
>>>> simplify the interface between the StatefulContainer and  
>>>> StatefulInstanceManager (the cache).  Right now, if you want to  
>>>> plugin in a new cache, you have to either write a lot of EJB  
>>>> specific logic or subclass from our the existing  
>>>> StatefulInstanceManager, which sucks.  My goal is to extract a  
>>>> simple interface with just a few Map like operations that one  
>>>> would need to implement to introduce a new cache.
>>>>
>>>> Anyway, just a heads up.  I'll post again when I have a initial  
>>>> draft of the interface available.  I'll also try to keep the  
>>>> existing extensions of StatefulInstanceManager in Geronimo working.
>>>>
>>>> -dain teracotta
>>>
>>
>


Re: Stateful Session Bean Caching

Posted by Dain Sundstrom <da...@iq80.com>.
Gianny,

I recently made some pretty big changes to the interface between the  
StatefulContainer and the Cache.  I updated the Geronimo integration  
to the best of my abilities, but I would really appreciate a review of  
the changes.  The biggest thing that needs attention is the  
WadiCacheTest.  I was unable to fully convert this test, because I  
don't really understand how the invocation ordering is checked.

One thing I did see while reading the code in Geronimo is the sub- 
class of StatefulContainer is redirecting invocations to a remote  
server when the instance has been migrated to another server.  (For  
everyone else reading along, most cache systems will migrate the  
session bean instance (the state) to the call instead of migrating the  
call to the state as Wadi is doing here).  This strategy won't work  
properly in OpenEJB because we rely on thread local data such as the  
ThreadContext and the current Transaction in the TransactionManager.   
The ThreadContext can contain data that is not serializable  
(TransactionPolicy) and data that should not be relocated (Security  
identity).  The real show-stopper is Transaction which you can not  
relocate without a distributed TransactionManager implementation.

Is there a way to migrate the session back to the call?  Otherwise,  
you'll have to throw an exception stating that the instance has been  
migrated.

-dain

On Aug 26, 2008, at 2:38 PM, Dain Sundstrom wrote:

> It is committed. Check it out :)
>
> -dain
>
> On Aug 26, 2008, at 10:41 AM, Dain Sundstrom wrote:
>
>> I shelved this work for a few weeks, but got back on it last  
>> night.  To start with, I merged the StatefulInstanceManager and  
>> SessionSynchronizationCoordinator into the Stateful container.  In  
>> my opinion, this vastly simplifies the code and because all bean  
>> call backs and the general EJB lifecycle is much more visible (and  
>> readable).  Then I extracted a simple cache interface from the  
>> container:
>>
>> public interface Cache<K, V> {
>>   /**
>>    * Add a new entry to the cache.  The entry is marked checked-out  
>> and can
>>    * not be accessed again until checked-in.
>>    *
>>    * @IllegalStateException if an value is already associated with  
>> the key
>>    */
>>   void add(K key, V value);
>>
>>   /**
>>    * Marks the entry checked-out, so this entry can not be accessed  
>> until
>>    * checked-in.
>>    *
>>    * @throws IllegalStateException if the entry is already checked  
>> out.
>>    * @throws Exception if an entry is loaded and the afterLoad  
>> method threw an
>>    * exception
>>    */
>>   V checkOut(K key) throws Exception;
>>
>>   /**
>>    * Marks the entry available, so it can be accessed again.
>>    *
>>    * @throws IllegalStateException if the entry is not checked out.
>>    */
>>   void checkIn(K key);
>>
>>   /**
>>    * Removes the entry from the cache.
>>    */
>>   V remove(K key);
>>
>>   /**
>>    * Removes all of th entries that match the specified filter.
>>    */
>>   void removeAll(CacheFilter<V> filter);
>>
>>   /**
>>    * Callback listener for cache events.
>>    */
>>   public interface CacheListener<V> {
>>       /**
>>        * Called after an entry is loaded from a store.
>>        *
>>        * @throws Exception if there is a problem with the instance
>>        */
>>       void afterLoad(V value) throws Exception;
>>
>>       /**
>>        * Called before an entry is written to a store.
>>        *
>>        * @throws Exception if there is a problem with the instance
>>        */
>>       void beforeStore(V value) throws Exception;
>>
>>       /**
>>        * Called when an instance has been removed from the cache  
>> due to a
>>        * time-out.
>>        */
>>       void timedOut(V value);
>>   }
>>
>>   /**
>>    * CacheFileter is used to select values to remove during a  
>> removeAll
>>    * invocation.
>>    */
>>   public interface CacheFilter<V> {
>>       /**
>>        * True if the filter matches the value.
>>        */
>>       boolean matches(V v);
>>   }
>> }
>>
>> Generally, the container checks out an instance when a method is  
>> invoked, and checks it back in when the transaction completes.   
>> This behavior is due to the Stateful specification that an instance  
>> can not be passivated (e.g., written to disk, distributed across a  
>> cluster, etc.)  while in a transaction.  The container is notified  
>> when the cache loads or stores an instance so it can make the  
>> proper ejbActivate/ejbPassivate calls.
>>
>> I believe this interface is simple enough that we can adapt it to a  
>> great verity of cache implementations, but we won't know until we  
>> write some :)
>>
>> -dain
>>
>> On Jul 2, 2008, at 3:39 PM, Dain Sundstrom wrote:
>>
>>> Hi all,
>>>
>>> I've been thinking about SFSB caching, and have a few ideas about  
>>> cache implements I'd like to experiment with like using Java5  
>>> concurrent collections, ehCache, ServletSession and maybe  
>>> Terracotta.  Before I start experimenting, I'm going to try to  
>>> simplify the interface between the StatefulContainer and  
>>> StatefulInstanceManager (the cache).  Right now, if you want to  
>>> plugin in a new cache, you have to either write a lot of EJB  
>>> specific logic or subclass from our the existing  
>>> StatefulInstanceManager, which sucks.  My goal is to extract a  
>>> simple interface with just a few Map like operations that one  
>>> would need to implement to introduce a new cache.
>>>
>>> Anyway, just a heads up.  I'll post again when I have a initial  
>>> draft of the interface available.  I'll also try to keep the  
>>> existing extensions of StatefulInstanceManager in Geronimo working.
>>>
>>> -dain teracotta
>>
>


Re: Stateful Session Bean Caching

Posted by Dain Sundstrom <da...@iq80.com>.
It is committed. Check it out :)

-dain

On Aug 26, 2008, at 10:41 AM, Dain Sundstrom wrote:

> I shelved this work for a few weeks, but got back on it last night.   
> To start with, I merged the StatefulInstanceManager and  
> SessionSynchronizationCoordinator into the Stateful container.  In  
> my opinion, this vastly simplifies the code and because all bean  
> call backs and the general EJB lifecycle is much more visible (and  
> readable).  Then I extracted a simple cache interface from the  
> container:
>
> public interface Cache<K, V> {
>    /**
>     * Add a new entry to the cache.  The entry is marked checked-out  
> and can
>     * not be accessed again until checked-in.
>     *
>     * @IllegalStateException if an value is already associated with  
> the key
>     */
>    void add(K key, V value);
>
>    /**
>     * Marks the entry checked-out, so this entry can not be accessed  
> until
>     * checked-in.
>     *
>     * @throws IllegalStateException if the entry is already checked  
> out.
>     * @throws Exception if an entry is loaded and the afterLoad  
> method threw an
>     * exception
>     */
>    V checkOut(K key) throws Exception;
>
>    /**
>     * Marks the entry available, so it can be accessed again.
>     *
>     * @throws IllegalStateException if the entry is not checked out.
>     */
>    void checkIn(K key);
>
>    /**
>     * Removes the entry from the cache.
>     */
>    V remove(K key);
>
>    /**
>     * Removes all of th entries that match the specified filter.
>     */
>    void removeAll(CacheFilter<V> filter);
>
>    /**
>     * Callback listener for cache events.
>     */
>    public interface CacheListener<V> {
>        /**
>         * Called after an entry is loaded from a store.
>         *
>         * @throws Exception if there is a problem with the instance
>         */
>        void afterLoad(V value) throws Exception;
>
>        /**
>         * Called before an entry is written to a store.
>         *
>         * @throws Exception if there is a problem with the instance
>         */
>        void beforeStore(V value) throws Exception;
>
>        /**
>         * Called when an instance has been removed from the cache  
> due to a
>         * time-out.
>         */
>        void timedOut(V value);
>    }
>
>    /**
>     * CacheFileter is used to select values to remove during a  
> removeAll
>     * invocation.
>     */
>    public interface CacheFilter<V> {
>        /**
>         * True if the filter matches the value.
>         */
>        boolean matches(V v);
>    }
> }
>
> Generally, the container checks out an instance when a method is  
> invoked, and checks it back in when the transaction completes.  This  
> behavior is due to the Stateful specification that an instance can  
> not be passivated (e.g., written to disk, distributed across a  
> cluster, etc.)  while in a transaction.  The container is notified  
> when the cache loads or stores an instance so it can make the proper  
> ejbActivate/ejbPassivate calls.
>
> I believe this interface is simple enough that we can adapt it to a  
> great verity of cache implementations, but we won't know until we  
> write some :)
>
> -dain
>
> On Jul 2, 2008, at 3:39 PM, Dain Sundstrom wrote:
>
>> Hi all,
>>
>> I've been thinking about SFSB caching, and have a few ideas about  
>> cache implements I'd like to experiment with like using Java5  
>> concurrent collections, ehCache, ServletSession and maybe  
>> Terracotta.  Before I start experimenting, I'm going to try to  
>> simplify the interface between the StatefulContainer and  
>> StatefulInstanceManager (the cache).  Right now, if you want to  
>> plugin in a new cache, you have to either write a lot of EJB  
>> specific logic or subclass from our the existing  
>> StatefulInstanceManager, which sucks.  My goal is to extract a  
>> simple interface with just a few Map like operations that one would  
>> need to implement to introduce a new cache.
>>
>> Anyway, just a heads up.  I'll post again when I have a initial  
>> draft of the interface available.  I'll also try to keep the  
>> existing extensions of StatefulInstanceManager in Geronimo working.
>>
>> -dain teracotta
>