mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
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:
@@ -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,29 +362,16 @@ 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())
|
else
|
||||||
logger.debug("Creating Transactional Response for ReadWrite transaction; buffersize=" + trxParams.getBufferSize());
|
{
|
||||||
|
// Reset the response in case of a transaction retry
|
||||||
// create buffered response that's sensitive transaction boundary
|
bufferedRes.reset();
|
||||||
BufferedResponse bufferedRes = new BufferedResponse(scriptRes, trxParams.getBufferSize());
|
script.execute(scriptReq, bufferedRes);
|
||||||
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, redirectedRes);
|
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
{
|
{
|
||||||
@@ -414,7 +421,14 @@ 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
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user