List of usage examples for javax.transaction UserTransaction begin
void begin() throws NotSupportedException, SystemException;
From source file:org.alfresco.repo.search.impl.lucene.ADMLuceneTest.java
/** * @throws Exception// ww w . j a v a 2 s. c o m */ public void testDeltaIssue() throws Exception { luceneFTS.pause(); final NodeService pns = (NodeService) ctx.getBean("NodeService"); testTX.commit(); testTX = transactionService.getUserTransaction(); testTX.begin(); luceneFTS.pause(); buildBaseIndex(); runBaseTests(); testTX.commit(); Thread thread = new Thread(new Runnable() { public void run() { try { authenticationComponent.setSystemUserAsCurrentUser(); UserTransaction tx = transactionService.getUserTransaction(); tx = transactionService.getUserTransaction(); tx.begin(); SearchParameters sp = new SearchParameters(); sp.addStore(rootNodeRef.getStoreRef()); sp.setLanguage(SearchService.LANGUAGE_LUCENE); sp.setQuery("PATH:\"//.\""); sp.excludeDataInTheCurrentTransaction(false); ResultSet results = serviceRegistry.getSearchService().query(sp); for (ResultSetRow row : results) { System.out.println("row = " + row.getQName()); } assertEquals(15, results.length()); results.close(); sp = new SearchParameters(); sp.addStore(rootNodeRef.getStoreRef()); sp.setLanguage(SearchService.LANGUAGE_LUCENE); sp.setQuery("PATH:\"//.\""); sp.excludeDataInTheCurrentTransaction(false); results = serviceRegistry.getSearchService().query(sp); assertEquals(15, results.length()); results.close(); Map<QName, Serializable> props = new HashMap<QName, Serializable>(); props.put(ContentModel.PROP_TITLE, "woof"); pns.addAspect(n1, ContentModel.ASPECT_TITLED, props); sp = new SearchParameters(); sp.addStore(rootNodeRef.getStoreRef()); sp.setLanguage(SearchService.LANGUAGE_LUCENE); sp.setQuery("PATH:\"//.\""); sp.excludeDataInTheCurrentTransaction(false); results = serviceRegistry.getSearchService().query(sp); assertEquals(15, results.length()); results.close(); tx.rollback(); } catch (Throwable e) { throw new RuntimeException(e); } } }); thread.start(); thread.join(); testTX = transactionService.getUserTransaction(); testTX.begin(); SearchParameters sp = new SearchParameters(); sp.addStore(rootNodeRef.getStoreRef()); sp.setLanguage(SearchService.LANGUAGE_LUCENE); sp.setQuery("PATH:\"//.\""); sp.excludeDataInTheCurrentTransaction(false); ResultSet results = serviceRegistry.getSearchService().query(sp); assertEquals(16, results.length()); results.close(); sp = new SearchParameters(); sp.addStore(rootNodeRef.getStoreRef()); sp.setLanguage(SearchService.LANGUAGE_LUCENE); sp.setQuery("PATH:\"//.\""); sp.excludeDataInTheCurrentTransaction(false); results = serviceRegistry.getSearchService().query(sp); assertEquals(16, results.length()); results.close(); runBaseTests(); sp = new SearchParameters(); sp.addStore(rootNodeRef.getStoreRef()); sp.setLanguage(SearchService.LANGUAGE_LUCENE); sp.setQuery("PATH:\"//.\""); sp.excludeDataInTheCurrentTransaction(false); results = serviceRegistry.getSearchService().query(sp); assertEquals(16, results.length()); results.close(); Map<QName, Serializable> props = new HashMap<QName, Serializable>(); props.put(ContentModel.PROP_TITLE, "woof"); pns.addAspect(n1, ContentModel.ASPECT_TITLED, props); sp = new SearchParameters(); sp.addStore(rootNodeRef.getStoreRef()); sp.setLanguage(SearchService.LANGUAGE_LUCENE); sp.setQuery("PATH:\"//.\""); sp.excludeDataInTheCurrentTransaction(false); results = serviceRegistry.getSearchService().query(sp); assertEquals(16, results.length()); results.close(); pns.setProperty(n1, ContentModel.PROP_TITLE, "cube"); sp = new SearchParameters(); sp.addStore(rootNodeRef.getStoreRef()); sp.setLanguage(SearchService.LANGUAGE_LUCENE); sp.setQuery("PATH:\"//.\""); sp.excludeDataInTheCurrentTransaction(false); results = serviceRegistry.getSearchService().query(sp); assertEquals(16, results.length()); results.close(); testTX.rollback(); }
From source file:org.alfresco.repo.search.impl.lucene.ADMLuceneTest.java
/** * @throws Exception//from www . jav a 2s . co m */ public void testIssueAR47() throws Exception { // This bug arose from repeated deletes and adds creating empty index // segments. // Two segements each containing one deletyed entry were merged together // producing a single empty entry. // This seemed to be bad for lucene - I am not sure why // So we add something, add and delete someting repeatedly and then // check we can still do the search. // Running in autocommit against the index testTX.commit(); UserTransaction tx = transactionService.getUserTransaction(); tx.begin(); ChildAssociationRef testFind = nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, QName.createQName("{namespace}testFind"), testSuperType); tx.commit(); ADMLuceneSearcherImpl searcher = buildSearcher(); ResultSet results = searcher.query(rootNodeRef.getStoreRef(), "lucene", "QNAME:\"namespace:testFind\""); assertEquals(1, results.length()); results.close(); for (int i = 0; i < 100; i++) { UserTransaction tx1 = transactionService.getUserTransaction(); tx1.begin(); ChildAssociationRef test = nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, QName.createQName("{namespace}test"), testSuperType); tx1.commit(); UserTransaction tx2 = transactionService.getUserTransaction(); tx2.begin(); nodeService.deleteNode(test.getChildRef()); tx2.commit(); } UserTransaction tx3 = transactionService.getUserTransaction(); tx3.begin(); results = searcher.query(rootNodeRef.getStoreRef(), "lucene", "QNAME:\"namespace:testFind\""); assertEquals(1, results.length()); results.close(); tx3.commit(); }
From source file:org.alfresco.repo.tenant.MultiTAdminServiceImpl.java
@Override public void startTenants() { AuthenticationUtil.setMtEnabled(true); // initialise the tenant admin service and status of tenants (using attribute service) // note: this requires that the repository schema has already been initialised // register dictionary - to allow enable/disable tenant callbacks register(dictionaryComponent);/* ww w. ja v a2 s.c o m*/ if (isTenantDeployer(tenantFileContentStore)) { // register file store - to allow enable/disable tenant callbacks // note: tenantFileContentStore must be registed before dictionaryRepositoryBootstrap register(tenantDeployer(tenantFileContentStore), 0); } UserTransaction userTransaction = transactionService.getUserTransaction(); try { authenticationContext.setSystemUserAsCurrentUser(); userTransaction.begin(); // bootstrap Tenant Service internal cache List<Tenant> tenants = getAllTenants(); int enabledCount = 0; int disabledCount = 0; for (Tenant tenant : tenants) { if ((!(isTenantRoutingContentStore(tenantFileContentStore))) && (!tenantFileContentStore.getRootLocation().equals(tenant.getRootContentStoreDir()))) { // eg. ALF-14121 - MT will not work with replicating-content-services-context.sample if tenants are not co-mingled throw new AlfrescoRuntimeException( "MT: cannot start tenants - TenantRoutingContentStore is not configured AND not all tenants use co-mingled content store"); } String tenantDomain = tenant.getTenantDomain(); if (tenant.isEnabled()) { // notify tenant deployers registered so far ... notifyAfterEnableTenant(tenantDomain); enabledCount++; } else { disabledCount++; if (logger.isDebugEnabled()) { logger.debug("Tenant disabled: " + tenantDomain); } } } userTransaction.commit(); if ((enabledCount + disabledCount) == 0) { AuthenticationUtil.setMtEnabled(false); // explicitly disable if there are no tenants } if (logger.isInfoEnabled() && ((enabledCount + disabledCount) > 0)) { logger.info(String.format("Alfresco Multi-Tenant startup - %d enabled tenants, %d disabled tenants", enabledCount, disabledCount)); } else if (logger.isDebugEnabled()) { logger.debug( String.format("Alfresco Multi-Tenant startup - %d enabled tenants, %d disabled tenants", enabledCount, disabledCount)); } } catch (Throwable e) { // rollback the transaction try { if (userTransaction != null) { userTransaction.rollback(); } } catch (Exception ex) { } throw new AlfrescoRuntimeException("Failed to bootstrap tenants", e); } finally { authenticationContext.clearCurrentSecurityContext(); } }
From source file:org.alfresco.repo.tenant.MultiTAdminServiceImpl.java
@Override public void deployTenants(final TenantDeployer deployer, Log logger) { if (deployer == null) { throw new AlfrescoRuntimeException("Deployer must be provided"); }//from ww w .ja v a2 s .co m if (logger == null) { throw new AlfrescoRuntimeException("Logger must be provided"); } if (tenantService.isEnabled()) { UserTransaction userTransaction = transactionService.getUserTransaction(); authenticationContext.setSystemUserAsCurrentUser(); List<Tenant> tenants = null; try { userTransaction.begin(); tenants = getAllTenants(); userTransaction.commit(); } catch (Throwable e) { // rollback the transaction try { if (userTransaction != null) { userTransaction.rollback(); } } catch (Exception ex) { } throw new AlfrescoRuntimeException("Failed to get tenants", e); } finally { authenticationContext.clearCurrentSecurityContext(); } for (Tenant tenant : tenants) { if (tenant.isEnabled()) { try { // deploy within context of tenant domain TenantUtil.runAsSystemTenant(new TenantRunAsWork<Object>() { public Object doWork() { // init the service within tenant context deployer.init(); return null; } }, tenant.getTenantDomain()); } catch (Throwable e) { logger.error("Deployment failed" + e); StringWriter stringWriter = new StringWriter(); e.printStackTrace(new PrintWriter(stringWriter)); logger.error(stringWriter.toString()); // tenant deploy failure should not necessarily affect other tenants } } } } }
From source file:org.alfresco.repo.tenant.MultiTAdminServiceImpl.java
@Override public void undeployTenants(final TenantDeployer deployer, Log logger) { if (deployer == null) { throw new AlfrescoRuntimeException("Deployer must be provided"); }/*w w w . j ava2 s . c o m*/ if (logger == null) { throw new AlfrescoRuntimeException("Logger must be provided"); } if (tenantService.isEnabled()) { UserTransaction userTransaction = transactionService.getUserTransaction(); authenticationContext.setSystemUserAsCurrentUser(); List<Tenant> tenants = null; try { userTransaction.begin(); tenants = getAllTenants(); userTransaction.commit(); } catch (Throwable e) { // rollback the transaction try { if (userTransaction != null) { userTransaction.rollback(); } } catch (Exception ex) { } try { authenticationContext.clearCurrentSecurityContext(); } catch (Exception ex) { } throw new AlfrescoRuntimeException("Failed to get tenants", e); } try { AuthenticationUtil.pushAuthentication(); for (Tenant tenant : tenants) { if (tenant.isEnabled()) { try { // undeploy within context of tenant domain TenantUtil.runAsSystemTenant(new TenantRunAsWork<Object>() { public Object doWork() { // destroy the service within tenant context deployer.destroy(); return null; } }, tenant.getTenantDomain()); } catch (Throwable e) { logger.error("Undeployment failed" + e); StringWriter stringWriter = new StringWriter(); e.printStackTrace(new PrintWriter(stringWriter)); logger.error(stringWriter.toString()); // tenant undeploy failure should not necessarily affect other tenants } } } } finally { AuthenticationUtil.popAuthentication(); } } }
From source file:org.alfresco.repo.transaction.RetryingTransactionHelper.java
/** * Execute a callback in a transaction until it succeeds, fails * because of an error not the result of an optimistic locking failure, * or a deadlock loser failure, or until a maximum number of retries have * been attempted.//www . ja va 2 s .c o m * <p> * It is possible to force a new transaction to be created or to partake in * any existing transaction. * * @param cb The callback containing the unit of work. * @param readOnly Whether this is a read only transaction. * @param requiresNew <tt>true</tt> to force a new transaction or * <tt>false</tt> to partake in any existing transaction. * @return Returns the result of the unit of work. * @throws RuntimeException all checked exceptions are converted */ public <R> R doInTransaction(RetryingTransactionCallback<R> cb, boolean readOnly, boolean requiresNew) { // First validate the requiresNew setting if (!requiresNew) { TxnReadState readState = AlfrescoTransactionSupport.getTransactionReadState(); switch (readState) { case TXN_READ_ONLY: if (!readOnly) { // The current transaction is read-only, but a writable transaction is requested throw new AlfrescoRuntimeException( "Read-Write transaction started within read-only transaction"); } // We are in a read-only transaction and this is what we require so continue with it. break; case TXN_READ_WRITE: // We are in a read-write transaction. It cannot be downgraded so just continue with it. break; case TXN_NONE: // There is no current transaction so we need a new one. requiresNew = true; break; default: throw new RuntimeException("Unknown transaction state: " + readState); } } // If we need a new transaction, then we have to check that the read-write request can be served if (requiresNew) { if (this.readOnly && !readOnly) { throw new AccessDeniedException(MSG_READ_ONLY); } } // If we are time limiting, set ourselves a time limit and maintain the count of concurrent transactions long startTime = 0; Throwable stackTrace = null; if (requiresNew && maxExecutionMs > 0) { startTime = System.currentTimeMillis(); synchronized (this) { if (txnCount > 0) { // If this transaction would take us above our ceiling, reject it long oldestStart = txnsInProgress.firstKey(); long oldestDuration = startTime - oldestStart; if (oldestDuration > maxExecutionMs) { throw new TooBusyException("Too busy: " + txnCount + " transactions. Oldest " + oldestDuration + " milliseconds", txnsInProgress.get(oldestStart).get(0)); } } // Record the start time and stack trace of the starting thread List<Throwable> traces = txnsInProgress.get(startTime); if (traces == null) { traces = new LinkedList<Throwable>(); txnsInProgress.put(startTime, traces); } stackTrace = new Exception("Stack trace"); traces.add(stackTrace); ++txnCount; } } try { // Track the last exception caught, so that we // can throw it if we run out of retries. RuntimeException lastException = null; for (int count = 0; count == 0 || count < maxRetries; count++) { UserTransaction txn = null; try { if (requiresNew) { txn = txnService.getNonPropagatingUserTransaction(readOnly, forceWritable); txn.begin(); // Wrap it to protect it UserTransactionProtectionAdvise advise = new UserTransactionProtectionAdvise(); ProxyFactory proxyFactory = new ProxyFactory(txn); proxyFactory.addAdvice(advise); UserTransaction wrappedTxn = (UserTransaction) proxyFactory.getProxy(); // Store the UserTransaction for static retrieval. There is no need to unbind it // because the transaction management will do that for us. AlfrescoTransactionSupport.bindResource(KEY_ACTIVE_TRANSACTION, wrappedTxn); } // Do the work. R result = cb.execute(); // Only commit if we 'own' the transaction. if (txn != null) { if (txn.getStatus() == Status.STATUS_MARKED_ROLLBACK) { if (logger.isDebugEnabled()) { logger.debug("\n" + "Transaction marked for rollback: \n" + " Thread: " + Thread.currentThread().getName() + "\n" + " Txn: " + txn + "\n" + " Iteration: " + count); } // Something caused the transaction to be marked for rollback // There is no recovery or retrying with this txn.rollback(); } else { // The transaction hasn't been flagged for failure so the commit // sould still be good. txn.commit(); } } if (logger.isDebugEnabled()) { if (count != 0) { logger.debug("\n" + "Transaction succeeded: \n" + " Thread: " + Thread.currentThread().getName() + "\n" + " Txn: " + txn + "\n" + " Iteration: " + count); } } return result; } catch (Throwable e) { // Somebody else 'owns' the transaction, so just rethrow. if (txn == null) { RuntimeException ee = AlfrescoRuntimeException.makeRuntimeException(e, "Exception from transactional callback: " + cb); throw ee; } if (logger.isDebugEnabled()) { logger.debug("\n" + "Transaction commit failed: \n" + " Thread: " + Thread.currentThread().getName() + "\n" + " Txn: " + txn + "\n" + " Iteration: " + count + "\n" + " Exception follows:", e); } // Rollback if we can. if (txn != null) { try { int txnStatus = txn.getStatus(); // We can only rollback if a transaction was started (NOT NO_TRANSACTION) and // if that transaction has not been rolled back (NOT ROLLEDBACK). // If an exception occurs while the transaction is being created (e.g. no database connection) // then the status will be NO_TRANSACTION. if (txnStatus != Status.STATUS_NO_TRANSACTION && txnStatus != Status.STATUS_ROLLEDBACK) { txn.rollback(); } } catch (Throwable e1) { // A rollback failure should not preclude a retry, but logging of the rollback failure is required logger.error("Rollback failure. Normal retry behaviour will resume.", e1); } } if (e instanceof RollbackException) { lastException = (e.getCause() instanceof RuntimeException) ? (RuntimeException) e.getCause() : new AlfrescoRuntimeException("Exception in Transaction.", e.getCause()); } else { lastException = (e instanceof RuntimeException) ? (RuntimeException) e : new AlfrescoRuntimeException("Exception in Transaction.", e); } // Check if there is a cause for retrying Throwable retryCause = extractRetryCause(e); // ALF-17361 fix, also check for configured extra exceptions if (retryCause == null && extraExceptions != null && !extraExceptions.isEmpty()) { retryCause = ExceptionStackUtil.getCause(e, extraExceptions.toArray(new Class[] {})); } if (retryCause != null) { // Sleep a random amount of time before retrying. // The sleep interval increases with the number of retries. int sleepIntervalRandom = (count > 0 && retryWaitIncrementMs > 0) ? random.nextInt(count * retryWaitIncrementMs) : minRetryWaitMs; int sleepInterval = Math.min(maxRetryWaitMs, sleepIntervalRandom); sleepInterval = Math.max(sleepInterval, minRetryWaitMs); if (logger.isInfoEnabled() && !logger.isDebugEnabled()) { String msg = String.format( "Retrying %s: count %2d; wait: %1.1fs; msg: \"%s\"; exception: (%s)", Thread.currentThread().getName(), count, (double) sleepInterval / 1000D, retryCause.getMessage(), retryCause.getClass().getName()); logger.info(msg); } try { Thread.sleep(sleepInterval); } catch (InterruptedException ie) { // Do nothing. } // Try again continue; } else { // It was a 'bad' exception. throw lastException; } } } // We've worn out our welcome and retried the maximum number of times. // So, fail. throw lastException; } finally { if (requiresNew && maxExecutionMs > 0) { synchronized (this) { txnCount--; List<Throwable> traces = txnsInProgress.get(startTime); if (traces != null) { if (traces.size() == 1) { txnsInProgress.remove(startTime); } else { traces.remove(stackTrace); } } } } } }
From source file:org.alfresco.repo.transaction.RetryingTransactionHelperTest.java
public void testStartNewTransaction() throws Exception { // MNT-10096//w w w .j av a2 s . co m class CustomListenerAdapter extends TransactionListenerAdapter { private String newTxnId; @Override public void afterRollback() { newTxnId = txnHelper.doInTransaction(new RetryingTransactionCallback<String>() { @Override public String execute() throws Throwable { return AlfrescoTransactionSupport.getTransactionId(); } }, true, false); } } UserTransaction txn = transactionService.getUserTransaction(); txn.begin(); String txnId = AlfrescoTransactionSupport.getTransactionId(); CustomListenerAdapter listener = new CustomListenerAdapter(); AlfrescoTransactionSupport.bindListener(listener); txn.rollback(); assertFalse("New transaction has not started", txnId.equals(listener.newTxnId)); }
From source file:org.alfresco.repo.transaction.TransactionUtil.java
/** * Execute the transaction work in a user transaction of a specified type * /*ww w. j a v a 2 s. c om*/ * @param transactionService the transaction service * @param transactionWork the transaction work * @param nonPropagatingUserTransaction indicates whether the transaction * should be non propigating or not * @param readOnly true if the transaction should be read-only * * @throws java.lang.RuntimeException if the transaction was rolled back */ private static <R> R executeInTransaction(TransactionService transactionService, TransactionWork<R> transactionWork, boolean nonPropagatingUserTransaction, boolean readOnly) { ParameterCheck.mandatory("transactionWork", transactionWork); R result = null; // Get the right type of user transaction UserTransaction txn = null; if (nonPropagatingUserTransaction == true) { txn = transactionService.getNonPropagatingUserTransaction(); } else { txn = transactionService.getUserTransaction(readOnly); } try { // Begin the transaction, do the work and then commit the // transaction txn.begin(); result = transactionWork.doWork(); // rollback or commit if (txn.getStatus() == Status.STATUS_MARKED_ROLLBACK) { // something caused the transaction to be marked for rollback txn.rollback(); } else { // transaction should still commit txn.commit(); } } catch (RollbackException exception) { // commit failed throw new AlfrescoRuntimeException("Unexpected rollback exception: \n" + exception.getMessage(), exception); } catch (Throwable exception) { try { // Roll back the exception txn.rollback(); } catch (Throwable rollbackException) { // just dump the exception - we are already in a failure state logger.error("Error rolling back transaction", rollbackException); } // Re-throw the exception if (exception instanceof RuntimeException) { throw (RuntimeException) exception; } else { throw new RuntimeException("Error during execution of transaction.", exception); } } return result; }
From source file:org.alfresco.repo.transfer.fsr.FileTransferReceiverMain.java
/** * @param args String[]//w w w. j a v a 2 s. c o m */ public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("alfresco/fsr-bootstrap-context.xml"); RetryingTransactionHelper ts = (RetryingTransactionHelper) context.getBean("retryingTransactionHelper"); FileTransferReceiverTransactionServiceImpl transactionService = (FileTransferReceiverTransactionServiceImpl) context .getBean("transactionService"); //TransferReceiver ftTransferReceiver = (TransferReceiver) context.getBean("transferReceiver"); try { UserTransaction ut = transactionService.getUserTransaction(); ut.begin(); //ftTransferReceiver.start("1234", false, ftTransferReceiver.getVersion()); QNameDAO qNameDAO = (QNameDAO) context.getBean("qnameDAO"); //qNameDAO.getOrCreateNamespace("test2"); //Pair<Long, String> pair = qNameDAO.getNamespace(1L); //System.out.println("Pair:" + pair.getSecond()); //Pair<Long, String> pair = qNameDAO.getNamespace("test2"); //System.out.println("Pair first:" + pair.getFirst()); //System.out.println("Pair second:" + pair.getSecond()); FileTransferInfoDAO fileTransferInfoDAO = (FileTransferInfoDAO) context.getBean("fileTransferInfoDAO"); //fileTransferInfoDAO.createFileTransferInfo("nodeRef", "Parent", "/a/b/c", "tot.txt","contentUrl"); FileTransferInfoEntity fti = fileTransferInfoDAO.findFileTransferInfoByNodeRef("nodeRef"); if (fti == null) { System.out.println("FTI is null!!!"); } else { System.out.println("FTI ID:" + fti.getId()); System.out.println("FTI path:" + fti.getPath()); System.out.println("FTI contentName:" + fti.getContentName()); System.out.println("FTI content Url:" + fti.getContentUrl()); } ut.commit(); } catch (Exception e) { e.printStackTrace(); } ((ClassPathXmlApplicationContext) context).close(); System.exit(0); }
From source file:org.alfresco.repo.transfer.TransferServiceImpl2.java
/** * Transfer async./*from w w w.j av a2s . com*/ * * @param targetName String * @param definition TransferDefinition * */ public void transferAsync(String targetName, TransferDefinition definition, Collection<TransferCallback> callbacks) { /** * Event processor for this transfer instance */ final TransferEventProcessor eventProcessor = new TransferEventProcessor(); if (callbacks != null) { eventProcessor.observers.addAll(callbacks); } /* * Note: * callback should be Serializable to be passed through the action API * However Serializable is not used so it does not matter. Perhaps the action API should be * changed? Or we could add a Serializable proxy here. */ Map<String, Serializable> params = new HashMap<String, Serializable>(); params.put("targetName", targetName); params.put("definition", definition); params.put("callbacks", (Serializable) callbacks); Action transferAction = actionService.createAction("transfer-async", params); /** * Execute transfer async in its own transaction. * The action service only runs actions in the post commit which is why there's * a separate transaction here. */ boolean success = false; UserTransaction trx = transactionService.getNonPropagatingUserTransaction(); try { trx.begin(); logger.debug("calling action service to execute action"); actionService.executeAction(transferAction, null, false, true); trx.commit(); logger.debug("committed successfully"); success = true; } catch (Exception error) { logger.error("unexpected exception", error); throw new AlfrescoRuntimeException(MSG_ERR_TRANSFER_ASYNC, error); } finally { if (!success) { try { logger.debug("rolling back after error"); trx.rollback(); } catch (Exception error) { logger.error("unexpected exception during rollback", error); // There's nothing much we can do here } } } }