use of org.kie.api.executor.CommandCallback in project jbpm by kiegroup.
the class AbstractAvailableJobsExecutor method executeGivenJob.
public void executeGivenJob(RequestInfo request) {
Throwable exception = null;
try {
AsyncExecutionMarker.markAsync();
eventSupport.fireBeforeJobExecuted(request, null);
if (request != null) {
boolean processReoccurring = false;
Command cmd = null;
CommandContext ctx = null;
ExecutionResults results = null;
List<CommandCallback> callbacks = null;
ClassLoader cl = getClassLoader(request.getDeploymentId());
try {
logger.debug("Processing Request Id: {}, status {} command {}", request.getId(), request.getStatus(), request.getCommandName());
byte[] reqData = request.getRequestData();
if (reqData != null) {
ObjectInputStream in = null;
try {
in = new ClassLoaderObjectInputStream(cl, new ByteArrayInputStream(reqData));
ctx = (CommandContext) in.readObject();
} catch (IOException e) {
logger.warn("Exception while serializing context data", e);
return;
} finally {
if (in != null) {
in.close();
}
}
}
if (request.getResponseData() == null) {
for (Map.Entry<String, Object> entry : contextData.entrySet()) {
ctx.setData(entry.getKey(), entry.getValue());
}
// add class loader so internally classes can be created with valid (kjar) deployment
ctx.setData("ClassLoader", cl);
cmd = classCacheManager.findCommand(request.getCommandName(), cl);
// increment execution counter directly to cover both success and failure paths
request.setExecutions(request.getExecutions() + 1);
results = cmd.execute(ctx);
if (results == null) {
results = new ExecutionResults();
}
try {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bout);
out.writeObject(results);
byte[] respData = bout.toByteArray();
request.setResponseData(respData);
} catch (IOException e) {
request.setResponseData(null);
}
results.setData("CompletedAt", new Date());
request.setStatus(STATUS.DONE);
executorStoreService.updateRequest(request, null);
processReoccurring = true;
} else {
logger.debug("Job was already successfully executed, retrying callbacks only...");
byte[] resData = request.getResponseData();
if (resData != null) {
ObjectInputStream in = null;
try {
in = new ClassLoaderObjectInputStream(cl, new ByteArrayInputStream(resData));
results = (ExecutionResults) in.readObject();
} catch (IOException e) {
logger.warn("Exception while serializing response data", e);
return;
} finally {
if (in != null) {
in.close();
}
}
}
request.setStatus(STATUS.DONE);
executorStoreService.updateRequest(request, null);
processReoccurring = true;
}
// callback handling after job execution
callbacks = classCacheManager.buildCommandCallback(ctx, cl);
for (CommandCallback handler : callbacks) {
handler.onCommandDone(ctx, results);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Throwable e) {
exception = e;
if (callbacks == null) {
callbacks = classCacheManager.buildCommandCallback(ctx, cl);
}
processReoccurring = handleException(request, e, ctx, callbacks);
} finally {
((ExecutorImpl) executor).clearExecution(request.getId());
AsyncExecutionMarker.reset();
handleCompletion(processReoccurring, cmd, ctx);
eventSupport.fireAfterJobExecuted(request, exception);
}
}
} catch (Exception e) {
logger.warn("Unexpected error while processin executor's job {}", e.getMessage(), e);
}
}
use of org.kie.api.executor.CommandCallback in project jbpm by kiegroup.
the class ClassCacheManager method findCommandCallback.
/**
* Finds command callback by FQCN and if not found loads the class and store the instance in
* the cache.
* @param name - fully qualified class name of the command callback
* @return initialized class instance
*/
public CommandCallback findCommandCallback(String name, ClassLoader cl) {
synchronized (callbackCache) {
if (!callbackCache.containsKey(name)) {
try {
CommandCallback commandCallbackInstance = (CommandCallback) Class.forName(name, true, cl).newInstance();
return commandCallbackInstance;
// callbackCache.put(name, commandCallbackInstance);
} catch (Exception ex) {
throw new IllegalArgumentException("Unknown Command implementation with name '" + name + "'");
}
} else {
CommandCallback cmdCallback = callbackCache.get(name);
if (!cmdCallback.getClass().getClassLoader().equals(cl)) {
callbackCache.remove(name);
try {
CommandCallback commandCallbackInstance = (CommandCallback) Class.forName(name, true, cl).newInstance();
callbackCache.put(name, commandCallbackInstance);
} catch (Exception ex) {
throw new IllegalArgumentException("Unknown Command implementation with name '" + name + "'");
}
}
}
}
return callbackCache.get(name);
}
use of org.kie.api.executor.CommandCallback in project jbpm by kiegroup.
the class AbstractAvailableJobsExecutor method handleException.
@SuppressWarnings("unchecked")
protected boolean handleException(RequestInfo request, Throwable e, CommandContext ctx, List<CommandCallback> callbacks) {
logger.warn("Error during command {} error message {}", request.getCommandName(), e.getMessage(), e);
ErrorInfo errorInfo = new ErrorInfo(e.getMessage(), ExceptionUtils.getStackTrace(e.fillInStackTrace()));
errorInfo.setRequestInfo(request);
((List<ErrorInfo>) request.getErrorInfo()).add(errorInfo);
logger.debug("Error Number: {}", request.getErrorInfo().size());
if (request.getRetries() > 0) {
request.setStatus(STATUS.RETRYING);
request.setRetries(request.getRetries() - 1);
// calculate next retry time
List<Long> retryDelay = (List<Long>) ctx.getData("retryDelay");
if (retryDelay != null) {
long retryAdd = 0l;
try {
// need to decrement it as executions are directly incremented upon execution
retryAdd = retryDelay.get(request.getExecutions() - 1);
} catch (IndexOutOfBoundsException ex) {
// in case there is no element matching given execution, use last one
retryAdd = retryDelay.get(retryDelay.size() - 1);
}
request.setTime(new Date(System.currentTimeMillis() + retryAdd));
logger.info("Retrying request ( with id {}) - delay configured, next retry at {}", request.getId(), request.getTime());
}
logger.debug("Retrying ({}) still available!", request.getRetries());
executorStoreService.updateRequest(request, ((ExecutorImpl) executor).scheduleExecution(request, request.getTime()));
return false;
} else {
logger.debug("Error no retries left!");
request.setStatus(STATUS.ERROR);
executorStoreService.updateRequest(request, null);
AsyncJobException wrappedException = new AsyncJobException(request.getId(), request.getCommandName(), e);
if (callbacks != null) {
for (CommandCallback handler : callbacks) {
handler.onCommandError(ctx, wrappedException);
}
}
return true;
}
}
use of org.kie.api.executor.CommandCallback in project jbpm by kiegroup.
the class ClassCacheManager method buildCommandCallback.
/**
* Builds completely initialized list of callbacks for given context.
* @param ctx contextual data given by execution service
* @return
*/
public List<CommandCallback> buildCommandCallback(CommandContext ctx, ClassLoader cl) {
List<CommandCallback> callbackList = new ArrayList<CommandCallback>();
if (ctx != null && ctx.getData("callbacks") != null) {
logger.debug("Callback: {}", ctx.getData("callbacks"));
String[] callbacksArray = ((String) ctx.getData("callbacks")).split(",");
List<String> callbacks = (List<String>) Arrays.asList(callbacksArray);
for (String callbackName : callbacks) {
CommandCallback handler = findCommandCallback(callbackName.trim(), cl);
callbackList.add(handler);
}
}
return callbackList;
}
Aggregations