Search in sources :

Example 1 with CommandCallback

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);
    }
}
Also used : CommandContext(org.kie.api.executor.CommandContext) ExecutionResults(org.kie.api.executor.ExecutionResults) ClassLoaderObjectInputStream(org.apache.commons.io.input.ClassLoaderObjectInputStream) IOException(java.io.IOException) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ObjectOutputStream(java.io.ObjectOutputStream) Date(java.util.Date) IOException(java.io.IOException) AsyncJobException(org.jbpm.executor.AsyncJobException) Command(org.kie.api.executor.Command) ByteArrayInputStream(java.io.ByteArrayInputStream) CommandCallback(org.kie.api.executor.CommandCallback) HashMap(java.util.HashMap) Map(java.util.Map) ObjectInputStream(java.io.ObjectInputStream) ClassLoaderObjectInputStream(org.apache.commons.io.input.ClassLoaderObjectInputStream)

Example 2 with CommandCallback

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);
}
Also used : CommandCallback(org.kie.api.executor.CommandCallback)

Example 3 with CommandCallback

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;
    }
}
Also used : ErrorInfo(org.jbpm.executor.entities.ErrorInfo) AsyncJobException(org.jbpm.executor.AsyncJobException) List(java.util.List) CommandCallback(org.kie.api.executor.CommandCallback) Date(java.util.Date)

Example 4 with CommandCallback

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;
}
Also used : ArrayList(java.util.ArrayList) List(java.util.List) ArrayList(java.util.ArrayList) CommandCallback(org.kie.api.executor.CommandCallback)

Aggregations

CommandCallback (org.kie.api.executor.CommandCallback)4 Date (java.util.Date)2 List (java.util.List)2 AsyncJobException (org.jbpm.executor.AsyncJobException)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 IOException (java.io.IOException)1 ObjectInputStream (java.io.ObjectInputStream)1 ObjectOutputStream (java.io.ObjectOutputStream)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 ClassLoaderObjectInputStream (org.apache.commons.io.input.ClassLoaderObjectInputStream)1 ErrorInfo (org.jbpm.executor.entities.ErrorInfo)1 Command (org.kie.api.executor.Command)1 CommandContext (org.kie.api.executor.CommandContext)1 ExecutionResults (org.kie.api.executor.ExecutionResults)1