Exception thrown when calling remove during after-completion
rworsnop Mar 13, 2007 4:49 PMJBoss Cache version: 1.4.1.SP2
I have been having some problems using Hibernate with JBoss Cache in optimistic locking mode. During the after-completion phase of the transaction, Hibernate will, in certain circumstances, call TreeCache.remove.
This causes problems because JBoss Cache sees that the transaction is committing. A CacheException is thrown, with a "Must be in a valid transaction" message.
The code below replicates what Hibernate does:
public static void main(String[] args) throws Exception { TreeCache tree = new TreeCache(); tree.setTransactionManagerLookup(new DummyTransactionManagerLookup()); tree.setCacheMode(TreeCache.LOCAL); tree.setNodeLockingScheme("optimistic"); tree.startService(); // kick start tree cache TransactionManager txManager = DummyTransactionManager.getInstance(); try { txManager.begin(); txManager.getTransaction().registerSynchronization(remover(tree)); tree.put(fqn("custard"), "item", 45); txManager.commit(); } catch(Throwable ex) { ex.printStackTrace(); try { txManager.rollback(); } catch(Throwable t) {} } finally{ tree.stopService(); } } private static Synchronization remover(final TreeCache tree) { return new Synchronization(){ public void afterCompletion(int status) { try { tree.remove(fqn("custard"), option(false)); } catch (CacheException e) { System.err.println("Bad things happened when I tried to remove custard"); e.printStackTrace(); } } public void beforeCompletion() { } }; } private static Fqn fqn(String s){ return Fqn.fromString(s); } private static Option option(boolean failSilently){ Option option = new Option(); option.setFailSilently( failSilently ); option.setDataVersion(new DataVersion(){ public boolean newerThan(DataVersion arg0) { return false; }} ); return option; }
It causes this exception:
Bad things happened when I tried to remove custard org.jboss.cache.CacheException: Must be in a valid transaction _remove; id:5(null, /custard, true) at org.jboss.cache.interceptors.OptimisticNodeInterceptor.invoke(OptimisticNodeInterceptor.java:66) at org.jboss.cache.interceptors.Interceptor.invoke(Interceptor.java:68) at org.jboss.cache.interceptors.OptimisticCreateIfNotExistsInterceptor.invoke(OptimisticCreateIfNotExistsInterceptor.java:69) at org.jboss.cache.interceptors.Interceptor.invoke(Interceptor.java:68) at org.jboss.cache.interceptors.OptimisticValidatorInterceptor.invoke(OptimisticValidatorInterceptor.java:84) at org.jboss.cache.interceptors.Interceptor.invoke(Interceptor.java:68) at org.jboss.cache.interceptors.OptimisticLockingInterceptor.invoke(OptimisticLockingInterceptor.java:126) at org.jboss.cache.interceptors.Interceptor.invoke(Interceptor.java:68) at org.jboss.cache.interceptors.TxInterceptor.handleNonTxMethod(TxInterceptor.java:365) at org.jboss.cache.interceptors.TxInterceptor.invoke(TxInterceptor.java:160) at org.jboss.cache.interceptors.Interceptor.invoke(Interceptor.java:68) at org.jboss.cache.interceptors.CacheMgmtInterceptor.invoke(CacheMgmtInterceptor.java:183) at org.jboss.cache.TreeCache.invokeMethod(TreeCache.java:5776) at org.jboss.cache.TreeCache.remove(TreeCache.java:3855) at org.jboss.cache.TreeCache.remove(TreeCache.java:3438) at com.medq.test.TestTreeCacheNotInTransaction$1.afterCompletion(TestTreeCacheNotInTransaction.java:47) at org.jboss.cache.transaction.DummyTransaction.notifyAfterCompletion(DummyTransaction.java:270) at org.jboss.cache.transaction.DummyTransaction.commit(DummyTransaction.java:64) at org.jboss.cache.transaction.DummyBaseTransactionManager.commit(DummyBaseTransactionManager.java:61) at com.medq.test.TestTreeCacheNotInTransaction.main(TestTreeCacheNotInTransaction.java:32)
Is this expected behaviour for JBoss Cache? If so I will raise the issue on the Hibernate forum.