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
This commit is contained in:
Dave Ward
2010-09-14 12:47:50 +00:00
parent 86a09d69e2
commit 945d511298

View File

@@ -38,7 +38,6 @@ import org.alfresco.repo.tenant.TenantAdminService;
import org.alfresco.repo.tenant.TenantDeployer; import org.alfresco.repo.tenant.TenantDeployer;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport; import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.TransactionListener;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.TemplateService; import org.alfresco.service.cmr.repository.TemplateService;
@@ -79,9 +78,6 @@ public class RepositoryContainer extends AbstractRuntimeContainer implements Ten
// Logger // Logger
protected static final Log logger = LogFactory.getLog(RepositoryContainer.class); 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 */ /** Component Dependencies */
private Repository repository; private Repository repository;
private RepositoryImageResolver imageResolver; private RepositoryImageResolver imageResolver;
@@ -331,6 +327,30 @@ public class RepositoryContainer extends AbstractRuntimeContainer implements Ten
} }
else 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 // encapsulate script within transaction
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>() RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
{ {
@@ -342,30 +362,17 @@ public class RepositoryContainer extends AbstractRuntimeContainer implements Ten
logger.debug("Begin retry transaction block: " + description.getRequiredTransaction() + "," logger.debug("Begin retry transaction block: " + description.getRequiredTransaction() + ","
+ description.getRequiredTransactionParameters().getCapability()); + description.getRequiredTransactionParameters().getCapability());
WebScriptResponse redirectedRes = scriptRes; if (bufferedRes == null)
RequiredTransactionParameters trxParams = description.getRequiredTransactionParameters();
if (trxParams.getCapability() == TransactionCapability.readwrite)
{ {
if (trxParams.getBufferSize() > 0) script.execute(scriptReq, scriptRes);
{
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 else
{ {
if (logger.isDebugEnabled()) // Reset the response in case of a transaction retry
logger.debug("Transactional Response bypassed for ReadWrite - buffersize=0"); bufferedRes.reset();
script.execute(scriptReq, bufferedRes);
} }
} }
script.execute(scriptReq, redirectedRes);
}
catch(Exception e) catch(Exception e)
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
@@ -415,6 +422,13 @@ public class RepositoryContainer extends AbstractRuntimeContainer implements Ten
boolean readonly = description.getRequiredTransactionParameters().getCapability() == TransactionCapability.readonly; boolean readonly = description.getRequiredTransactionParameters().getCapability() == TransactionCapability.readonly;
boolean requiresNew = description.getRequiredTransaction() == RequiredTransaction.requiresnew; 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 * Transactional Buffered Response
*/ */
private static class BufferedResponse implements TransactionListener, WrappingWebScriptResponse private static class BufferedResponse implements WrappingWebScriptResponse
{ {
private WebScriptResponse res; private WebScriptResponse res;
private int bufferSize; private int bufferSize;
@@ -752,48 +766,6 @@ public class RepositoryContainer extends AbstractRuntimeContainer implements Ten
res.setStatus(status); 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 * Write buffered response to underlying response
*/ */