use of org.alfresco.service.cmr.transfer.TransferCallback in project alfresco-repository by Alfresco.
the class TransferServiceImplTest method testAsyncCallback.
// Path based update
/**
* Test the transfer method when it is running async.
*
* This is a unit test so it does some shenanigans to send to the same instance of alfresco.
*/
@Test
public void testAsyncCallback() throws Exception {
final int MAX_SLEEPS = 5;
final RetryingTransactionHelper tran = transactionService.getRetryingTransactionHelper();
/**
* Unit test kludge to transfer from guest home to company home
*/
final UnitTestTransferManifestNodeFactory testNodeFactory = unitTestKludgeToTransferGuestHomeToCompanyHome();
/**
* This needs to be committed before we can call transfer asycnc.
*/
final String CONTENT_TITLE = "ContentTitle";
final String CONTENT_NAME_A = "Demo Node A";
final String CONTENT_NAME_B = "Demo Node B";
final Locale CONTENT_LOCALE = Locale.GERMAN;
final String CONTENT_STRING = "Hello";
final String targetName = "testAsyncCallback";
class TestContext {
TransferTarget transferMe;
NodeRef nodeRefA = null;
NodeRef nodeRefB = null;
}
;
RetryingTransactionCallback<TestContext> setupCB = new RetryingTransactionCallback<TestContext>() {
@Override
public TestContext execute() throws Throwable {
TestContext ctx = new TestContext();
final NodeRef guestHome = repositoryHelper.getGuestHome();
ctx.nodeRefA = nodeService.getChildByName(guestHome, ContentModel.ASSOC_CONTAINS, CONTENT_NAME_A);
if (ctx.nodeRefA == null) {
/**
* Create a test node that we will read and write
*/
ChildAssociationRef child = nodeService.createNode(guestHome, ContentModel.ASSOC_CONTAINS, QName.createQName(GUID.generate()), ContentModel.TYPE_CONTENT);
ctx.nodeRefA = child.getChildRef();
nodeService.setProperty(ctx.nodeRefA, ContentModel.PROP_TITLE, CONTENT_TITLE);
nodeService.setProperty(ctx.nodeRefA, ContentModel.PROP_NAME, CONTENT_NAME_A);
ContentWriter writer = contentService.getWriter(ctx.nodeRefA, ContentModel.PROP_CONTENT, true);
writer.setLocale(CONTENT_LOCALE);
writer.putContent(CONTENT_STRING);
}
ctx.nodeRefB = nodeService.getChildByName(guestHome, ContentModel.ASSOC_CONTAINS, CONTENT_NAME_B);
if (ctx.nodeRefB == null) {
ChildAssociationRef child = nodeService.createNode(guestHome, ContentModel.ASSOC_CONTAINS, QName.createQName(GUID.generate()), ContentModel.TYPE_CONTENT);
ctx.nodeRefB = child.getChildRef();
nodeService.setProperty(ctx.nodeRefB, ContentModel.PROP_TITLE, CONTENT_TITLE);
nodeService.setProperty(ctx.nodeRefB, ContentModel.PROP_NAME, CONTENT_NAME_B);
ContentWriter writer = contentService.getWriter(ctx.nodeRefB, ContentModel.PROP_CONTENT, true);
writer.setLocale(CONTENT_LOCALE);
writer.putContent(CONTENT_STRING);
}
/**
* Now go ahead and create our first transfer target
*/
if (!transferService.targetExists(targetName)) {
createTransferTarget(targetName);
} else {
transferService.getTransferTarget(targetName);
}
return ctx;
}
};
final TestContext testContext = tran.doInTransaction(setupCB);
RetryingTransactionCallback<List<TransferEvent>> transferCB = new RetryingTransactionCallback<List<TransferEvent>>() {
@Override
public List<TransferEvent> execute() throws Throwable {
List<TransferEvent> transferReport = new ArrayList<TransferEvent>(50);
TestTransferCallback callback = new TestTransferCallback();
Set<TransferCallback> callbacks = new HashSet<TransferCallback>();
callbacks.add(callback);
TransferDefinition definition = new TransferDefinition();
Set<NodeRef> nodes = new HashSet<NodeRef>();
nodes.add(testContext.nodeRefA);
nodes.add(testContext.nodeRefB);
definition.setNodes(nodes);
transferService.transferAsync(targetName, definition, callbacks);
logger.debug("transfer async has returned");
/**
* Need to poll the transfer events here until callback receives the last event
*/
Queue<TransferEvent> events = callback.getEvents();
int sleepCount = MAX_SLEEPS;
boolean ended = false;
TransferEvent event = events.poll();
while (!ended) {
logger.debug("polling loop:" + sleepCount);
while (event != null) {
/**
* Got an event - reset the sleep counter
*/
sleepCount = MAX_SLEEPS;
logger.debug("Got an event" + event.toString());
/**
* Squirrel away the event for analysis later
*/
transferReport.add(event);
/**
* If we read the last record which will either be SUCCESS or ERROR then we we have finished
*/
if (event.isLast()) {
logger.debug("got last event");
ended = true;
}
/**
* Try to get the next event
*/
event = events.poll();
}
if (event == null && !ended) {
if (sleepCount <= 0) {
fail("timed out without receiving last event");
ended = true;
} else {
/**
* No content - go to sleep to wait for some more
*/
if (sleepCount-- > 0) {
// Sleep for 5 second
Thread.sleep(5000);
}
}
/**
* Try to get the next event
*/
event = events.poll();
}
}
return transferReport;
}
};
/**
* The transfer report is a plain report of the transfer - no async shenanigans to worry about
*/
final List<TransferEvent> transferReport = tran.doInTransaction(transferCB);
/**
* Now validate the transferReport
*/
assertTrue("transfer report is too small", transferReport.size() > 2);
assertTrue("transfer report does not start with START", transferReport.get(0).getTransferState().equals(TransferEvent.TransferState.START));
boolean success = false;
for (TransferEvent event : transferReport) {
if (event.getTransferState() == TransferEvent.TransferState.SUCCESS) {
success = true;
}
}
assertTrue("transfer report does not contain SUCCESS", success);
}
Aggregations