org.jbpm.bpel.tutorial.task.TaskManager_Impl.java Source code

Java tutorial

Introduction

Here is the source code for org.jbpm.bpel.tutorial.task.TaskManager_Impl.java

Source

/*
 * JBoss, Home of Professional Open Source
 * Copyright 2005, JBoss Inc., and individual contributors as indicated
 * by the @authors tag.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the JBPM BPEL PUBLIC LICENSE AGREEMENT as
 * published by JBoss Inc.; either version 1.0 of the License, or
 * (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */
package org.jbpm.bpel.tutorial.task;

import java.rmi.RemoteException;
import java.util.List;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.Stub;
import javax.xml.rpc.server.ServiceLifecycle;
import javax.xml.rpc.server.ServletEndpointContext;
import javax.xml.rpc.soap.SOAPFaultException;
import javax.xml.soap.SOAPConstants;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;

import org.jbpm.JbpmConfiguration;
import org.jbpm.JbpmContext;
import org.jbpm.bpel.tutorial.wsa.EndpointReferenceType;
import org.jbpm.graph.exe.Token;
import org.jbpm.taskmgmt.exe.TaskInstance;

/**
 * @author Alejandro Guizar
 * @version $Revision$ $Date: 2008/06/12 08:30:54 $
 */
public class TaskManager_Impl implements TaskManager, ServiceLifecycle {

    private Service taskCallbackService;
    private JbpmConfiguration jbpmConfiguration;

    /** Initialization parameter for the jBPM configuration resource. */
    public static final String JBPM_CONFIG_RESOURCE_PARAM = "JbpmCfgResource";

    private static final String REPLY_ADDRESS_VARIABLE = "replyAddress";
    private static final QName SERVER_CODE = new QName(SOAPConstants.URI_NS_SOAP_ENVELOPE, "Server");

    private static final Log log = LogFactory.getLog(TaskManager_Impl.class);

    public long createTask(TaskInfo taskInfo, EndpointReferenceType replyTo) throws RemoteException {
        JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
        try {
            /*
             * Loading the token, even for read only, leads Hibernate to update the version column at the
             * end of the transaction, causing a stale state exception on the process side. To cope with
             * this situation, this method can either (1) ignore a second invocation when the process
             * detects the stale state and retries the operation or (2) avoid loading the token and set
             * the token column with a plain SQL statement
             */
            TaskInstance taskInstance = createTaskInstance2(taskInfo, replyTo, jbpmContext);
            return taskInstance.getId();
        } catch (RuntimeException e) {
            jbpmContext.setRollbackOnly();
            throw e;
        } finally {
            jbpmContext.close();
        }
    }

    private TaskInstance createTaskInstance1(TaskInfo taskInfo, EndpointReferenceType replyTo,
            JbpmContext jbpmContext) {
        String name = taskInfo.getName();
        Long tokenId = taskInfo.getTokenId();
        String actorId = taskInfo.getActorId();

        log.debug("looking for existing task instances with name=" + name + ", tokenId=" + tokenId + " and actorId="
                + actorId);

        List duplicates = jbpmContext.getSession().createCriteria(TaskInstance.class)
                .add(Restrictions.eq("name", name)).add(Restrictions.eq("actorId", actorId))
                .createAlias("token", "t").add(Restrictions.eq("t.id", tokenId)).list();

        if (!duplicates.isEmpty()) {
            jbpmContext.setRollbackOnly();

            TaskInstance duplicate = (TaskInstance) duplicates.get(0);
            log.debug("found " + duplicates.size() + " task instances, selected instance with id="
                    + duplicate.getId());
            return duplicate;
        }

        // materialize token
        Token token = jbpmContext.loadToken(tokenId.longValue());

        // create task instance for token
        TaskInstance taskInstance = token.getProcessInstance().getTaskMgmtInstance().createTaskInstance(token);

        // set task instance properties
        taskInstance.setName(name);
        taskInstance.setActorId(actorId);

        // save return address
        taskInstance.setVariable(REPLY_ADDRESS_VARIABLE, replyTo.getAddress().toString());
        jbpmContext.save(taskInstance);

        log.debug("found no task instances, created instance with id=" + taskInstance.getId());
        return taskInstance;
    }

    private TaskInstance createTaskInstance2(TaskInfo taskInfo, EndpointReferenceType replyTo,
            JbpmContext jbpmContext) {
        // TODO use task instance factory? requires execution context...
        TaskInstance taskInstance = new TaskInstance();

        // fire task creation event
        taskInstance.create();

        // set task instance properties
        taskInstance.setName(taskInfo.getName());
        taskInstance.setActorId(taskInfo.getActorId());

        // preserve return address
        taskInstance.setVariable(REPLY_ADDRESS_VARIABLE, replyTo.getAddress().toString());

        // save task instance
        Session hbSession = jbpmContext.getSession();
        hbSession.save(taskInstance);

        // associate task instance with token via SQL statement
        // FIXME isn't there a better way?
        hbSession.createSQLQuery("UPDATE JBPM_TASKINSTANCE SET TOKEN_ = :token WHERE ID_ = :id")
                .setLong("token", taskInfo.getTokenId().longValue()).setLong("id", taskInstance.getId())
                .executeUpdate();

        return taskInstance;
    }

    public void endTask(TaskInfo taskInfo) {
        JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
        String replyAddress;
        try {
            // end task instance
            TaskInstance taskInstance = jbpmContext.loadTaskInstance(taskInfo.getTaskId().longValue());
            replyAddress = (String) taskInstance.getVariable(REPLY_ADDRESS_VARIABLE);
            taskInstance.end();
        } catch (RuntimeException e) {
            jbpmContext.setRollbackOnly();
            throw e;
        } finally {
            jbpmContext.close();
        }

        try {
            // acquire endpoint proxy
            TaskCallback taskCallback = (TaskCallback) taskCallbackService.getPort(TaskCallback.class);

            // configure callback address
            Stub taskCallbackStub = (Stub) taskCallback;
            taskCallbackStub._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, replyAddress);

            log.debug("calling back endpoint at: " + replyAddress);
            taskCallback.taskEnded(taskInfo);
        } catch (ServiceException e) {
            log.error("could not get callback endpoint proxy", e);
            throw new SOAPFaultException(SERVER_CODE, "task callback failed", null, null);
        } catch (RemoteException e) {
            log.error("endpoint callback failed", e);
            throw new SOAPFaultException(SERVER_CODE, "task callback failed", null, null);
        }
    }

    public TaskList getTaskList(String actorId) {
        JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext();
        try {
            List taskInstances = jbpmContext.getTaskList(actorId);
            int taskCount = taskInstances.size();
            TaskInfo[] taskInfos = new TaskInfo[taskCount];

            for (int i = 0; i < taskCount; i++) {
                TaskInstance taskInstance = (TaskInstance) taskInstances.get(i);

                TaskInfo taskInfo = new TaskInfo();
                taskInfo.setTaskId(new Long(taskInstance.getId()));
                taskInfo.setName(taskInstance.getName());
                taskInfo.setActorId(taskInstance.getActorId());
                taskInfo.setTokenId(new Long(taskInstance.getToken().getId()));

                taskInfos[i] = taskInfo;
            }
            return new TaskList(taskInfos);
        } finally {
            jbpmContext.close();
        }
    }

    public void init(Object context) throws ServiceException {
        // jbpm configuration
        ServletEndpointContext endpointContext = (ServletEndpointContext) context;
        String configResource = endpointContext.getServletContext().getInitParameter(JBPM_CONFIG_RESOURCE_PARAM);
        jbpmConfiguration = JbpmConfiguration.getInstance(configResource);

        // task callback service
        try {
            Context initialContext = new InitialContext();
            taskCallbackService = (Service) initialContext.lookup("java:comp/env/service/TaskCallback");
            initialContext.close();
        } catch (NamingException e) {
            throw new ServiceException("could not retrieve task callback service", e);
        }
    }

    public void destroy() {
        taskCallbackService = null;
    }
}