From 945d5112987ccef013edea9e15043de5b6b3d810 Mon Sep 17 00:00:00 2001 From: Dave Ward Date: Tue, 14 Sep 2010 12:47:50 +0000 Subject: [PATCH] Merged V3.3-BUG-FIX to HEAD 22497: Merged V3.3 to V3.3-BUG-FIX 22495: Merged V3.2 to V3.3 22465: (RECORD ONLY) Fix for ALF-4741. Repository Web Scripts can produce a corrupted response after a transaction collision/retry. The fix was to have the BufferedResponse.afterRollback() method reset the buffer rather than write the response. 22468: (RECORD ONLY) Incremented version label 22494: ALF-4741: Rework of previous fix to ensure a buffered web script response is always flushed after the last transaction retry - even on a rollback git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@22498 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../repo/web/scripts/RepositoryContainer.java | 110 +++++++----------- 1 file changed, 41 insertions(+), 69 deletions(-) diff --git a/source/java/org/alfresco/repo/web/scripts/RepositoryContainer.java b/source/java/org/alfresco/repo/web/scripts/RepositoryContainer.java index b8ea6728fb..cfddb5e6a4 100644 --- a/source/java/org/alfresco/repo/web/scripts/RepositoryContainer.java +++ b/source/java/org/alfresco/repo/web/scripts/RepositoryContainer.java @@ -38,7 +38,6 @@ import org.alfresco.repo.tenant.TenantAdminService; import org.alfresco.repo.tenant.TenantDeployer; import org.alfresco.repo.transaction.AlfrescoTransactionSupport; import org.alfresco.repo.transaction.RetryingTransactionHelper; -import org.alfresco.repo.transaction.TransactionListener; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.TemplateService; @@ -79,9 +78,6 @@ public class RepositoryContainer extends AbstractRuntimeContainer implements Ten // Logger protected static final Log logger = LogFactory.getLog(RepositoryContainer.class); - // Transaction key for buffered response - private static String BUFFERED_RESPONSE_KEY = RepositoryContainer.class.getName() + ".bufferedresponse"; - /** Component Dependencies */ private Repository repository; private RepositoryImageResolver imageResolver; @@ -331,6 +327,30 @@ public class RepositoryContainer extends AbstractRuntimeContainer implements Ten } else { + final BufferedResponse bufferedRes; + RequiredTransactionParameters trxParams = description.getRequiredTransactionParameters(); + if (trxParams.getCapability() == TransactionCapability.readwrite) + { + if (trxParams.getBufferSize() > 0) + { + if (logger.isDebugEnabled()) + logger.debug("Creating Transactional Response for ReadWrite transaction; buffersize=" + trxParams.getBufferSize()); + + // create buffered response that allows transaction retrying + bufferedRes = new BufferedResponse(scriptRes, trxParams.getBufferSize()); + } + else + { + if (logger.isDebugEnabled()) + logger.debug("Transactional Response bypassed for ReadWrite - buffersize=0"); + bufferedRes = null; + } + } + else + { + bufferedRes = null; + } + // encapsulate script within transaction RetryingTransactionCallback work = new RetryingTransactionCallback() { @@ -342,29 +362,16 @@ public class RepositoryContainer extends AbstractRuntimeContainer implements Ten logger.debug("Begin retry transaction block: " + description.getRequiredTransaction() + "," + description.getRequiredTransactionParameters().getCapability()); - WebScriptResponse redirectedRes = scriptRes; - RequiredTransactionParameters trxParams = description.getRequiredTransactionParameters(); - if (trxParams.getCapability() == TransactionCapability.readwrite) + if (bufferedRes == null) { - if (trxParams.getBufferSize() > 0) - { - if (logger.isDebugEnabled()) - logger.debug("Creating Transactional Response for ReadWrite transaction; buffersize=" + trxParams.getBufferSize()); - - // create buffered response that's sensitive transaction boundary - BufferedResponse bufferedRes = new BufferedResponse(scriptRes, trxParams.getBufferSize()); - AlfrescoTransactionSupport.bindResource(BUFFERED_RESPONSE_KEY, bufferedRes); - AlfrescoTransactionSupport.bindListener(bufferedRes); - redirectedRes = bufferedRes; - } - else - { - if (logger.isDebugEnabled()) - logger.debug("Transactional Response bypassed for ReadWrite - buffersize=0"); - } + script.execute(scriptReq, scriptRes); + } + else + { + // Reset the response in case of a transaction retry + bufferedRes.reset(); + script.execute(scriptReq, bufferedRes); } - - script.execute(scriptReq, redirectedRes); } catch(Exception e) { @@ -414,7 +421,14 @@ public class RepositoryContainer extends AbstractRuntimeContainer implements Ten boolean readonly = description.getRequiredTransactionParameters().getCapability() == TransactionCapability.readonly; boolean requiresNew = description.getRequiredTransaction() == RequiredTransaction.requiresnew; - retryingTransactionHelper.doInTransaction(work, readonly, requiresNew); + retryingTransactionHelper.doInTransaction(work, readonly, requiresNew); + + // Ensure a response is always flushed after successful execution + if (bufferedRes != null) + { + bufferedRes.writeResponse(); + } + } } @@ -575,7 +589,7 @@ public class RepositoryContainer extends AbstractRuntimeContainer implements Ten /** * Transactional Buffered Response */ - private static class BufferedResponse implements TransactionListener, WrappingWebScriptResponse + private static class BufferedResponse implements WrappingWebScriptResponse { private WebScriptResponse res; private int bufferSize; @@ -752,48 +766,6 @@ public class RepositoryContainer extends AbstractRuntimeContainer implements Ten res.setStatus(status); } - /* - * (non-Javadoc) - * @see org.alfresco.repo.transaction.TransactionListener#afterCommit() - */ - public void afterCommit() - { - writeResponse(); - } - - /* - * (non-Javadoc) - * @see org.alfresco.repo.transaction.TransactionListener#afterRollback() - */ - public void afterRollback() - { - reset(); - } - - /* - * (non-Javadoc) - * @see org.alfresco.repo.transaction.TransactionListener#beforeCommit(boolean) - */ - public void beforeCommit(boolean readOnly) - { - } - - /* - * (non-Javadoc) - * @see org.alfresco.repo.transaction.TransactionListener#beforeCompletion() - */ - public void beforeCompletion() - { - } - - /* - * (non-Javadoc) - * @see org.alfresco.repo.transaction.TransactionListener#flush() - */ - public void flush() - { - } - /** * Write buffered response to underlying response */