diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/action/running-action.lib.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/action/running-action.lib.ftl
index a141834873..5bedcc1072 100644
--- a/config/alfresco/templates/webscripts/org/alfresco/repository/action/running-action.lib.ftl
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/action/running-action.lib.ftl
@@ -6,7 +6,7 @@
"actionType": "${action.type}",
"actionInstance": "${action.instance?string}",
"actionNodeRef": <#if action.nodeRef??>"${action.nodeRef.nodeRef}"<#else>null#if>,
- "startedAt": "${action.startedAt}",
+ "startedAt": <#if action.startedAt??>"${action.startedAt}"<#else>null#if>,
"cancelRequested": "${action.cancelRequested?string}",
"details": "${"/api/running-action/" + action.key}",
}
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/action/running-actions.post.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/action/running-actions.post.desc.xml
index 00a47a3da6..5a30d61c95 100644
--- a/config/alfresco/templates/webscripts/org/alfresco/repository/action/running-actions.post.desc.xml
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/action/running-actions.post.desc.xml
@@ -6,6 +6,5 @@
/api/running-actions?nodeRef={nodeRef?}
admin
-
- none
+ required
diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/action/running-replication-actions.post.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/action/running-replication-actions.post.desc.xml
index 8952e774b2..49c138898f 100644
--- a/config/alfresco/templates/webscripts/org/alfresco/repository/action/running-replication-actions.post.desc.xml
+++ b/config/alfresco/templates/webscripts/org/alfresco/repository/action/running-replication-actions.post.desc.xml
@@ -6,6 +6,5 @@
/api/running-replication-actions?name={name?}
admin
-
- none
+ required
diff --git a/config/alfresco/web-scripts-application-context.xml b/config/alfresco/web-scripts-application-context.xml
index 855f425270..62c494ab5a 100644
--- a/config/alfresco/web-scripts-application-context.xml
+++ b/config/alfresco/web-scripts-application-context.xml
@@ -922,7 +922,6 @@
-
diff --git a/source/java/org/alfresco/repo/web/scripts/action/AbstractExecuteActionWebscript.java b/source/java/org/alfresco/repo/web/scripts/action/AbstractExecuteActionWebscript.java
index 357f8bfec8..92b5f50be8 100644
--- a/source/java/org/alfresco/repo/web/scripts/action/AbstractExecuteActionWebscript.java
+++ b/source/java/org/alfresco/repo/web/scripts/action/AbstractExecuteActionWebscript.java
@@ -20,12 +20,8 @@ package org.alfresco.repo.web.scripts.action;
import java.util.Map;
-import javax.transaction.UserTransaction;
-
import org.alfresco.service.cmr.action.Action;
-import org.alfresco.service.cmr.action.ActionStatus;
import org.alfresco.service.cmr.action.ExecutionSummary;
-import org.alfresco.service.transaction.TransactionService;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
@@ -38,64 +34,34 @@ import org.springframework.extensions.webscripts.WebScriptRequest;
*/
public abstract class AbstractExecuteActionWebscript extends AbstractActionWebscript
{
- protected TransactionService transactionService;
-
- public void setTransactionService(TransactionService transactionService)
- {
- this.transactionService = transactionService;
- }
-
protected Map buildModel(
RunningActionModelBuilder modelBuilder,
WebScriptRequest req,
Status status, Cache cache)
{
try {
- // Start our transaction
- UserTransaction txn = transactionService.getUserTransaction();
- txn.begin();
-
// Have the action to run be identified
Action action = identifyAction(req, status, cache);
if(action == null) {
- txn.rollback();
throw new WebScriptException(
Status.STATUS_NOT_FOUND,
- "No Running Action found with the supplied details"
+ "No Runnable Action found with the supplied details"
);
}
// Ask for it to be run in the background
+ // It will be available to execute once the webscript finishes
actionService.executeAction(
action, null,
false, true
);
- // Have it begin
- txn.commit();
-
- // TODO Update this after changes to the
- // action tracking service for pending actions
- // have been made
-
- // Wait up to 5 seconds for it to kick off
- long beganWaitingAt = System.currentTimeMillis();
- while(beganWaitingAt + 5000 > System.currentTimeMillis() &&
- action.getExecutionStatus() == ActionStatus.Pending)
- {
- try {
- Thread.sleep(50);
- } catch(InterruptedException e) {}
- }
-
// Return the details if we can
-System.err.println(action);
-System.err.println(action.getExecutionStatus());
ExecutionSummary summary = getSummaryFromAction(action);
if(summary == null) {
throw new WebScriptException(
Status.STATUS_EXPECTATION_FAILED,
- "Action failed to start in the required timeframe"
+ "Action failed to be added to the pending queue"
);
}
diff --git a/source/java/org/alfresco/repo/web/scripts/action/RunningActionModelBuilder.java b/source/java/org/alfresco/repo/web/scripts/action/RunningActionModelBuilder.java
index 1a99914ce0..2c626bef72 100644
--- a/source/java/org/alfresco/repo/web/scripts/action/RunningActionModelBuilder.java
+++ b/source/java/org/alfresco/repo/web/scripts/action/RunningActionModelBuilder.java
@@ -121,10 +121,15 @@ public class RunningActionModelBuilder
ram.put(ACTION_KEY, AbstractActionWebscript.getRunningId(summary));
ram.put(ACTION_NODE_REF, details.getPersistedActionRef());
- ram.put(ACTION_STARTED_AT, ISO8601DateFormat.format(details.getStartedAt()));
ram.put(ACTION_RUNNING_ON, details.getRunningOn());
ram.put(ACTION_CANCEL_REQUESTED, details.isCancelRequested());
+ if(details.getStartedAt() != null) {
+ ram.put(ACTION_STARTED_AT, ISO8601DateFormat.format(details.getStartedAt()));
+ } else {
+ ram.put(ACTION_STARTED_AT, null);
+ }
+
return ram;
}
diff --git a/source/java/org/alfresco/repo/web/scripts/action/RunningActionRestApiTest.java b/source/java/org/alfresco/repo/web/scripts/action/RunningActionRestApiTest.java
index 8cbd88640a..6e1d27617d 100644
--- a/source/java/org/alfresco/repo/web/scripts/action/RunningActionRestApiTest.java
+++ b/source/java/org/alfresco/repo/web/scripts/action/RunningActionRestApiTest.java
@@ -171,7 +171,7 @@ public class RunningActionRestApiTest extends BaseWebScriptTest
id + "=" + instance, jsonRD.get("details"));
- // Add a 2nd and 3rd
+ // Add a 2nd and 3rd - one pending, one running
rd = replicationService.createReplicationDefinition("Test2", "2nd Testing");
replicationService.saveReplicationDefinition(rd);
actionTrackingService.recordActionExecuting(rd);
@@ -181,7 +181,7 @@ public class RunningActionRestApiTest extends BaseWebScriptTest
rd = replicationService.createReplicationDefinition("AnotherTest", "3rd Testing");
replicationService.saveReplicationDefinition(rd);
- actionTrackingService.recordActionExecuting(rd);
+ actionTrackingService.recordActionPending(rd);
String id3 = rd.getId();
@@ -464,7 +464,7 @@ public class RunningActionRestApiTest extends BaseWebScriptTest
id + "=" + instance, jsonRD.get("details"));
- // Add a 2nd and 3rd
+ // Add a 2nd and 3rd, one running and one pending
rd = replicationService.createReplicationDefinition("Test2", "2nd Testing");
replicationService.saveReplicationDefinition(rd);
actionTrackingService.recordActionExecuting(rd);
@@ -474,7 +474,7 @@ public class RunningActionRestApiTest extends BaseWebScriptTest
rd = replicationService.createReplicationDefinition("AnotherTest", "3rd Testing");
replicationService.saveReplicationDefinition(rd);
- actionTrackingService.recordActionExecuting(rd);
+ actionTrackingService.recordActionPending(rd);
String id3 = rd.getId();
@@ -688,6 +688,29 @@ public class RunningActionRestApiTest extends BaseWebScriptTest
assertEquals(startedAt, jsonRD.get("startedAt"));
assertEquals(false, jsonRD.getBoolean("cancelRequested"));
assertEquals("/" + URL_RUNNING_ACTION + key1, jsonRD.get("details"));
+
+
+ // Add one that is pending - has everything except start date
+ rd = replicationService.createReplicationDefinition("Test3", "Testing");
+ replicationService.saveReplicationDefinition(rd);
+ actionTrackingService.recordActionPending(rd);
+ String id3 = rd.getId();
+ String instance3 = Integer.toString( ((ActionImpl)rd).getExecutionInstance() );
+ String key3 = "replicationActionExecutor=" + id3 + "=" + instance3;
+
+ response = sendRequest(new GetRequest(URL_RUNNING_ACTION + key3), Status.STATUS_OK);
+ assertEquals(Status.STATUS_OK, response.getStatus());
+
+ jsonStr = response.getContentAsString();
+ jsonRD = new JSONObject(jsonStr);
+ assertNotNull(jsonRD);
+ assertEquals(id3, jsonRD.get("actionId"));
+ assertEquals(ReplicationDefinitionImpl.EXECUTOR_NAME, jsonRD.get("actionType"));
+ assertEquals(instance3, jsonRD.get("actionInstance"));
+ assertEquals(rd.getNodeRef().toString(), jsonRD.get("actionNodeRef"));
+ assertEquals(JSONObject.NULL, jsonRD.get("startedAt"));
+ assertEquals(false, jsonRD.getBoolean("cancelRequested"));
+ assertEquals("/" + URL_RUNNING_ACTION + key3, jsonRD.get("details"));
}
public void testRunningActionCancel() throws Exception
@@ -736,13 +759,40 @@ public class RunningActionRestApiTest extends BaseWebScriptTest
assertEquals(Status.STATUS_GONE, response.getStatus());
assertEquals(true, actionTrackingService.isCancellationRequested(rd));
+
+
+ // You can ask a pending action to cancel
+ // At this time, it will remain in the queue though
+ rd = replicationService.createReplicationDefinition("Test2", "Testing");
+ replicationService.saveReplicationDefinition(rd);
+ actionTrackingService.recordActionPending(rd);
+ String id2 = rd.getId();
+ String instance2 = Integer.toString( ((ActionImpl)rd).getExecutionInstance() );
+ String key2 = "replicationActionExecutor=" + id2 + "=" + instance2;
+
+
+ // Should be in the cache, but not not running and not cancelled
+ assertEquals(false, actionTrackingService.isCancellationRequested(rd));
+ assertEquals(null, rd.getExecutionStartDate());
+
+ assertNotNull(executingActionsCache.get(key2));
+ assertFalse(executingActionsCache.get(key2).isCancelRequested());
+
+
+ // Ask for it to be cancelled via the webscript
+ response = sendRequest(new DeleteRequest(URL_RUNNING_ACTION + key2), Status.STATUS_GONE);
+ assertEquals(Status.STATUS_GONE, response.getStatus());
+
+
+ // Should still be in the cache, not running but cancelled
+ assertNotNull(executingActionsCache.get(key2));
+ assertTrue(executingActionsCache.get(key2).isCancelRequested());
+
+ assertEquals(true, actionTrackingService.isCancellationRequested(rd));
+ assertEquals(null, rd.getExecutionStartDate());
}
- /**
- * TODO Fix this up after the changes to the action tracking
- * service for pending actions have been made
- */
- public void DISABLEDtestRunningActionsPost() throws Exception
+ public void testRunningActionsPost() throws Exception
{
Response response;
@@ -792,22 +842,25 @@ public class RunningActionRestApiTest extends BaseWebScriptTest
assertEquals(rd.getNodeRef().toString(), jsonRD.get("actionNodeRef"));
assertEquals(false, jsonRD.getBoolean("cancelRequested"));
- // Wait a bit for it to be run + fail
- // Check that it failed due to insufficient definition options
+ // Should be pending
+ // Wait for it to fail (we didn't
+ // specify enough options for a valid transfer)
for(int i=0; i<50; i++) {
txn = transactionService.getUserTransaction();
txn.begin();
rd = replicationService.loadReplicationDefinition("Test1");
txn.commit();
-
- if(rd.getExecutionStatus() == ActionStatus.New ||
- rd.getExecutionStatus() == ActionStatus.Pending ||
- rd.getExecutionStatus() == ActionStatus.Running) {
+
+ if(rd.getExecutionStatus() == ActionStatus.New) {
+ // Still pending, or maybe running
try {
Thread.sleep(100);
} catch(InterruptedException e) {}
- } else {
+ } else if (rd.getExecutionStatus() == ActionStatus.Failed) {
+ // We're done
break;
+ } else {
+ fail("Unexpected status in repo of " + rd.getExecutionStatus());
}
}
assertEquals(ActionStatus.Failed, rd.getExecutionStatus());
@@ -817,14 +870,93 @@ public class RunningActionRestApiTest extends BaseWebScriptTest
json = new JSONObject();
json.put("nodeRef", "XX"+rd.getNodeRef().toString()+"ZZ");
- response = sendRequest(new PostRequest(URL_RUNNING_ACTIONS, json.toString(), JSON), Status.STATUS_BAD_REQUEST);
- assertEquals(Status.STATUS_BAD_REQUEST, response.getStatus());
+ response = sendRequest(new PostRequest(URL_RUNNING_ACTIONS, json.toString(), JSON), Status.STATUS_NOT_FOUND);
+ assertEquals(Status.STATUS_NOT_FOUND, response.getStatus());
}
+ public void testRunningReplicationsActionsPost() throws Exception
+ {
+ Response response;
+
+
+ // Not allowed if you're not an admin
+ AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getGuestUserName());
+ response = sendRequest(new PostRequest(URL_RUNNING_REPLICATION_ACTIONS, "{}", JSON), Status.STATUS_UNAUTHORIZED);
+ assertEquals(Status.STATUS_UNAUTHORIZED, response.getStatus());
+
+ AuthenticationUtil.setFullyAuthenticatedUser(USER_NORMAL);
+ response = sendRequest(new PostRequest(URL_RUNNING_REPLICATION_ACTIONS, "{}", JSON), Status.STATUS_UNAUTHORIZED);
+ assertEquals(Status.STATUS_UNAUTHORIZED, response.getStatus());
+
+
+ // If no noderef supplied, will get an error
+ AuthenticationUtil.setFullyAuthenticatedUser(AuthenticationUtil.getAdminUserName());
+ response = sendRequest(new PostRequest(URL_RUNNING_REPLICATION_ACTIONS, "{}", JSON), Status.STATUS_BAD_REQUEST);
+ assertEquals(Status.STATUS_BAD_REQUEST, response.getStatus());
+
+
+ // Add a running action
+ UserTransaction txn = transactionService.getUserTransaction();
+ txn.begin();
+
+ ReplicationDefinition rd = replicationService.createReplicationDefinition("Test1", "Testing");
+ replicationService.saveReplicationDefinition(rd);
+ String id = rd.getId();
+
+ txn.commit();
+
+
+ // Ask for it to be started
+ // (It should start but fail due to missing definition parts)
+ JSONObject json = new JSONObject();
+ json.put("name", "Test1");
+
+ response = sendRequest(new PostRequest(URL_RUNNING_REPLICATION_ACTIONS, json.toString(), JSON), Status.STATUS_OK);
+ assertEquals(Status.STATUS_OK, response.getStatus());
+
+ // Check we got back some details on it
+ String jsonStr = response.getContentAsString();
+ JSONObject jsonRD = new JSONObject(jsonStr);
+ assertNotNull(jsonRD);
+
+ assertEquals(id, jsonRD.get("actionId"));
+ assertEquals(ReplicationDefinitionImpl.EXECUTOR_NAME, jsonRD.get("actionType"));
+ assertEquals(rd.getNodeRef().toString(), jsonRD.get("actionNodeRef"));
+ assertEquals(false, jsonRD.getBoolean("cancelRequested"));
+
+ // Should be pending
+ // Wait for it to fail (we didn't
+ // specify enough options for a valid transfer)
+ for(int i=0; i<50; i++) {
+ txn = transactionService.getUserTransaction();
+ txn.begin();
+ rd = replicationService.loadReplicationDefinition("Test1");
+ txn.commit();
+
+ if(rd.getExecutionStatus() == ActionStatus.New) {
+ // Still pending, or maybe running
+ try {
+ Thread.sleep(100);
+ } catch(InterruptedException e) {}
+ } else if (rd.getExecutionStatus() == ActionStatus.Failed) {
+ // We're done
+ break;
+ } else {
+ fail("Unexpected status in repo of " + rd.getExecutionStatus());
+ }
+ }
+ assertEquals(ActionStatus.Failed, rd.getExecutionStatus());
+
+
+ // Ensure you can't start with an invalid name
+ json = new JSONObject();
+ json.put("name", "MadeUpName");
+
+ response = sendRequest(new PostRequest(URL_RUNNING_REPLICATION_ACTIONS, json.toString(), JSON), Status.STATUS_NOT_FOUND);
+ assertEquals(Status.STATUS_NOT_FOUND, response.getStatus());
+ }
- // TODO - Running Replication Actions POST unit tests
-
-
+
@Override
protected void setUp() throws Exception
{
diff --git a/source/java/org/alfresco/repo/web/scripts/action/RunningActionsPost.java b/source/java/org/alfresco/repo/web/scripts/action/RunningActionsPost.java
index c9d15c4503..ea465f5c60 100644
--- a/source/java/org/alfresco/repo/web/scripts/action/RunningActionsPost.java
+++ b/source/java/org/alfresco/repo/web/scripts/action/RunningActionsPost.java
@@ -59,10 +59,14 @@ public class RunningActionsPost extends AbstractExecuteActionWebscript
}
}
- // Load the specified action
+ // Does it exist in the repo?
NodeRef actionNodeRef = new NodeRef(nodeRef);
+ if(! nodeService.exists(actionNodeRef)) {
+ return null;
+ }
+
+ // Load the specified action
Action action = runtimeActionService.createAction(actionNodeRef);
-
return action;
}
}
\ No newline at end of file