cancel
Showing results for 
Search instead for 
Did you mean: 

How to write code with transactions

hbf
Champ on-the-rise
Champ on-the-rise
Dear list,

I need advice on how to use Alfresco transactions in my custom code. As far as I understand the Alfresco APIs, there are two ways to use transactions:

1. Create the transaction, begin() it, do the work, and eventually call commit() or rollback().
2. Do the work within a RetryingTransactionHelper's RetryingTransactionCallback.

The first approach can be difficult because, it seems, a transaction may fail due to concurrency issues, see this post. So it seems it's best to use approach 2.

However, the work I do in a transaction is spread over different classes/methods/places and I cannot easily write a single RetryingTransactionCallback that does it all. Therefore my question: is there maybe a third way to do work within a transaction that gets retried in case of concurrency issues?

Many thanks,
Kaspar
19 REPLIES 19

cheffilet
Champ in-the-making
Champ in-the-making
It depends on your usecase what you want to achieve with a retrying-operation.

To start a retrying-process you have to throw a exception that implements and/or derives from following interfaces/classes (Alfresco 3.2 CE):

  • class org.springframework.dao.ConcurrencyFailureException

  • class org.springframework.dao.DeadlockLoserDataAccessException

  • class org.hibernate.StaleObjectStateException

  • class org.springframework.jdbc.JdbcUpdateAffectedIncorrectNumberOfRowsException

  • class org.hibernate.exception.LockAcquisitionException

  • class org.hibernate.exception.ConstraintViolationException

  • class org.springframework.jdbc.UncategorizedSQLException

  • class java.sql.SQLException

  • class java.sql.BatchUpdateException

  • class org.springframework.dao.DataIntegrityViolationException

  • class org.hibernate.StaleStateException

  • class org.hibernate.ObjectNotFoundException

  • class org.hibernate.cache.CacheException

  • class net.sf.ehcache.distribution.RemoteCacheException

  • class org.hibernate.exception.SQLGrammarException
You can review the list of possible classes in the static member field org.alfresco.repo.transaction.RetryingTransactionHelper.RETRY_EXCEPTIONS


Boolean result = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Boolean>(){
    public Boolean execute() throws Throwable {
            
      …
      if(val == null)
         throw new java.sql.SQLException("Val must not be null");
  
      return true;
    }  
//we need to setup a new transaction for this
}, false, true);

Regards
Sebastian

dranakan
Champ on-the-rise
Champ on-the-rise
Thank you Cheffilet. Create this kind of errors do the retrying-process.

I have a problem to modify a nodeReference. For exemple, if I want to change a property (add 33 to the property FirmNb), this create error :

BAD CODE (not working)

         …
         final int firmNbF=33;
         final NodeRef actionedUponNodeRefF = actionedUponNodeRef;
         boolean success = transactionService
               .getRetryingTransactionHelper()
               .doInTransaction(
                     new RetryingTransactionHelper.RetryingTransactionCallback<Boolean>() {
                        public Boolean execute() throws Throwable {
                           
                           // Change property
                           nodeService.setProperty(
                                 actionedUponNodeRefF, QNAME_SC_FIRMNB, firmNbF);
                           return true;
                        }
                     }, false, true);

      } catch (Exception e) {
         logger.error(e);
      }

There is no error in log, with after doing this, the file is removed and a new file is created with this :
Le contenu de l'élément est manquant : 
élément : workspace://SpacesStore/0d213852-7fc6-4392-a733-ab5216a5746b
lecteur : null
Veuillez contacter votre administrateur système.
How do I access to the actionedUponNodeRef (nodeRef) correctly ?

Thanks 🙂

wesse
Champ in-the-making
Champ in-the-making
How can I execute code in a transaction that is read only that needs to be able to write data ?

My specific problem is that I wnat to update a property on the event onReadContent

/Micke

cheffilet
Champ in-the-making
Champ in-the-making
@dranakan please post the whole strack-trace - in english Smiley Happy

@Weese

Well you could open a new transaction within the current transaction - this should working. But after all, i´l prefer to dont to this approach as there exist numerous reasons why the transactions is marked as read-only. The worst thing we can do is, to "compell" alfresco for doing things it is not desinged to. So there are other chances on the table to solve your problem?

dranakan
Champ on-the-rise
Champ on-the-rise
Thanks for your help Cheffilet

logger.error(e); :
org.alfresco.service.cmr.repository.InvalidNodeRefException: Node does not exist: workspace://SpacesStore/3ce67710-4e6c-4f36-8401-87b0496812fa

This arrives only when the rule is setted with : Not running in background ("Run rule in Background" Disable). If this option is enable… all is working fine 🙂

I don't know why (certainly new updates) but I have no more the problem that I said : "There is no error in log, with after doing this, the file is removed and a new file is created with this :" in my last post.

Some ideas ?

Thanks

dranakan
Champ on-the-rise
Champ on-the-rise
I isolated the problem… this is with nodeService (same with FileFolderService, …) in the transaction :


logger.debug("A : " + nodeService.getProperty(actionedUponNodeRef,ContentModel.PROP_NAME)); 
final NodeRef actionedUponNodeRefF = actionedUponNodeRef;
final NodeManager nodeManagerF = nodeManager;
final Action actionF = action;
logger.debug("B : "+ nodeService.getProperty(actionedUponNodeRefF,ContentModel.PROP_NAME));

try {
   success = transactionService.getRetryingTransactionHelper().doInTransaction(
      new RetryingTransactionHelper.RetryingTransactionCallback<Boolean>() {
         public Boolean execute() throws Throwable {
            try{
               logger.debug("C : "+ nodeService.getProperty(actionedUponNodeRefF,ContentModel.PROP_NAME));
            }catch (Exception e){
               logger.error(e);
               e.printStackTrace();
            }

         }, false, true);

Rule setted in background, output is :

A : nameFile
B : nameFile
C : nameFile

Rule NOT setted in background, output is :

A : nameFile
B : nameFile
org.alfresco.service.cmr.repository.InvalidNodeRefException: Node does not exist: workspace://SpacesStore/35cf425e-e8db-4664-904a-8a38bc2a44a4
org.alfresco.service.cmr.repository.InvalidNodeRefException: Node does not exist: workspace://SpacesStore/35cf425e-e8db-4664-904a-8a38bc2a44a4
        at org.alfresco.repo.node.db.DbNodeServiceImpl.getNodePairNotNull(DbNodeServiceImpl.java:156)
        at org.alfresco.repo.node.db.DbNodeServiceImpl.hasAspect(DbNodeServiceImpl.java:712)
        at sun.reflect.GeneratedMethodAccessor273.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:296)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:177)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144)
        at org.alfresco.repo.transaction.SingleEntryTransactionResourceInterceptor.invokeInternal(SingleEntryTransactionResourceInterceptor.java:163)
        at org.alfresco.repo.transaction.SingleEntryTransactionResourceInterceptor.invoke(SingleEntryTransactionResourceInterceptor.java:138)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
        at $Proxy7.hasAspect(Unknown Source)
        at sun.reflect.GeneratedMethodAccessor273.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:296)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:177)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144)
        at org.alfresco.repo.tenant.MultiTNodeServiceInterceptor.invoke(MultiTNodeServiceInterceptor.java:110)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
        at $Proxy7.hasAspect(Unknown Source)
        at sun.reflect.GeneratedMethodAccessor273.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.alfresco.repo.service.StoreRedirectorProxyFactory$RedirectorInvocationHandler.invoke(StoreRedirectorProxyFactory.java:221)
        at $Proxy8.hasAspect(Unknown Source)
        at org.alfresco.repo.node.MLPropertyInterceptor.getPivotNodeRef(MLPropertyInterceptor.java:320)
        at org.alfresco.repo.node.MLPropertyInterceptor.invoke(MLPropertyInterceptor.java:164)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
        at org.alfresco.repo.node.NodeRefPropertyMethodInterceptor.invoke(NodeRefPropertyMethodInterceptor.java:203)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
        at org.alfresco.repo.node.NodeRefPropertyMethodInterceptor.invoke(NodeRefPropertyMethodInterceptor.java:203)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
        at $Proxy7.getProperty(Unknown Source)
        at ch.custom.manageoffice.actions.OrganizeFileInDirectory$1.execute(OrganizeFileInDirectory.java:170)
        at ch.custom.manageoffice.actions.OrganizeFileInDirectory$1.execute(OrganizeFileInDirectory.java:1)
        at org.alfresco.repo.transaction.RetryingTransactionHelper.doInTransaction(RetryingTransactionHelper.java:320)
        at ch.custom.manageoffice.actions.OrganizeFileInDirectory.executeImpl(OrganizeFileInDirectory.java:165)
        at org.alfresco.repo.action.executer.ActionExecuterAbstractBase.execute(ActionExecuterAbstractBase.java:127)
        at org.alfresco.repo.action.ActionServiceImpl.directActionExecution(ActionServiceImpl.java:592)
        at org.alfresco.repo.action.executer.CompositeActionExecuter.executeImpl(CompositeActionExecuter.java:72)
        at org.alfresco.repo.action.executer.ActionExecuterAbstractBase.execute(ActionExecuterAbstractBase.java:127)
        at org.alfresco.repo.action.ActionServiceImpl.directActionExecution(ActionServiceImpl.java:592)
        at org.alfresco.repo.action.ActionServiceImpl.executeActionImpl(ActionServiceImpl.java:529)
        at org.alfresco.repo.action.ActionServiceImpl.executeAction(ActionServiceImpl.java:391)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:296)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:177)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144)
        at org.alfresco.repo.security.permissions.impl.AlwaysProceedMethodInterceptor.invoke(AlwaysProceedMethodInterceptor.java:40)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
        at org.alfresco.repo.security.permissions.impl.ExceptionTranslatorMethodInterceptor.invoke(ExceptionTranslatorMethodInterceptor.java:49)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
        at org.alfresco.repo.audit.AuditComponentImpl.audit(AuditComponentImpl.java:275)
        at org.alfresco.repo.audit.AuditMethodInterceptor.invoke(AuditMethodInterceptor.java:69)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:166)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
        at $Proxy22.executeAction(Unknown Source)
        at org.alfresco.repo.rule.RuleServiceImpl.executeRule(RuleServiceImpl.java:928)
        at org.alfresco.repo.rule.RuleServiceImpl.executePendingRule(RuleServiceImpl.java:896)
        at org.alfresco.repo.rule.RuleServiceImpl.executePendingRulesImpl(RuleServiceImpl.java:867)
        at org.alfresco.repo.rule.RuleServiceImpl.executePendingRules(RuleServiceImpl.java:840)
        at org.alfresco.repo.rule.RuleTransactionListener.beforeCommit(RuleTransactionListener.java:63)
        at org.alfresco.repo.transaction.AlfrescoTransactionSupport$TransactionSynchronizationImpl.doBeforeCommit(AlfrescoTransactionSupport.java:710)
        at org.alfresco.repo.transaction.AlfrescoTransactionSupport$TransactionSynchronizationImpl.doBeforeCommit(AlfrescoTransactionSupport.java:690)
        at org.alfresco.repo.transaction.AlfrescoTransactionSupport$TransactionSynchronizationImpl.beforeCommit(AlfrescoTransactionSupport.java:650)
        at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:48)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:835)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:645)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:632)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:314)
        at org.alfresco.util.transaction.SpringAwareUserTransaction.commit(SpringAwareUserTransaction.java:466)
        at org.alfresco.repo.transaction.RetryingTransactionHelper.doInTransaction(RetryingTransactionHelper.java:334)
        at org.alfresco.repo.transaction.RetryingTransactionHelper.doInTransaction(RetryingTransactionHelper.java:227)
        at org.alfresco.web.bean.dialog.BaseDialogBean.finish(BaseDialogBean.java:127)
        at org.alfresco.web.bean.dialog.DialogManager.finish(DialogManager.java:534)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.myfaces.el.MethodBindingImpl.invoke(MethodBindingImpl.java:132)
        at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:61)
        at javax.faces.component.UICommand.broadcast(UICommand.java:109)
        at javax.faces.component.UIViewRoot._broadcastForPhase(UIViewRoot.java:97)
        at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:171)
        at org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:32)
        at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:95)
        at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:70)
        at javax.faces.webapp.FacesServlet.service(FacesServlet.java:139)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.alfresco.web.app.servlet.AuthenticationFilter.doFilter(AuthenticationFilter.java:81)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
        at java.lang.Thread.run(Thread.java:619)

What is the problem ?

Thanks

dranakan
Champ on-the-rise
Champ on-the-rise
Hello,

Have someone a sample of code to write transactions (in an action) ?
(working with rules in background or not, able to restart if failed)

(http://wiki.alfresco.com/wiki/Java_Foundation_API#Handling_UserTransaction_Directly)
Thanks

vikashkaushik
Champ in-the-making
Champ in-the-making
As mentioned in the first post of this discussion ,
1. Create the transaction, begin() it, do the work, and eventually call commit() or rollback().

I have tried this way to check if rollback() works or not.

My code is typically like this :

UserTransaction userTransaction = jtaTransactionManager.getUserTransaction();

try {

userTransaction.begin();

Alfresco operation1 - using CMIS API ( To create a document )

Alfresco operation2 - using CMIS API ( To create a document)

userTransaction.commit();
}
catch (Exception e)
{
userTransaction.rollback();
}

My Alfresco operation2 throws an exception, then the document inserted by Alfresco operation1 is still there in Alfresco , even though the User Transaction is rolled back.

Can anyone help me how to resolve this.

I am using Spring JTA Transaction manager(XA)

mrogers
Star Contributor
Star Contributor
Cmis is not a remote transactional Api.   It may be in future,  but not now.    I'm fairly sure it will never work as you laid out,  the proposal I've heard about suggests a set of operations could be batched together as a single transaction.

If you want to do this then you need to write an alfresco WebScript and call that instead.


I've heard that it is possible to rewire alfresco's trasaction handling so transactions will distribute.   Mostly for J2EE shops that want to wrap alfresco functionality in EJB.   However I've not done it myself and suspect there may be limitations.

Thank you for the reply.

The scenario that we need currently is :

1. Creation/updation of document in Alfresco from a separate web application.
2. Insertion of the details of document in DB

So when DB insertion fails, we need to rollback the document creation/updation transaction.

Can you please let me know the approach for this. ( I doubt web script would be able to support to tie transactions from one application to Alfresco). I am very much new to this Alfresco.
It will be helpful for me if you provide some good pointers.