From 8b7c8003959e7c35bde2e418bee2de5e07eacb41 Mon Sep 17 00:00:00 2001
From: Marco Rietveld
Date: Thu, 3 Oct 2013 16:36:23 +0200
Subject: [PATCH] JBPM-3814 BZ 1002724 Fixes that use SeamTransaction injection
(cherry picked from commit ca439c9dd697bcd2418efaf32d3ed597f8246395)
---
.../remote/cdi/ProcessRequestBean.java | 77 -----
.../remote/jms/RequestMessageBean.java | 82 +++++-
.../services/remote/rest/ResourceBase.java | 111 ++++++-
.../remote/rest/RestProcessRequestBean.java | 274 ++++++++++++++++++
.../services/remote/rest/RuntimeResource.java | 233 ++++++++++-----
.../services/remote/rest/TaskResource.java | 104 ++++---
.../DescriptiveExceptionHandler.java | 6 +
.../remote/util/CommandsRequestUtil.java | 70 -----
8 files changed, 665 insertions(+), 292 deletions(-)
delete mode 100644 kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/cdi/ProcessRequestBean.java
create mode 100644 kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/RestProcessRequestBean.java
delete mode 100644 kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/util/CommandsRequestUtil.java
diff --git a/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/cdi/ProcessRequestBean.java b/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/cdi/ProcessRequestBean.java
deleted file mode 100644
index 28541f9084..0000000000
--- a/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/cdi/ProcessRequestBean.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package org.kie.services.remote.cdi;
-
-
-import javax.enterprise.context.ApplicationScoped;
-import javax.inject.Inject;
-
-import org.jboss.resteasy.spi.UnauthorizedException;
-import org.jbpm.services.task.exception.PermissionDeniedException;
-import org.kie.api.command.Command;
-import org.kie.api.runtime.KieSession;
-import org.kie.api.runtime.manager.Context;
-import org.kie.api.runtime.manager.RuntimeEngine;
-import org.kie.api.runtime.manager.RuntimeManager;
-import org.kie.api.task.TaskService;
-import org.kie.internal.runtime.manager.context.EmptyContext;
-import org.kie.internal.runtime.manager.context.ProcessInstanceIdContext;
-import org.kie.internal.task.api.InternalTaskService;
-import org.kie.services.client.serialization.jaxb.impl.JaxbExceptionResponse;
-import org.kie.services.remote.exception.DomainNotFoundBadRequestException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@ApplicationScoped
-public class ProcessRequestBean {
-
- private static final Logger logger = LoggerFactory.getLogger(ProcessRequestBean.class);
-
- @Inject
- private RuntimeManagerManager runtimeMgrMgr;
-
- @Inject
- private TaskService taskService;
-
- public Object doKieSessionOperation(Command> cmd, String deploymentId, Long processInstanceId) {
- Object result = null;
- try {
- KieSession kieSession = getRuntimeEngine(deploymentId, processInstanceId).getKieSession();
- result = kieSession.execute(cmd);
- } catch( Exception e ) {
- JaxbExceptionResponse exceptResp = new JaxbExceptionResponse(e, cmd);
- logger.warn( "Unable to execute " + exceptResp.getCommandName() + " because of " + e.getClass().getSimpleName() + ": " + e.getMessage());
- logger.trace("Stack trace: \n", e);
- result = exceptResp;
- }
- return result;
- }
-
- public Object doTaskOperation(Command> cmd) {
- Object result = null;
- try {
- result = ((InternalTaskService) taskService).execute(cmd);
- } catch( PermissionDeniedException pde ) {
- throw new UnauthorizedException(pde.getMessage(), pde);
- } catch( Exception e ) {
- JaxbExceptionResponse exceptResp = new JaxbExceptionResponse(e, cmd);
- logger.warn( "Unable to execute " + exceptResp.getCommandName() + " because of " + e.getClass().getSimpleName() + ": " + e.getMessage());
- logger.trace("Stack trace: \n", e);
- result = exceptResp;
- }
- return result;
- }
-
- protected RuntimeEngine getRuntimeEngine(String domainName, Long processInstanceId) {
- RuntimeManager runtimeManager = runtimeMgrMgr.getRuntimeManager(domainName);
- Context> runtimeContext;
- if (processInstanceId != null) {
- runtimeContext = new ProcessInstanceIdContext(processInstanceId);
- } else {
- runtimeContext = EmptyContext.get();
- }
- if( runtimeManager == null ) {
- throw new DomainNotFoundBadRequestException("No runtime manager could be found for domain '" + domainName + "'.");
- }
- return runtimeManager.getRuntimeEngine(runtimeContext);
- }
-
-}
diff --git a/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/jms/RequestMessageBean.java b/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/jms/RequestMessageBean.java
index 864c7c7a4d..9ecf2ff48d 100644
--- a/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/jms/RequestMessageBean.java
+++ b/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/jms/RequestMessageBean.java
@@ -24,19 +24,29 @@
import org.jbpm.services.task.commands.TaskCommand;
import org.jbpm.services.task.exception.PermissionDeniedException;
import org.kie.api.command.Command;
+import org.kie.api.runtime.KieSession;
+import org.kie.api.runtime.manager.Context;
+import org.kie.api.runtime.manager.RuntimeEngine;
+import org.kie.api.runtime.manager.RuntimeManager;
+import org.kie.api.task.TaskService;
+import org.kie.internal.runtime.manager.context.EmptyContext;
+import org.kie.internal.runtime.manager.context.ProcessInstanceIdContext;
+import org.kie.internal.task.api.InternalTaskService;
import org.kie.services.client.api.command.AcceptedCommands;
import org.kie.services.client.serialization.jaxb.JaxbSerializationProvider;
import org.kie.services.client.serialization.jaxb.impl.JaxbCommandsRequest;
import org.kie.services.client.serialization.jaxb.impl.JaxbCommandsResponse;
-import org.kie.services.remote.cdi.ProcessRequestBean;
+import org.kie.services.client.serialization.jaxb.impl.JaxbExceptionResponse;
+import org.kie.services.remote.cdi.RuntimeManagerManager;
import org.kie.services.remote.exception.DomainNotFoundBadRequestException;
import org.kie.services.remote.exception.KieRemoteServicesInternalError;
+import org.kie.services.remote.rest.RestProcessRequestBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class is the link between incoming request (whether via REST or JMS or .. whatever)
- * and the bean that processes the requests, the {@link ProcessRequestBean}.
+ * and the bean that processes the requests, the {@link RestProcessRequestBean}.
*
* Responses to requests are not placed on the reply-to queue, but on the answer queue.
* Because there are multiple queues to which an instance of this class could listen to, the (JMS queue) configuration is
@@ -49,12 +59,15 @@ public class RequestMessageBean implements MessageListener {
@Resource(mappedName = "java:/ConnectionFactory")
private ConnectionFactory connectionFactory;
- @Inject
- private ProcessRequestBean processRequestBean;
-
private String RESPONSE_QUEUE_NAME = null;
private static String RESPONSE_QUEUE_NAME_PROPERTY = "kie.services.jms.queues.response";
+ @Inject
+ private RuntimeManagerManager runtimeMgrMgr;
+
+ @Inject
+ private TaskService taskService;
+
@PostConstruct
public void init() {
RESPONSE_QUEUE_NAME = System.getProperty(RESPONSE_QUEUE_NAME_PROPERTY, "queue/KIE.RESPONSE.ALL");
@@ -81,7 +94,7 @@ public void onMessage(Message message) {
// 2. process request
JaxbCommandsResponse jaxbResponse;
if (cmdsRequest != null) {
- jaxbResponse = processJaxbCommandsRequest(cmdsRequest, processRequestBean);
+ jaxbResponse = processJaxbCommandsRequest(cmdsRequest);
} else {
// Failure reasons have been logged in deserializeRequest().
logger.error("Stopping processing of request message due to errors: see above.");
@@ -190,7 +203,7 @@ private Message serializeResponse(Session session, String msgId, int serializati
return byteMsg;
}
- public JaxbCommandsResponse processJaxbCommandsRequest(JaxbCommandsRequest request, ProcessRequestBean requestBean) {
+ public JaxbCommandsResponse processJaxbCommandsRequest(JaxbCommandsRequest request) {
// If exceptions are happening here, then there is something REALLY wrong and they should be thrown.
JaxbCommandsResponse jaxbResponse = new JaxbCommandsResponse(request);
List> commands = request.getCommands();
@@ -207,9 +220,9 @@ public JaxbCommandsResponse processJaxbCommandsRequest(JaxbCommandsRequest reque
Object cmdResult = null;
if (cmd instanceof TaskCommand>) {
- cmdResult = internalDoTaskOperation(requestBean, cmd, jaxbResponse, i);
+ cmdResult = internalDoTaskOperation(cmd, jaxbResponse, i);
} else {
- cmdResult = internalDoKieSessionOperation(requestBean, cmd, request, jaxbResponse, i);
+ cmdResult = internalDoKieSessionOperation( cmd, request, jaxbResponse, i);
}
if (cmdResult != null) {
try {
@@ -232,10 +245,10 @@ public JaxbCommandsResponse processJaxbCommandsRequest(JaxbCommandsRequest reque
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
- public Object internalDoTaskOperation(ProcessRequestBean requestBean, Command> cmd, JaxbCommandsResponse jaxbResponse, int i) {
+ public Object internalDoTaskOperation(Command> cmd, JaxbCommandsResponse jaxbResponse, int i) {
Object cmdResult;
try {
- cmdResult = requestBean.doTaskOperation(cmd);
+ cmdResult = doTaskOperation(cmd);
} catch( UnauthorizedException ue ) {
Throwable cause = ue.getCause();
if( cause instanceof PermissionDeniedException ) {
@@ -250,10 +263,10 @@ public Object internalDoTaskOperation(ProcessRequestBean requestBean, Command>
}
@TransactionAttribute(TransactionAttributeType.NEVER)
- public Object internalDoKieSessionOperation(ProcessRequestBean requestBean, Command> cmd, JaxbCommandsRequest request, JaxbCommandsResponse jaxbResponse, int i) {
+ public Object internalDoKieSessionOperation(Command> cmd, JaxbCommandsRequest request, JaxbCommandsResponse jaxbResponse, int i) {
Object cmdResult;
try {
- cmdResult = requestBean.doKieSessionOperation(cmd, request.getDeploymentId(), request.getProcessInstanceId());
+ cmdResult = doKieSessionOperation(cmd, request.getDeploymentId(), request.getProcessInstanceId());
} catch( DomainNotFoundBadRequestException dnfbre ) {
logger.warn( dnfbre.getMessage() );
jaxbResponse.addException(dnfbre, i, cmd);
@@ -261,4 +274,47 @@ public Object internalDoKieSessionOperation(ProcessRequestBean requestBean, Comm
}
return cmdResult;
}
+
+ private Object doKieSessionOperation(Command> cmd, String deploymentId, Long processInstanceId) {
+ Object result = null;
+ try {
+ KieSession kieSession = getRuntimeEngine(deploymentId, processInstanceId).getKieSession();
+ result = kieSession.execute(cmd);
+ } catch( Exception e ) {
+ JaxbExceptionResponse exceptResp = new JaxbExceptionResponse(e, cmd);
+ logger.warn( "Unable to execute " + exceptResp.getCommandName() + " because of " + e.getClass().getSimpleName() + ": " + e.getMessage());
+ logger.trace("Stack trace: \n", e);
+ result = exceptResp;
+ }
+ return result;
+ }
+
+ private Object doTaskOperation(Command> cmd) {
+ Object result = null;
+ try {
+ result = ((InternalTaskService) taskService).execute(cmd);
+ } catch( PermissionDeniedException pde ) {
+ throw new UnauthorizedException(pde.getMessage(), pde);
+ } catch( Exception e ) {
+ JaxbExceptionResponse exceptResp = new JaxbExceptionResponse(e, cmd);
+ logger.warn( "Unable to execute " + exceptResp.getCommandName() + " because of " + e.getClass().getSimpleName() + ": " + e.getMessage());
+ logger.trace("Stack trace: \n", e);
+ result = exceptResp;
+ }
+ return result;
+ }
+
+ protected RuntimeEngine getRuntimeEngine(String domainName, Long processInstanceId) {
+ RuntimeManager runtimeManager = runtimeMgrMgr.getRuntimeManager(domainName);
+ Context> runtimeContext;
+ if (processInstanceId != null) {
+ runtimeContext = new ProcessInstanceIdContext(processInstanceId);
+ } else {
+ runtimeContext = EmptyContext.get();
+ }
+ if( runtimeManager == null ) {
+ throw new DomainNotFoundBadRequestException("No runtime manager could be found for domain '" + domainName + "'.");
+ }
+ return runtimeManager.getRuntimeEngine(runtimeContext);
+ }
}
diff --git a/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/ResourceBase.java b/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/ResourceBase.java
index 3d3622531e..430f6f42fe 100644
--- a/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/ResourceBase.java
+++ b/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/ResourceBase.java
@@ -14,22 +14,114 @@
import javax.ws.rs.core.Variant;
import org.jboss.resteasy.spi.BadRequestException;
+import org.jboss.resteasy.spi.NotAcceptableException;
+import org.jboss.resteasy.spi.NotFoundException;
+import org.jbpm.services.task.commands.CompleteTaskCommand;
+import org.jbpm.services.task.commands.ExitTaskCommand;
+import org.jbpm.services.task.commands.FailTaskCommand;
+import org.jbpm.services.task.commands.GetTaskCommand;
+import org.jbpm.services.task.commands.SkipTaskCommand;
+import org.jbpm.services.task.commands.TaskCommand;
import org.jbpm.services.task.impl.model.GroupImpl;
import org.jbpm.services.task.impl.model.TaskImpl;
import org.jbpm.services.task.impl.model.UserImpl;
import org.jbpm.services.task.query.TaskSummaryImpl;
+import org.kie.api.command.Command;
import org.kie.api.task.model.OrganizationalEntity;
import org.kie.api.task.model.Status;
+import org.kie.api.task.model.Task;
+import org.kie.services.client.api.command.AcceptedCommands;
+import org.kie.services.client.serialization.jaxb.impl.JaxbCommandsRequest;
+import org.kie.services.client.serialization.jaxb.impl.JaxbCommandsResponse;
+import org.kie.services.client.serialization.jaxb.impl.JaxbExceptionResponse;
+import org.kie.services.remote.cdi.RuntimeManagerManager;
+import org.kie.services.remote.exception.KieRemoteServicesInternalError;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
public class ResourceBase {
- private static List variants
+ private static final Logger logger = LoggerFactory.getLogger(ResourceBase.class);
+
+ // Seam-Transaction ----------------------------------------------------------------------------------------------------------
+
+ public static JaxbCommandsResponse restProcessJaxbCommandsRequest(JaxbCommandsRequest request, RestProcessRequestBean requestBean) {
+ // If exceptions are happening here, then there is something REALLY wrong and they should be thrown.
+ JaxbCommandsResponse jaxbResponse = new JaxbCommandsResponse(request);
+ List> commands = request.getCommands();
+
+ if (commands != null) {
+ int cmdListSize = commands.size();
+ for (int i = 0; i < cmdListSize; ++i) {
+ boolean restartTx = !( i == cmdListSize - 1 ); // restart tx for all cmds except the last one
+ Command> cmd = commands.get(i);
+ if (!AcceptedCommands.getSet().contains(cmd.getClass())) {
+ throw new NotAcceptableException("The execute REST operation does not accept " + cmd.getClass().getName() + " instances.");
+ }
+ logger.debug("Processing command " + cmd.getClass().getSimpleName());
+ Object cmdResult = null;
+ try {
+ if (cmd instanceof TaskCommand>) {
+ String errorMsg = "Unable to execute command " + cmd.getClass().getSimpleName();
+ TaskCommand> taskCmd = (TaskCommand>) cmd;
+ if( cmd instanceof CompleteTaskCommand
+ || cmd instanceof ExitTaskCommand
+ || cmd instanceof FailTaskCommand
+ || cmd instanceof SkipTaskCommand ) {
+ cmdResult = requestBean.doTaskOperationOnDeployment(
+ taskCmd,
+ errorMsg,
+ request.getDeploymentId(),
+ restartTx); // restart commit
+ } else {
+ cmdResult = requestBean.doTaskOperation(taskCmd, errorMsg);
+ }
+ } else {
+ cmdResult = requestBean.doKieSessionOperation(
+ cmd,
+ request.getDeploymentId(),
+ request.getProcessInstanceId(),
+ "Unable to execute command " + cmd.getClass().getSimpleName(),
+ true, // commit
+ restartTx); // restart commit
+ }
+ } catch(Exception e) {
+ jaxbResponse.addException(e, i, cmd);
+ logger.warn("Unable to execute " + cmd.getClass().getSimpleName()
+ + " because of " + e.getClass().getSimpleName() + ": " + e.getMessage());
+ logger.trace("Stack trace: \n", e);
+ }
+ if (cmdResult != null) {
+ try {
+ // addResult could possibly throw an exception, which is why it's here and not above
+ jaxbResponse.addResult(cmdResult, i, cmd);
+ } catch (Exception e) {
+ logger.error("Unable to add result from " + cmd.getClass().getSimpleName() + "/" + i + " because of "
+ + e.getClass().getSimpleName(), e);
+ logger.trace("Stack trace: \n", e);
+ jaxbResponse.addException(e, i, cmd);
+ }
+ }
+ }
+ }
+
+ if (commands == null || commands.isEmpty()) {
+ logger.info("Commands request object with no commands sent!");
+ }
+
+ return jaxbResponse;
+ }
+
+ // JSON / JAXB ---------------------------------------------------------------------------------------------------------------
+
+ public static List variants
= Variant.mediaTypes(MediaType.APPLICATION_XML_TYPE, MediaType.APPLICATION_JSON_TYPE).build();
- protected Variant getVariant(Request restRequest) {
+ protected static Variant getVariant(Request restRequest) {
return restRequest.selectVariant(variants);
}
- protected Response createCorrectVariant(Object responseObj, Request restRequest) {
+ protected static Response createCorrectVariant(Object responseObj, Request restRequest) {
Variant v = getVariant(restRequest);
if( v != null ) {
return Response.ok(responseObj, v).build();
@@ -37,16 +129,9 @@ protected Response createCorrectVariant(Object responseObj, Request restRequest)
return Response.notAcceptable(variants).build();
}
}
-
- protected static String checkThatOperationExists(String operation, String[] possibleOperations) {
- for (String oper : possibleOperations) {
- if (oper.equals(operation.trim().toLowerCase())) {
- return oper;
- }
- }
- throw new BadRequestException("Operation '" + operation + "' is not supported on tasks.");
- }
+ // Request Params -------------------------------------------------------------------------------------------------------------
+
protected static Map> getRequestParams(HttpServletRequest request) {
Map> parameters = new HashMap>();
Enumeration names = request.getParameterNames();
@@ -231,6 +316,8 @@ protected static List convertStringListToStatusList( List status
return statusList;
}
+ // Pagination ----------------------------------------------------------------------------------------------------------------
+
protected static int [] getPageNumAndPageSize(Map> params) {
int [] pageInfo = new int[3];
Number page = getNumberParam("page", false, params, "query", false);
diff --git a/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/RestProcessRequestBean.java b/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/RestProcessRequestBean.java
new file mode 100644
index 0000000000..3c2d12eb99
--- /dev/null
+++ b/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/RestProcessRequestBean.java
@@ -0,0 +1,274 @@
+package org.kie.services.remote.rest;
+
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.event.Event;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+
+import org.jboss.resteasy.spi.InternalServerErrorException;
+import org.jboss.resteasy.spi.UnauthorizedException;
+import org.jboss.seam.transaction.DefaultTransaction;
+import org.jboss.seam.transaction.SeamTransaction;
+import org.jboss.solder.exception.control.ExceptionToCatch;
+import org.jbpm.services.task.commands.CompleteTaskCommand;
+import org.jbpm.services.task.commands.FailTaskCommand;
+import org.jbpm.services.task.commands.GetTaskCommand;
+import org.jbpm.services.task.commands.TaskCommand;
+import org.jbpm.services.task.exception.PermissionDeniedException;
+import org.kie.api.command.Command;
+import org.kie.api.runtime.KieSession;
+import org.kie.api.runtime.manager.Context;
+import org.kie.api.runtime.manager.RuntimeEngine;
+import org.kie.api.runtime.manager.RuntimeManager;
+import org.kie.api.task.TaskService;
+import org.kie.api.task.model.Task;
+import org.kie.internal.runtime.manager.context.EmptyContext;
+import org.kie.internal.runtime.manager.context.ProcessInstanceIdContext;
+import org.kie.internal.task.api.InternalTaskService;
+import org.kie.services.client.serialization.jaxb.impl.JaxbExceptionResponse;
+import org.kie.services.remote.cdi.RuntimeManagerManager;
+import org.kie.services.remote.exception.DomainNotFoundBadRequestException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class is used by both the {@link RuntimeResource} and {@link TaskResource} to do the core operations on
+ * the Deployment/Runtime's {@link KieSession} and {@link TaskService}.
+ *
+ * It contains the necessary logic to do the following:
+ *
+ * - Retrieve the KieSession or TaskService
+ * - Execute the submitted command
+ * - Call commit on the given {@link SeamTransaction} instance
+ *
+ * The commit on the {@link SeamTransaction} is necessary in order to avoid race-conditions
+ * involving the application scoped {@link EntityManager} used in the {@link KieSession}.
+ */
+@RequestScoped
+public class RestProcessRequestBean {
+
+ private static final Logger logger = LoggerFactory.getLogger(RestProcessRequestBean.class);
+
+ /* KIE processing */
+ @Inject
+ private RuntimeManagerManager runtimeMgrMgr;
+
+ @Inject
+ private TaskService taskService;
+
+ /* Transaction control */
+ @Inject
+ @DefaultTransaction
+ private SeamTransaction tx;
+
+ @Inject
+ Event txExceptionEvent;
+
+ /**
+ * Executes a command on the {@link KieSession} from the proper {@link RuntimeManager}. This method
+ * ends up synchronizing around the retrieved {@link KieSession} in order to avoid race-conditions.
+ *
+ * @param cmd The command to be executed.
+ * @param deploymentId The id of the runtime.
+ * @param processInstanceId The process instance id, if available.
+ * @param commit Whether or not to commit (the {@link SeamTransaction}) at after the {@link Command} has been completed.
+ * @return The result of the {@link Command}.
+ */
+ public Object doKieSessionOperation(Command> cmd, String deploymentId, Long processInstanceId, String errorMsg,
+ boolean commit, boolean restartTx) {
+ Object result = null;
+ try {
+ RuntimeEngine runtimeEngine = getRuntimeEngine(deploymentId, processInstanceId);
+ synchronized (runtimeEngine) {
+ KieSession kieSession = runtimeEngine.getKieSession();
+ try {
+ result = kieSession.execute(cmd);
+ } finally {
+ if (commit) {
+ commit(tx, txExceptionEvent, logger);
+ }
+ if(restartTx) {
+ start(tx, txExceptionEvent, logger);
+ }
+ }
+ }
+ } catch (Exception e) {
+ if( e instanceof RuntimeException ) {
+ throw (RuntimeException) e;
+ } else {
+ throw new InternalServerErrorException(errorMsg, e);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * A variant of the above method which always calls commit once the {@link Command} has completed.
+ *
+ * @param cmd The command to be executed.
+ * @param deploymentId The id of the runtime.
+ * @param processInstanceId The process id, if available.
+ * @return The result of the executed command.
+ */
+ public Object doKieSessionOperation(Command> cmd, String deploymentId, Long processInstanceId, String errorMsg) {
+ return doKieSessionOperation(cmd, deploymentId, processInstanceId, errorMsg, true);
+ }
+
+ /**
+ * A variant of the above method which commits but does not restart the {@link SeamTransaction} once the command has completed.
+ *
+ * @param cmd The command to be executed.
+ * @param deploymentId The id of the runtime.
+ * @param processInstanceId The process id, if available.
+ * @return The result of the executed command.
+ */
+ public Object doKieSessionOperation(Command> cmd, String deploymentId, Long processInstanceId, String errorMsg, boolean commit) {
+ return doKieSessionOperation(cmd, deploymentId, processInstanceId, errorMsg, commit, false);
+ }
+
+ /**
+ * Executes a command on the injected {@link TaskService} instance.
+ *
+ * Should be used only for commands that end up affecting the associated {@link KieSession}.
+ * Since the {@link CompleteTaskCommand} ends up signalling the {@link KieSession}, we make sure to
+ * first retrieve the proper {@link KieSession} in order to synchronize around it.
+ *
+ * @param cmd The command to be executed.
+ * @param errorMsg The message to be added to any (non-runtime) exceptions thrown.
+ * @param deploymentId The deployment id of the runtime.
+ * @return The result of the completed command.
+ */
+ public Object doTaskOperationOnDeployment(TaskCommand> cmd, String errorMsg, String deploymentId, boolean restartTx) {
+ Object result = null;
+ try {
+ if( deploymentId != null ) {
+ RuntimeEngine runtimeEngine = getRuntimeEngine(deploymentId, null);
+ synchronized (runtimeEngine) {
+ try {
+ ((InternalTaskService) taskService).execute(cmd);
+ } finally {
+ commit(tx, txExceptionEvent, logger);
+ if( restartTx ) {
+ start(tx, txExceptionEvent, logger);
+ }
+ }
+ }
+ } else {
+ result = ((InternalTaskService) taskService).execute(cmd);
+ }
+ } catch (PermissionDeniedException pde) {
+ throw new UnauthorizedException(pde.getMessage(), pde);
+ } catch (RuntimeException re) {
+ throw re;
+ } catch( Exception e ) {
+ throw new InternalServerErrorException(errorMsg, e);
+ }
+ return result;
+ }
+
+ /**
+ * Variant of the above method which does not restart the transaction.
+ * @param cmd The {@link Command} to be executed.
+ * @param errorMsg The error message for any exception thrown.
+ * @param deploymentId The deployment id.
+ * @return The result of the given {@link Command}.
+ */
+ public Object doTaskOperationOnDeployment(TaskCommand> cmd, String errorMsg, String deploymentId) {
+ return doTaskOperationOnDeployment(cmd, errorMsg, deploymentId, false);
+ }
+
+ /**
+ * Executes a command on the {@link TaskService} (without synchronizing around the {@link KieSession})
+ * @param cmd The command to be executed.
+ * @param errorMsg The error message to be attached to any exceptions thrown.
+ * @return The result of the completed command.
+ */
+ public Object doTaskOperation(TaskCommand> cmd, String errorMsg) {
+ return doTaskOperationOnDeployment(cmd, errorMsg, null);
+ }
+
+ /**
+ * Retrieve the relevant {@link RuntimeEngine} instance.
+ *
+ * @param deploymentId The id of the deployment for the {@link RuntimeEngine}.
+ * @param processInstanceId The process instance id, if available.
+ * @return The {@link RuntimeEngine} instance.
+ */
+ private RuntimeEngine getRuntimeEngine(String deploymentId, Long processInstanceId) {
+ RuntimeManager runtimeManager = runtimeMgrMgr.getRuntimeManager(deploymentId);
+ Context> runtimeContext;
+ if (processInstanceId != null) {
+ runtimeContext = new ProcessInstanceIdContext(processInstanceId);
+ } else {
+ runtimeContext = EmptyContext.get();
+ }
+ if (runtimeManager == null) {
+ throw new DomainNotFoundBadRequestException("No runtime manager could be found for deployment '" + deploymentId + "'.");
+ }
+ return runtimeManager.getRuntimeEngine(runtimeContext);
+ }
+
+ /**
+ * Commit the given {@link SeamTransaction}.
+ *
+ * @param tx The {@link SeamTransaction} instance.
+ * @param txExceptionEvent The CDI Event used in order to communicate with the seam-transaction framework.
+ * @param logger In order to log thrown exceptions.
+ */
+ private static void commit(SeamTransaction tx, Event txExceptionEvent, Logger logger) {
+ try {
+ switch (tx.getStatus()) {
+ case javax.transaction.Status.STATUS_ACTIVE:
+ tx.commit();
+ break;
+ case javax.transaction.Status.STATUS_MARKED_ROLLBACK:
+ case javax.transaction.Status.STATUS_PREPARED:
+ case javax.transaction.Status.STATUS_PREPARING:
+ tx.rollback();
+ break;
+ case javax.transaction.Status.STATUS_COMMITTED:
+ case javax.transaction.Status.STATUS_COMMITTING:
+ case javax.transaction.Status.STATUS_ROLLING_BACK:
+ case javax.transaction.Status.STATUS_UNKNOWN:
+ case javax.transaction.Status.STATUS_ROLLEDBACK:
+ case javax.transaction.Status.STATUS_NO_TRANSACTION:
+ break;
+ }
+ } catch (SystemException se) {
+ logger.warn("Error commiting/rolling back the transaction", se);
+ txExceptionEvent.fire(new ExceptionToCatch(se));
+ } catch (HeuristicRollbackException hre) {
+ logger.warn("Error committing the transaction", hre);
+ txExceptionEvent.fire(new ExceptionToCatch(hre));
+ } catch (RollbackException re) {
+ logger.warn("Error committing the transaction", re);
+ txExceptionEvent.fire(new ExceptionToCatch(re));
+ } catch (HeuristicMixedException hme) {
+ logger.warn("Error committing the transaction", hme);
+ txExceptionEvent.fire(new ExceptionToCatch(hme));
+ }
+ }
+
+ private static void start(SeamTransaction tx, Event txExceptionEvent, Logger logger) {
+ try {
+ if (tx.getStatus() == Status.STATUS_ACTIVE) {
+ logger.warn("Transaction was already started before the listener");
+ } else {
+ logger.debug("Beginning transaction");
+ tx.begin();
+ }
+ } catch (SystemException se) {
+ logger.warn("Error starting the transaction, or checking status", se);
+ txExceptionEvent.fire(new ExceptionToCatch(se));
+ } catch (NotSupportedException e) {
+ logger.warn("Error starting the transaction", e);
+ txExceptionEvent.fire(new ExceptionToCatch(e));
+ }
+ }
+}
diff --git a/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/RuntimeResource.java b/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/RuntimeResource.java
index 0d2abcbd66..30f8626301 100644
--- a/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/RuntimeResource.java
+++ b/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/RuntimeResource.java
@@ -1,7 +1,5 @@
package org.kie.services.remote.rest;
-import static org.kie.services.remote.util.CommandsRequestUtil.restProcessJaxbCommandsRequest;
-
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -9,6 +7,7 @@
import java.util.Map.Entry;
import javax.enterprise.context.RequestScoped;
+import javax.enterprise.event.Event;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
@@ -32,7 +31,10 @@
import org.drools.core.process.instance.WorkItem;
import org.jboss.resteasy.spi.BadRequestException;
import org.jboss.resteasy.spi.InternalServerErrorException;
-import org.jboss.resteasy.spi.UnsupportedMediaTypeException;
+import org.jboss.resteasy.spi.NotAcceptableException;
+import org.jboss.seam.transaction.DefaultTransaction;
+import org.jboss.seam.transaction.SeamTransaction;
+import org.jboss.solder.exception.control.ExceptionToCatch;
import org.jbpm.process.audit.NodeInstanceLog;
import org.jbpm.process.audit.ProcessInstanceLog;
import org.jbpm.process.audit.VariableInstanceLog;
@@ -42,8 +44,11 @@
import org.jbpm.process.audit.command.FindProcessInstancesCommand;
import org.jbpm.process.audit.command.FindSubProcessInstancesCommand;
import org.jbpm.process.audit.command.FindVariableInstancesCommand;
+import org.jbpm.process.audit.event.AuditEvent;
+import org.jbpm.services.task.commands.TaskCommand;
import org.kie.api.command.Command;
import org.kie.api.runtime.process.ProcessInstance;
+import org.kie.services.client.api.command.AcceptedCommands;
import org.kie.services.client.serialization.jaxb.impl.JaxbCommandsRequest;
import org.kie.services.client.serialization.jaxb.impl.JaxbCommandsResponse;
import org.kie.services.client.serialization.jaxb.impl.JaxbExceptionResponse;
@@ -53,26 +58,33 @@
import org.kie.services.client.serialization.jaxb.impl.process.JaxbProcessInstanceWithVariablesResponse;
import org.kie.services.client.serialization.jaxb.impl.process.JaxbWorkItem;
import org.kie.services.client.serialization.jaxb.rest.JaxbGenericResponse;
-import org.kie.services.remote.cdi.ProcessRequestBean;
+import org.kie.services.remote.exception.KieRemoteServicesInternalError;
+import org.kie.services.remote.exception.KieRemoteServicesPreConditionException;
import org.kie.services.remote.util.Paginator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
@Path("/runtime/{id: [a-zA-Z0-9-:\\.]+}")
@RequestScoped
@SuppressWarnings("unchecked")
public class RuntimeResource extends ResourceBase {
- @Inject
- private ProcessRequestBean processRequestBean;
-
- @PathParam("id")
- private String deploymentId;
+ private static final Logger logger = LoggerFactory.getLogger(RuntimeResource.class);
+ /* REST information */
@Context
private HttpServletRequest request;
@Context
private Request restRequest;
+ /* KIE information and processing */
+ @Inject
+ private RestProcessRequestBean processRequestBean;
+
+ @PathParam("id")
+ private String deploymentId;
+
// Rest methods --------------------------------------------------------------------------------------------------------------
@POST
@@ -81,7 +93,7 @@ public class RuntimeResource extends ResourceBase {
@Path("/execute")
public JaxbCommandsResponse execute(JaxbCommandsRequest cmdsRequest) {
return restProcessJaxbCommandsRequest(cmdsRequest, processRequestBean);
- }
+ }
@POST
@Path("/process/{processDefId: [_a-zA-Z0-9-:\\.]+}/start")
@@ -90,7 +102,13 @@ public Response startNewProcess(@PathParam("processDefId") String processId) {
Map params = extractMapFromParams(formParams, "process/" + processId + "/start");
Command> cmd = new StartProcessCommand(processId, params);
- Object result = internalDoKieSessionOperation(cmd, "Unable to start process with process definition id '" + processId + "'");
+ Object result = processRequestBean.doKieSessionOperation(
+ cmd,
+ deploymentId,
+ (Long) getNumberParam("processInstanceId", false, formParams, "process/"+ processId+"/start", true),
+ "Unable to start process with process definition id '" + processId + "'",
+ true);
+
JaxbProcessInstanceResponse responseObj = new JaxbProcessInstanceResponse((ProcessInstance) result, request);
return createCorrectVariant(responseObj, restRequest);
}
@@ -101,7 +119,13 @@ public Response getProcessInstanceDetails(@PathParam("procInstId") Long procInst
Command> cmd = new GetProcessInstanceCommand(procInstId);
((GetProcessInstanceCommand) cmd).setReadOnly(true);
- Object result = internalDoKieSessionOperation(cmd, "Unable to get process instance " + procInstId);
+ Object result = processRequestBean.doKieSessionOperation(
+ cmd,
+ deploymentId,
+ procInstId,
+ "Unable to get process instance " + procInstId,
+ true);
+
Object responseObj = null;
if (result != null) {
responseObj = new JaxbProcessInstanceResponse((ProcessInstance) result);
@@ -117,7 +141,14 @@ public Response getProcessInstanceDetails(@PathParam("procInstId") Long procInst
public Response abortProcessInstance(@PathParam("procInstId") Long procInstId) {
Command> cmd = new AbortProcessInstanceCommand();
((AbortProcessInstanceCommand) cmd).setProcessInstanceId(procInstId);
- internalDoKieSessionOperation(cmd, "Unable to abort process instance " + procInstId);
+
+ processRequestBean.doKieSessionOperation(
+ cmd,
+ deploymentId,
+ procInstId,
+ "Unable to abort process instance " + procInstId,
+ true);
+
return createCorrectVariant(new JaxbGenericResponse(request), restRequest);
}
@@ -138,14 +169,15 @@ public Response signalProcessInstance(@PathParam("procInstId") Long procInstId)
if( event != null ) {
errorMsg += " and event '" + event + "'";
}
- internalDoKieSessionOperation(cmd, errorMsg);
+
+ processRequestBean.doKieSessionOperation(cmd, deploymentId, procInstId, errorMsg, true);
return createCorrectVariant(new JaxbGenericResponse(request), restRequest);
}
@GET
@Path("/process/instance/{procInstId: [0-9]+}/variables")
public Response getProcessInstanceVariables(@PathParam("procInstId") Long procInstId) {
- Map vars = getVariables(procInstId);
+ Map vars = getVariables(procInstId, true);
return createCorrectVariant(new JaxbVariablesResponse(vars, request), restRequest);
}
@@ -155,20 +187,29 @@ public Response signalEvent() {
Map> formParams = getRequestParams(request);
String eventType = getStringParam("signal", true, formParams, "signal");
Object event = getObjectParam("event", false, formParams, "signal");
- Command> cmd = new SignalEventCommand(eventType, event);
String errorMsg = "Unable to send signal '" + eventType + "'";
if( event != null ) {
errorMsg += " with event '" + event + "'";
}
- internalDoKieSessionOperation(cmd, errorMsg);
+
+ processRequestBean.doKieSessionOperation(
+ new SignalEventCommand(eventType, event),
+ deploymentId,
+ (Long) getNumberParam("processInstanceId", false, formParams, "signal", true),
+ errorMsg,
+ true);
return createCorrectVariant(new JaxbGenericResponse(request), restRequest);
}
@GET
@Path("/workitem/{workItemId: [0-9-]+}")
public Response getWorkItem(@PathParam("workItemId") Long workItemId) {
- Command> cmd = new GetWorkItemCommand(workItemId);
- WorkItem workItem = (WorkItem) internalDoKieSessionOperation(cmd, "Unable to get work item " + workItemId );
+ WorkItem workItem = (WorkItem) processRequestBean.doKieSessionOperation(
+ new GetWorkItemCommand(workItemId),
+ deploymentId,
+ (Long) getNumberParam("processInstanceId", false, getRequestParams(request), "workitem/" + workItemId, true),
+ "Unable to get work item " + workItemId,
+ true);
return createCorrectVariant(new JaxbWorkItem(workItem), restRequest);
}
@@ -185,7 +226,13 @@ public Response doWorkItemOperation(@PathParam("workItemId") Long workItemId, @P
} else {
throw new BadRequestException("Unsupported operation: /process/instance/" + workItemId + "/" + operation);
}
- internalDoKieSessionOperation(cmd, "Unable to " + operation + " workitem " + workItemId );
+
+ processRequestBean.doKieSessionOperation(
+ cmd,
+ deploymentId,
+ (Long) getNumberParam("processInstanceId", false, params, "workitem/" + workItemId + "/" + operation, true),
+ "Unable to " + operation + " work item " + workItemId,
+ true);
return createCorrectVariant(new JaxbGenericResponse(request), restRequest);
}
@@ -196,8 +243,12 @@ public Response doWorkItemOperation(@PathParam("workItemId") Long workItemId, @P
@POST
@Path("/history/clear")
public Response clearProcessInstanceLogs() {
- Command> cmd = new ClearHistoryLogsCommand();
- internalDoKieSessionOperation(cmd, "Unable to clear process instance logs");
+ processRequestBean.doKieSessionOperation(
+ new ClearHistoryLogsCommand(),
+ deploymentId,
+ (Long) getNumberParam("processInstanceId", false, getRequestParams(request), "history/clear", true),
+ "Unable to clear process instance logs",
+ true);
return createCorrectVariant(new JaxbGenericResponse(request), restRequest);
}
@@ -207,8 +258,12 @@ public Response getProcessInstanceLogs() {
Map> params = getRequestParams(request);
int [] pageInfo = getPageNumAndPageSize(params);
- Command> cmd = new FindProcessInstancesCommand();
- Object result = internalDoKieSessionOperation(cmd, "Unable to get process instance logs");
+ Object result = processRequestBean.doKieSessionOperation(
+ new FindProcessInstancesCommand(),
+ deploymentId,
+ (Long) getNumberParam("processInstanceId", false, params, "history/clear", true),
+ "Unable to get process instance logs",
+ true);
List results = (List) result;
results = (new Paginator()).paginate(pageInfo, results);
@@ -221,8 +276,12 @@ public Response getSpecificProcessInstanceLogs(@PathParam("procInstId") long pro
Map> params = getRequestParams(request);
int [] pageInfo = getPageNumAndPageSize(params);
- Command> cmd = new FindProcessInstanceCommand(procInstId);
- Object result = internalDoKieSessionOperation(cmd, "Unable to get process instance logs for process instance " + procInstId);
+ Object result = processRequestBean.doKieSessionOperation(
+ new FindProcessInstanceCommand(procInstId),
+ deploymentId,
+ procInstId,
+ "Unable to get process instance logs for process instance " + procInstId,
+ true);
ProcessInstanceLog procInstLog = (ProcessInstanceLog) result;
List logList = new ArrayList();
@@ -234,34 +293,29 @@ public Response getSpecificProcessInstanceLogs(@PathParam("procInstId") long pro
@GET
@Path("/history/instance/{procInstId: [0-9]+}/{oper: [a-zA-Z]+}")
- public Response getVariableOrNodeHistoryList(@PathParam("procInstId") Long procInstId,
- @PathParam("oper") String operation) {
+ public Response getVariableOrNodeHistoryList(@PathParam("procInstId") Long procInstId, @PathParam("oper") String operation) {
Map> params = getRequestParams(request);
int [] pageInfo = getPageNumAndPageSize(params);
- JaxbHistoryLogList resultList;
Command> cmd;
+ String errorMsg;
if ("child".equalsIgnoreCase(operation)) {
cmd = new FindSubProcessInstancesCommand(procInstId);
- Object result = internalDoKieSessionOperation(cmd, "Unable to get child process instance logs for process instance " + procInstId);
- List procInstLogList = (List) result;
- procInstLogList = (new Paginator()).paginate(pageInfo, procInstLogList);
- resultList = new JaxbHistoryLogList(procInstLogList);
+ errorMsg = "Unable to get child process instance logs for process instance " + procInstId;
} else if ("node".equalsIgnoreCase(operation)) {
cmd = new FindNodeInstancesCommand(procInstId);
- Object result = internalDoKieSessionOperation(cmd, "Unable to get node instance logs for process instance " + procInstId);
- List nodeInstLogList = (List) result;
- nodeInstLogList = (new Paginator()).paginate(pageInfo, nodeInstLogList);
- resultList = new JaxbHistoryLogList(nodeInstLogList);
+ errorMsg = "Unable to get node instance logs for process instance " + procInstId;
} else if ("variable".equalsIgnoreCase(operation)) {
cmd = new FindVariableInstancesCommand(procInstId);
- Object result = internalDoKieSessionOperation(cmd, "Unable to get variable instance logs for process instance " + procInstId);
- List varInstLogList = (List) result;
- varInstLogList = (new Paginator()).paginate(pageInfo, varInstLogList);
- resultList = new JaxbHistoryLogList(varInstLogList);
+ errorMsg = "Unable to get variable instance logs for process instance " + procInstId;
} else {
throw new BadRequestException("Unsupported operation: /history/instance/" + procInstId + "/" + operation);
}
+
+ Object result = processRequestBean.doKieSessionOperation(cmd, deploymentId, procInstId, errorMsg, true);
+ List varInstLogList = (List) result;
+ varInstLogList = (new Paginator()).paginate(pageInfo, varInstLogList);
+ JaxbHistoryLogList resultList = new JaxbHistoryLogList(varInstLogList);
return createCorrectVariant(resultList, restRequest);
}
@@ -272,24 +326,23 @@ public Response getSpecificVariableOrNodeHistoryList(@PathParam("procInstId") Lo
Map> params = getRequestParams(request);
int [] pageInfo = getPageNumAndPageSize(params);
- JaxbHistoryLogList resultList;
Command> cmd;
+ String errorMsg;
if ("node".equalsIgnoreCase(operation)) {
cmd = new FindNodeInstancesCommand(procInstId, logId);
- Object result = internalDoKieSessionOperation(cmd, "Unable to get node instance logs for node '" + logId + "' in process instance " + procInstId);
- List nodeInstLogList = (List) result;
- nodeInstLogList = (new Paginator()).paginate(pageInfo, nodeInstLogList);
- resultList = new JaxbHistoryLogList(nodeInstLogList);
+ errorMsg ="Unable to get node instance logs for node '" + logId + "' in process instance " + procInstId;
} else if ("variable".equalsIgnoreCase(operation)) {
cmd = new FindVariableInstancesCommand(procInstId, logId);
- Object result = internalDoKieSessionOperation(cmd, "Unable to get variable instance logs for variable '" + logId + "' in process instance " + procInstId);
- List varInstLogList = (List) result;
- varInstLogList = (new Paginator()).paginate(pageInfo, varInstLogList);
- resultList = new JaxbHistoryLogList(varInstLogList);
+ errorMsg = "Unable to get variable instance logs for variable '" + logId + "' in process instance " + procInstId;
} else {
throw new BadRequestException("Unsupported operation: /history/instance/" + procInstId + "/" + operation + "/"
+ logId);
}
+
+ Object result = processRequestBean.doKieSessionOperation(cmd, deploymentId, procInstId, errorMsg, true);
+ List varInstLogList = (List) result;
+ varInstLogList = (new Paginator()).paginate(pageInfo, varInstLogList);
+ JaxbHistoryLogList resultList = new JaxbHistoryLogList(varInstLogList);
return createCorrectVariant(resultList, restRequest);
}
@@ -299,8 +352,12 @@ public Response getProcessInstanceLogs(@PathParam("procId") String processId) {
Map> params = getRequestParams(request);
int [] pageInfo = getPageNumAndPageSize(params);
- Command> cmd = new FindProcessInstancesCommand(processId);
- Object result = internalDoKieSessionOperation(cmd, "Unable to get process instance logs for process '" + processId + "'");
+ Object result = processRequestBean.doKieSessionOperation(
+ new FindProcessInstancesCommand(processId),
+ deploymentId,
+ (Long) getNumberParam("processInstanceId", false, params, "history/process/" + processId, true),
+ "Unable to get process instance logs for process '" + processId + "'",
+ true);
List procInstLogList = (List) result;
procInstLogList = (new Paginator()).paginate(pageInfo, procInstLogList);
@@ -316,12 +373,17 @@ public Response getProcessInstanceLogs(@PathParam("procId") String processId) {
public Response startNewProcessWithVars(@PathParam("processDefId") String processId) {
Map> formParams = getRequestParams(request);
Map params = extractMapFromParams(formParams, "process/" + processId + "/start");
- Command> cmd = new StartProcessCommand(processId, params);
- Object result = internalDoKieSessionOperation(cmd, "Unable to get process instance logs for process '" + processId + "'");
+ Object result = processRequestBean.doKieSessionOperation(
+ new StartProcessCommand(processId, params),
+ deploymentId,
+ (Long) getNumberParam("processInstanceId", false, formParams, "withvars/process/" + processId + "/start", true),
+ "Unable to get process instance logs for process '" + processId + "'",
+ false);
+
ProcessInstance procInst = (ProcessInstance) result;
- Map vars = getVariables(procInst.getId());
+ Map vars = getVariables(procInst.getId(), true);
JaxbProcessInstanceWithVariablesResponse resp = new JaxbProcessInstanceWithVariablesResponse(procInst, vars, request);
return createCorrectVariant(resp, restRequest);
@@ -332,11 +394,18 @@ public Response startNewProcessWithVars(@PathParam("processDefId") String proces
public Response getProcessInstanceWithVars(@PathParam("procInstId") Long procInstId) {
Command> cmd = new GetProcessInstanceCommand(procInstId);
((GetProcessInstanceCommand) cmd).setReadOnly(true);
+
+ Object result = processRequestBean.doKieSessionOperation(
+ cmd,
+ deploymentId,
+ procInstId,
+ "Unable to get process instance " + procInstId,
+ false);
+
JaxbProcessInstanceWithVariablesResponse responseObj = null;
- Object result = internalDoKieSessionOperation(cmd, "Unable to get process instance " + procInstId);
if (result != null) {
ProcessInstance procInst = (ProcessInstance) result;
- Map vars = getVariables(procInstId);
+ Map vars = getVariables(procInstId, true);
responseObj = new JaxbProcessInstanceWithVariablesResponse(procInst, vars, request);
} else {
throw new BadRequestException("Unable to retrieve process instance " + procInstId
@@ -351,7 +420,6 @@ public Response signalProcessInstanceWithVars(@PathParam("procInstId") Long proc
Map> params = getRequestParams(request);
String eventType = getStringParam("eventType", true, params, "signal");
Object event = getObjectParam("event", false, params, "signal");
- Command> cmd = new SignalEventCommand(procInstId, eventType, event);
String errorMsg = "Unable to signal process instance " + procInstId;
if( eventType == null ) {
errorMsg += " with empty signal";
@@ -361,14 +429,27 @@ public Response signalProcessInstanceWithVars(@PathParam("procInstId") Long proc
if( event != null ) {
errorMsg += " and event '" + event + "'";
}
- internalDoKieSessionOperation(cmd, errorMsg);
- cmd = new GetProcessInstanceCommand(procInstId);
+ processRequestBean.doKieSessionOperation(
+ new SignalEventCommand(procInstId, eventType, event),
+ deploymentId,
+ procInstId,
+ errorMsg,
+ false);
+
+ Command> cmd = new GetProcessInstanceCommand(procInstId);
((GetProcessInstanceCommand) cmd).setReadOnly(true);
- Object result = internalDoKieSessionOperation(cmd, "Unable to get process instance " + procInstId);
+ Object result = processRequestBean.doKieSessionOperation(
+ cmd,
+ deploymentId,
+ procInstId,
+ "Unable to get process instance " + procInstId,
+ false);
ProcessInstance processInstance = (ProcessInstance) result;
-
- Map vars = getVariables(processInstance.getId());
+ if( processInstance == null ) {
+ throw new KieRemoteServicesPreConditionException("This method can only be used on processes that will not complete after a signal.");
+ }
+ Map vars = getVariables(processInstance.getId(), true);
return createCorrectVariant(new JaxbProcessInstanceWithVariablesResponse(processInstance, vars),
restRequest);
@@ -376,23 +457,13 @@ public Response signalProcessInstanceWithVars(@PathParam("procInstId") Long proc
// Helper methods --------------------------------------------------------------------------------------------------------------
- private Object internalDoKieSessionOperation(Command> cmd, String errorMsg) {
- Object result = processRequestBean.doKieSessionOperation(cmd, deploymentId, null);
- if( result instanceof JaxbExceptionResponse ) {
- Exception e = ((JaxbExceptionResponse) result).getCause();
- if( e instanceof RuntimeException ) {
- throw (RuntimeException) e;
- } else {
- throw new InternalServerErrorException(errorMsg, e);
- }
- }
- return result;
- }
-
- private Map getVariables(long processInstanceId) {
- Command> cmd = new FindVariableInstancesCommand(processInstanceId);
-
- Object result = internalDoKieSessionOperation(cmd, "Unable to retrieve process variables from process instance " + processInstanceId);
+ private Map getVariables(long processInstanceId, boolean lastOperation) {
+ Object result = processRequestBean.doKieSessionOperation(
+ new FindVariableInstancesCommand(processInstanceId),
+ deploymentId,
+ processInstanceId,
+ "Unable to retrieve process variables from process instance " + processInstanceId,
+ lastOperation);
List varInstLogList = (List) result;
Map vars = new HashMap();
@@ -417,4 +488,6 @@ private Map getVariables(long processInstanceId) {
return vars;
}
+
+
}
diff --git a/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/TaskResource.java b/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/TaskResource.java
index 0a9006126a..53758309c0 100644
--- a/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/TaskResource.java
+++ b/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/TaskResource.java
@@ -1,7 +1,5 @@
package org.kie.services.remote.rest;
-import static org.kie.services.remote.util.CommandsRequestUtil.restProcessJaxbCommandsRequest;
-
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
@@ -26,7 +24,6 @@
import javax.ws.rs.core.UriInfo;
import org.jboss.resteasy.spi.BadRequestException;
-import org.jboss.resteasy.spi.InternalServerErrorException;
import org.jboss.resteasy.spi.NotFoundException;
import org.jbpm.kie.services.api.IdentityProvider;
import org.jbpm.services.task.commands.*;
@@ -42,10 +39,9 @@
import org.kie.api.task.model.TaskSummary;
import org.kie.services.client.serialization.jaxb.impl.JaxbCommandsRequest;
import org.kie.services.client.serialization.jaxb.impl.JaxbCommandsResponse;
-import org.kie.services.client.serialization.jaxb.impl.JaxbExceptionResponse;
import org.kie.services.client.serialization.jaxb.impl.task.JaxbTaskSummaryListResponse;
import org.kie.services.client.serialization.jaxb.rest.JaxbGenericResponse;
-import org.kie.services.remote.cdi.ProcessRequestBean;
+import org.kie.services.remote.exception.KieRemoteServicesInternalError;
import org.kie.services.remote.util.Paginator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -57,7 +53,7 @@ public class TaskResource extends ResourceBase {
private static final Logger logger = LoggerFactory.getLogger(RuntimeResource.class);
@Inject
- private ProcessRequestBean processRequestBean;
+ private RestProcessRequestBean processRequestBean;
@Context
private HttpServletRequest request;
@@ -152,7 +148,7 @@ public Response query(@Context UriInfo uriInfo) {
List statusList = convertStringListToStatusList(statusStrList);
// process params/cmds
- Queue> cmds = new LinkedList>();
+ Queue> cmds = new LinkedList>();
if (!workItemIdList.isEmpty()) {
for (Long workItemId : workItemIdList) {
cmds.add(new GetTaskByWorkItemIdCommand(workItemId));
@@ -167,11 +163,13 @@ public Response query(@Context UriInfo uriInfo) {
Set alreadyRetrievedSet = new HashSet();
List results = new ArrayList();
- Command> cmd = null;
+ TaskCommand> cmd = null;
while (!cmds.isEmpty()) {
cmd = cmds.poll();
logger.debug( "query: " + cmd.getClass().getSimpleName());
- TaskImpl task = (TaskImpl) internalDoTaskOperation(cmd, "Unable to execute " + cmd.getClass().getSimpleName());
+ TaskImpl task = (TaskImpl) processRequestBean.doTaskOperation(
+ cmd,
+ "Unable to execute " + cmd.getClass().getSimpleName());
if (task != null) {
TaskSummaryImpl taskSum = convertTaskToTaskSummary(task);
if( alreadyRetrievedSet.add(taskSum) ) {
@@ -202,10 +200,14 @@ public Response query(@Context UriInfo uriInfo) {
cmd = new GetTasksByProcessInstanceIdCommand(procInstId);
logger.debug( "query: " + cmd.getClass().getSimpleName());
@SuppressWarnings("unchecked")
- List procInstTaskIdList = (List) internalDoTaskOperation(cmd, "Unable to execute " + cmd.getClass().getSimpleName());
+ List procInstTaskIdList = (List) processRequestBean.doTaskOperation(
+ cmd,
+ "Unable to execute " + cmd.getClass().getSimpleName());
for (Long taskId : procInstTaskIdList) {
cmd = new GetTaskCommand(taskId);
- TaskImpl task = (TaskImpl) internalDoTaskOperation(cmd, "Unable to execute " + cmd.getClass().getSimpleName());
+ TaskImpl task = (TaskImpl) processRequestBean.doTaskOperation(
+ cmd,
+ "Unable to execute " + cmd.getClass().getSimpleName());
if (task != null) {
TaskSummaryImpl taskSum = convertTaskToTaskSummary(task);
if( alreadyRetrievedSet.add(taskSum) ) {
@@ -256,7 +258,9 @@ public Response query(@Context UriInfo uriInfo) {
cmd = cmds.poll();
logger.debug( "query: " + cmd.getClass().getSimpleName());
@SuppressWarnings("unchecked")
- List taskSummaryList = (List) internalDoTaskOperation(cmd, "Unable to execute " + cmd.getClass().getSimpleName());
+ List taskSummaryList = (List) processRequestBean.doTaskOperation(
+ cmd,
+ "Unable to execute " + cmd.getClass().getSimpleName());
if (taskSummaryList != null && !taskSummaryList.isEmpty()) {
for (TaskSummary taskSummary : taskSummaryList) {
TaskSummaryImpl taskSum = (TaskSummaryImpl) taskSummary;
@@ -280,8 +284,10 @@ public Response query(@Context UriInfo uriInfo) {
@GET
@Path("/{taskId: [0-9-]+}")
public Response getTaskInstanceInfo(@PathParam("taskId") long taskId) {
- Command> cmd = new GetTaskCommand(taskId);
- Task task = (Task) internalDoTaskOperation(cmd, "Unable to get task " + taskId);
+ TaskCommand> cmd = new GetTaskCommand(taskId);
+ Task task = (Task) processRequestBean.doTaskOperation(
+ cmd,
+ "Unable to get task " + taskId);
if( task == null ) {
throw new NotFoundException("Task " + taskId + " could not be found.");
}
@@ -297,11 +303,8 @@ public Response doTaskOperation(@PathParam("taskId") long taskId, @PathParam("op
String userId = identityProvider.getName();
logger.debug("Executing " + operation + " on task " + taskId + " by user " + userId );
- Command> cmd = null;
- cmd = new GetTaskCommand(taskId);
- if( internalDoTaskOperation(cmd, "Unable to check if task " + taskId + " exists") == null ) {
- throw new NotFoundException("Task " + taskId + " could not be found.");
- }
+ TaskCommand> cmd = null;
+
if ("activate".equalsIgnoreCase(operation)) {
cmd = new ActivateTaskCommand(taskId, userId);
} else if ("claim".equalsIgnoreCase(operation)) {
@@ -344,15 +347,49 @@ public Response doTaskOperation(@PathParam("taskId") long taskId, @PathParam("op
} else {
throw new BadRequestException("Unsupported operation: /task/" + taskId + "/" + operation);
}
- internalDoTaskOperation(cmd, "Unable to " + operation + " task " + taskId);
+
+ internalCheckAndDoTaskOperation(cmd, taskId, "Unable to " + operation + " task " + taskId);
return createCorrectVariant(new JaxbGenericResponse(request), restRequest);
}
+ private static String checkThatOperationExists(String operation, String[] possibleOperations) {
+ for (String oper : possibleOperations) {
+ if (oper.equals(operation.trim().toLowerCase())) {
+ return oper;
+ }
+ }
+ throw new BadRequestException("Operation '" + operation + "' is not supported on tasks.");
+ }
+
+ private Object internalCheckAndDoTaskOperation(TaskCommand> cmd, Long taskId, String errorMsg) {
+ assert taskId != null : "Submitted task id should always have a value.";
+
+ if( cmd instanceof CompleteTaskCommand
+ || cmd instanceof ExitTaskCommand
+ || cmd instanceof FailTaskCommand
+ || cmd instanceof SkipTaskCommand ) {
+ TaskCommand> getTaskCmd = new GetTaskCommand(taskId);
+ Task task = (Task) processRequestBean.doTaskOperation(
+ getTaskCmd,
+ "Task " + taskId + " does not exist or unable to check if it exists");
+ if( task == null ) {
+ throw new NotFoundException("Task " + taskId + " could not be found.");
+ }
+ String deploymentId = task.getTaskData().getDeploymentId();
+ return processRequestBean.doTaskOperationOnDeployment(cmd, errorMsg, deploymentId);
+ } else {
+ return processRequestBean.doTaskOperation(cmd, errorMsg);
+ }
+ }
+
+
@GET
@Path("/{taskId: [0-9-]+}/content")
public Response getTaskContent(@PathParam("taskId") long taskId) {
- Command> cmd = new GetTaskCommand(taskId);
- Object result = internalDoTaskOperation(cmd, "Unable to get task " + taskId);
+ TaskCommand> cmd = new GetTaskCommand(taskId);
+ Object result = processRequestBean.doTaskOperation(
+ cmd,
+ "Unable to get task " + taskId);
if( result == null ) {
throw new NotFoundException("Task " + taskId + " could not be found.");
}
@@ -360,7 +397,9 @@ public Response getTaskContent(@PathParam("taskId") long taskId) {
Content content = null;
if( contentId > -1 ) {
cmd = new GetContentCommand(contentId);
- result = internalDoTaskOperation(cmd, "Unable get content " + contentId + " (from task " + taskId + ")");
+ result = processRequestBean.doTaskOperation(
+ cmd,
+ "Unable get content " + contentId + " (from task " + taskId + ")");
content = (Content) result;
}
return createCorrectVariant(new JaxbContent(content), restRequest);
@@ -369,27 +408,12 @@ public Response getTaskContent(@PathParam("taskId") long taskId) {
@GET
@Path("/content/{contentId: [0-9-]+}")
public Response getContent(@PathParam("contentId") long contentId) {
- Command> cmd = new GetContentCommand(contentId);
- Content content = (Content) internalDoTaskOperation(cmd, "Unable to get task content " + contentId);
+ TaskCommand> cmd = new GetContentCommand(contentId);
+ Content content = (Content) processRequestBean.doTaskOperation(cmd, "Unable to get task content " + contentId);
if( content == null ) {
throw new NotFoundException("Content " + contentId + " could not be found.");
}
return createCorrectVariant(new JaxbContent(content), restRequest);
}
- // Helper methods --------------------------------------------------------------------------------------------------------------
-
- private Object internalDoTaskOperation(Command> cmd, String errorMsg) {
- Object result = processRequestBean.doTaskOperation(cmd);
- if( result instanceof JaxbExceptionResponse ) {
- Exception cause = ((JaxbExceptionResponse) result).getCause();
- if( cause instanceof RuntimeException ) {
- throw (RuntimeException) cause;
- } else {
- throw new InternalServerErrorException(errorMsg, cause);
- }
- }
- return result;
- }
-
}
diff --git a/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/exception/DescriptiveExceptionHandler.java b/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/exception/DescriptiveExceptionHandler.java
index 4692198069..abe500b4f0 100644
--- a/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/exception/DescriptiveExceptionHandler.java
+++ b/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/rest/exception/DescriptiveExceptionHandler.java
@@ -1,7 +1,9 @@
package org.kie.services.remote.rest.exception;
+import static org.kie.services.remote.rest.ResourceBase.variants;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Request;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.ext.ExceptionMapper;
@@ -24,6 +26,9 @@ public class DescriptiveExceptionHandler implements ExceptionMapper {
@Context
HttpServletRequest request;
+
+ @Context
+ Request restRequest;
@Override
public Response toResponse(Exception e) {
@@ -57,6 +62,7 @@ public Response toResponse(Exception e) {
} catch (JAXBException jaxb) {
responseBuilder.entity(JaxbGenericResponse.convertStackTraceToString(jaxb));
}
+ responseBuilder.variant(restRequest.selectVariant(variants));
return responseBuilder.build();
}
diff --git a/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/util/CommandsRequestUtil.java b/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/util/CommandsRequestUtil.java
deleted file mode 100644
index 8ea93e353f..0000000000
--- a/kie-remote/kie-services-remote/src/main/java/org/kie/services/remote/util/CommandsRequestUtil.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package org.kie.services.remote.util;
-
-import java.util.List;
-
-import org.jboss.resteasy.spi.NotAcceptableException;
-import org.jbpm.services.task.commands.TaskCommand;
-import org.kie.api.command.Command;
-import org.kie.services.client.api.command.AcceptedCommands;
-import org.kie.services.client.serialization.jaxb.impl.JaxbCommandsRequest;
-import org.kie.services.client.serialization.jaxb.impl.JaxbCommandsResponse;
-import org.kie.services.client.serialization.jaxb.impl.JaxbExceptionResponse;
-import org.kie.services.remote.cdi.ProcessRequestBean;
-import org.kie.services.remote.exception.KieRemoteServicesInternalError;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class CommandsRequestUtil {
-
- private static final Logger logger = LoggerFactory.getLogger(CommandsRequestUtil.class);
-
- public static JaxbCommandsResponse restProcessJaxbCommandsRequest(JaxbCommandsRequest request, ProcessRequestBean requestBean) {
- // If exceptions are happening here, then there is something REALLY wrong and they should be thrown.
- JaxbCommandsResponse jaxbResponse = new JaxbCommandsResponse(request);
- List> commands = request.getCommands();
-
- if (commands != null) {
- for (int i = 0; i < commands.size(); ++i) {
- Command> cmd = commands.get(i);
- if (!AcceptedCommands.getSet().contains(cmd.getClass())) {
- throw new NotAcceptableException("The execute REST operation does not accept " + cmd.getClass().getName()
- + " instances.");
- }
- logger.debug("Processing command " + cmd.getClass().getSimpleName());
- Object cmdResult = null;
- if (cmd instanceof TaskCommand>) {
- cmdResult = requestBean.doTaskOperation(cmd);
- } else {
- cmdResult = requestBean.doKieSessionOperation(cmd, request.getDeploymentId(), request.getProcessInstanceId());
- }
- if (cmdResult instanceof JaxbExceptionResponse) {
- Exception e = ((JaxbExceptionResponse) cmdResult).cause;
- if (e instanceof RuntimeException) {
- throw (RuntimeException) e;
- } else {
- throw new KieRemoteServicesInternalError("Unable to execute " + cmd.getClass().getSimpleName() + ": "
- + e.getMessage(), e);
- }
- }
- if (cmdResult != null) {
- try {
- // addResult could possibly throw an exception, which is why it's here and not above
- jaxbResponse.addResult(cmdResult, i, cmd);
- } catch (Exception e) {
- logger.error("Unable to add result from " + cmd.getClass().getSimpleName() + "/" + i + " because of "
- + e.getClass().getSimpleName(), e);
- jaxbResponse.addException(e, i, cmd);
- }
- }
- }
- }
-
- if (commands == null || commands.isEmpty()) {
- logger.info("Commands request object with no commands sent!");
- }
-
- return jaxbResponse;
- }
-
-
-}