Announcement Announcement Module
Collapse
No announcement yet.
ACL: Cleanup aclCache after Transaction Rollback/Exception Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • ACL: Cleanup aclCache after Transaction Rollback/Exception

    Hi all (:

    I encountered a problem using Spring 3.0.7 / Spring Security 3.1.0.RC3 and hope you guys can help me out or at least point me to the right direction.

    The scenario is as follows:

    When a expection is thrown inside my transactional, the transaction (using JTA - Atomikos Transactionmanager) gets rolled back correctly on the database, but the ACL Mutations made are still in the aclCache (I'm using EhCache).

    I found a workaround, but imo it's pretty ugly :

    I looked into the source. The desired behaviour is obviously inside of JdbcMutableAclService' private method 'clearCacheIncludingChildren(ObjectIdentity objectIdentity)'

    Code:
      
    private void clearCacheIncludingChildren(ObjectIdentity objectIdentity) 
    {
            Assert.notNull(objectIdentity, "ObjectIdentity required");
            List<ObjectIdentity> children = findChildren(objectIdentity);
            if (children != null) {
                for (ObjectIdentity child : children) {
                    clearCacheIncludingChildren(child);
                }
            }
            aclCache.evictFromCache(objectIdentity);
       }
    This function is usually called aftern ACL Update.
    Since neither this method nor the aclCache is accessible from another class, I extended JdbcMutableAclService and added a reference to aclCache, a public cleanUp Method (see below) and copy of the above method.
    Code:
    public MutableAcl cleanupAcl( ObjectIdentityImpl oi)
    {
    	clearCacheIncludingChildren( oi);
    	return (MutableAcl) super.readAclById(oi);
    }
    When I throw an Exception the the corresponding ObjectIdentity is passed. The catch block looks like this
    Code:
     
       try {
          //doSomething is a Transactional Service Method where the object is updated and the acl update/insert is  made
          doSomething();
       catch (CustomException e) {	
    		MutableAcl acl = customJdbcMutableAcleService.cleanupAcl( e.getObjectIdentity());
       }

    I assume (or lets say I hope ) there is another easy way to notify the EHCache after a transaction is rolled back.

    thanks in advance... appreciate it.
    Last edited by ko0kie; Jan 19th, 2012, 07:04 PM.

  • #2
    I'm not sure if you have taken a look, but ehcache has some documentation on transaction management that may help.

    PS: You might consider updating to Spring Security 3.1.0.RELEASE

    Comment


    • #3
      thanks for your advice. I upgraded to Spring Security / Spring 3.1.0.RELEASE.

      I also had a good look at the ehcache documentation, updated my configuration but still did'nt get it to work.

      my configuration:

      applicationContext-acl.xml:
      Code:
      <bean id="aclCache" class="org.springframework.security.acls.domain.EhCacheBasedAclCache">
              <constructor-arg>
                  <bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
                      <property name="cacheManager">
                          <bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
                          	<property name="configLocation" value="/WEB-INF/ehcache.xml"/>
                          </bean>
                      </property>
                      <property name="cacheName" value="aclCache"/>
                  </bean>
              </constructor-arg>
          </bean>
      ehcache.xml
      Code:
      <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" name="myCache">
      	<diskStore path="java.io.tmpdir"/>
      	<defaultCache
             maxElementsInMemory="10000"
             eternal="false"
             timeToIdleSeconds="120"
             timeToLiveSeconds="240"
             overflowToDisk="true"
             maxEntriesLocalDisk="1000000"
             diskPersistent="false"
             diskExpiryThreadIntervalSeconds="120"
             memoryStoreEvictionPolicy="LRU"
             transactionalMode="xa"/>
      </ehcache>
      I also tried transactionalMode="xa_strict"..same result.

      Comment


      • #4
        Hi ko0kie!

        I've got the same problem and I also tried the transactionalMode in the ehcache configuration ... but nothing orking.
        Did you finally find a solution to clean ehCache after rollback?

        Thx a lot

        Comment


        • #5
          I'm having the same problem here.
          ehcache transactionalMode doesn't seem to do what we expect.

          ko0kie, have you stick with your work around or have you manage to get this working?

          Comment


          • #6
            There are two aspects:

            In order to activate transactionalMode for the aclCache you have to explictly define it in your ehcache.xml. It isn't enough to set it for the defaultCache.
            So your ehcache.xml should look like this:

            Code:
            <ehcache  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
            	<diskStore path="java.io.tmpdir"/>
            	<defaultCache
                   maxElementsInMemory="10000"
                   eternal="false"
                   timeToIdleSeconds="120"
                   timeToLiveSeconds="120"
                   overflowToDisk="true"
                   maxEntriesLocalDisk="1000000"
                   diskPersistent="false"
                   diskExpiryThreadIntervalSeconds="120"
                   memoryStoreEvictionPolicy="LRU"/>
                   
               <cache name="aclCache"
                   maxElementsInMemory="10000"
                   eternal="false"
                   timeToIdleSeconds="120"
                   timeToLiveSeconds="120"
                   overflowToDisk="true"
                   maxEntriesLocalDisk="2000000"
                   diskPersistent="false"
                   diskExpiryThreadIntervalSeconds="120"
                   memoryStoreEvictionPolicy="LRU"
                  transactionalMode="xa"
                   />
            </ehcache>
            As soon as you activate transactionalMode for your aclCache Spring will most probably complain that a TransactionManager wasn't found. According to the documentation of ehcache you have to define a custom TransactionManagerLookup if your transactionManager is not part of the ones which are supported out of the box.
            However the TransactionManagerLookup requires to return a JtaTransactionManager. So in case you are using a JpaTransactionManager it will again complain.

            I don't know if there is an easier workaround.

            Comment


            • #7
              you could pass the aclCache to the class that takes care of adding the entries to the ACL database

              class AclUtil {
              private MutableAclService mutableAclService;
              private AclCache aclCache;

              public void evict(ObjectIdentity oid){
              aclCache.evictFromCache(oid);
              }

              public void addPermissions( ObjectIdentity oid, .. ){
              MutableAcl acl;
              try {
              acl = (MutableAcl) mutableAclService.readAclById(oid);
              } catch (NotFoundException nfe) {
              acl = mutableAclService.createAcl(oid);
              }
              ....
              mutableAclService.updateAcl(acl);
              }
              }


              and what ever calls the addPermissions()...
              try {
              aclUtil.addPermissions( oid, ... );
              } catch ( TheException e ) {
              aclUtil.evict(oid);
              }

              Comment

              Working...
              X