JBoss 系列五十八:jBPM Human Task 源代码分析 - I

概述

本文基于jBPM 5.2.x分析jBPM 5jbpm-human-task 部分源代码,我们之所以选择jBPM 5.2.x是由于jBPM 5.2.x是有对应企业版本的BRMS,该代码是被Red Hat维护更新,经常企业版本BRMS5.3的patch等是基于此进行的。

jBPM 5.2.x代码链接:https://github.com/droolsjbpm/jbpm/tree/5.2.x

本处源代码分析基于: https://github.com/droolsjbpm/jbpm/tree/5.2.x/jbpm-human-task

                                         https://github.com/droolsjbpm/jbpm/tree/5.2.x/jbpm-human-task-war

org.jbpm.task.service.jms

org.jbpm.task.service.jms下定义了JMS作为执行human task的类,我们依次来看这些类。

org.jbpm.task.service.jms.JMSTaskServer

我们先来看JMSTaskServer类图:

JBoss 系列五十八:jBPM Human Task 源代码分析 - I_第1张图片

org.jbpm.task.service.TaskServer定义的start()方法JMSTaskServer进行了实现,JMSTaskServer实现的start()方法主要逻辑是初始化JMS相关的MessageConsumer,QueueSession,QueueConnection等,MessageConsumer基于服务器接收queue。顺序大致如下:

通过JNDI查询获取QueueConnectionFactory,通过QueueConnectionFactory创建QueueConnection,通过QueueConnection创建QueueSession,通过QueueSession创建MessageConsumer,如果初始化成功,则认为TaskServer运行状态为true,相关代码段如下:

如下:

		QueueConnectionFactory factory = (QueueConnectionFactory) ctx.lookup(connFactoryName);
		try {
			this.connection = factory.createQueueConnection();
			this.session = connection.createQueueSession(transacted, ackMode);
			this.queue = this.session.createQueue(queueName);
			this.responseQueue = this.session.createQueue(responseQueueName);
			this.consumer = this.session.createConsumer(this.queue);
			this.connection.start();
		} catch (JMSException e) {
			throw new RuntimeException("No se pudo levantar la cola servidora del JMSTaskServer", e);
		}
		this.running = true;

JMSTaskServer只定义一个构造方法,如下:

	public JMSTaskServer(TaskService service, Properties connProperties, Context context) {
		super(new JMSTaskServerHandler(service, SystemEventListenerFactory.getSystemEventListener()), connProperties, context);
	}

构造方法中参数:

  • service - 用来创建服务器端处理器JMSTaskServerHandler
  • connProperties - 定义初始化JMS发送消息相关的Session,Producer,Consumer等参数,如队列名字等
  • context - 定义JNDI的上下文,用来查询QueueConnectionFactory

另为JMSTaskServer实现Runnable,run()方法的实现如下:

	public void run() {
		try {
			start();
			while (this.running) {
				Message clientMessage = this.consumer.receive();
				if (clientMessage != null) {
					Object object = readMessage(clientMessage);
					String selector = readSelector(clientMessage);
					this.handler.messageReceived(this.session, object, this.responseQueue, selector);
				}
			}
		} catch (JMSException e) {
			if ("102".equals(e.getErrorCode())) {
				logger.info(e.getMessage());
			} else {
				logger.error(e.getMessage());
			}
		} catch (Exception e) {
			throw new RuntimeException("Error leyendo mensaje", e);
		}
	}

该部分代码大致逻辑是接收到一条消息后,JMSTaskServerHandler的messageReceived方法被调运。org.jbpm.task.service.jms.JMSTaskServerHandler类图如下:

JBoss 系列五十八:jBPM Human Task 源代码分析 - I_第2张图片

messageReceived方法实现如下:

	public void messageReceived(QueueSession session, Object message, Destination destination, String selector) throws Exception {
		String name = "";
		if (destination instanceof Queue) {
			name = ((Queue) destination).getQueueName();
		} else if (destination instanceof Topic) {
			name = ((Topic) destination).getTopicName();
		}
		MessageProducer producer = (MessageProducer) this.producers.get(name);
		if (producer == null) {
			producer = session.createProducer(destination);
			this.producers.put(name, producer);
		}
		this.handler.messageReceived(new JMSSessionWriter(session, producer, selector), message);
	}
此处理的结果是将结果发送到responseQueue,这一过程是在JMSSessionWriter的write()方法中,JMSSessionWriter的类图如下:

JBoss 系列五十八:jBPM Human Task 源代码分析 - I_第3张图片

JMSSessionWriter实现org.jbpm.task.service.SessionWriter,其中write()方法如下:

	public void write(Object message) throws IOException {
		try {
			ObjectMessage clientMessage = this.session.createObjectMessage();
			clientMessage.setObject((Serializable) message);
			
			clientMessage.setStringProperty(TaskServiceConstants.SELECTOR_NAME, this.selector);
			this.producer.send(clientMessage);
		} catch (JMSException e) {
			throw new IOException("Unable to create message: " + e.getMessage());
		} finally {
			try {
				if(this.session.getTransacted()) {
					this.session.commit();
				}
			} catch (JMSException e) {
				throw new IOException("Unable to commit message: " + e.getMessage());
			}
		}
	}
}


org.jbpm.task.service.TaskClient

TaskClient实现了接口org.jbpm.task.AsyncTaskService,相关类图 jbpm_source_taskclient.png。

TaskClient 提供了一系列方法用来管理Human Task的生命周期,这些方法包括:

    void start(long taskId, String userId, TaskOperationResponseHandler responseHandler);
    void stop(long taskId, String userId, TaskOperationResponseHandler responseHandler);
    void suspend(long taskId, String userId, TaskOperationResponseHandler responseHandler);
    void release(long taskId, String userId, TaskOperationResponseHandler responseHandler);
    void remove(long taskId, String userId, TaskOperationResponseHandler responseHandler);
    void resume(long taskId, String userId, TaskOperationResponseHandler responseHandler);
    void skip(long taskId, String userId, TaskOperationResponseHandler responseHandler);

所有这些方法都有如下参数:

  • taskId - Task的ID,这个ID是通过JPA数据库自动产生的,我们是通过查取数据库得到Task,然后从中获取此ID
  • userId - 这是指执行Task的用户ID,通常我们是在流程设计时设计定义,流程执行时通过此来获取Task
  • responseHandler - jBPM中执行Human Task,与Task Service的交互是异步的,所以我们需要返回处理器当返回结果可达时获取返回结果

When a message is invoked on the TaskClient, a message is created that will be sent to the server, and the server will execute the logic that implements the correct action.

我们会在后面的系列给出一个使用TaskClient操作改变Task生命周期的例子,具体链接:http://blog.csdn.net/kylinsoong/article/details/17040793#t4

org.jbpm.task.Task

org.jbpm.task.Task为数据库层模型,我们知道jBPM 执行Human Task时需要将数据存储与数据库,jBPM 通过JPA/Hibernate来实现这一功能,jBPM 数据模型主要包括两类实体:

  • Task实体 - 代表Human Task的主要信息
  • deadline, escalation, 和 notification实体 - 代表 执行Human Task时的相关deadline, escalation,已经与deadline, escalation相关的notification

相关类图: jbpm_source_task.png

另为i18ntext 和 organizationalentity也是主要数据模型的实体:

i18ntext实体- 代表与语言相关的文本存储,例如用户输入的名字,描述等

organizationalentity实体 - 代表一个用户

我们会在后面的系列给出一个数据模型明细相关的实验,具体链接:http://blog.csdn.net/kylinsoong/article/details/17040793#t3

org.jbpm.task.service.TaskService

org.jbpm.task.service.TaskService用来在执行Human Task时操作数据库,其中TaskSessionFactory包括JPA EntityManager,org.jbpm.task.service.TaskService所提供的构造方法如下:

public TaskService(EntityManagerFactory emf, SystemEventListener systemEventListener) {
        initialize(emf, systemEventListener, null);
}
public TaskService(EntityManagerFactory emf, SystemEventListener systemEventListener, EscalatedDeadlineHandler escalationHandler) {
        initialize(emf, systemEventListener, escalationHandler);
}

org.jbpm.task.service.TaskService相对应的类图  jbpm_source_taskservice.png


你可能感兴趣的:(jboss,异步,jbpm,源代码,jms)