IBM®
跳转到主要内容
    中国 [选择]    使用条款
 
 
Select a scope:Search for:    
    首页    产品    服务与解决方案     支持与下载    个性化服务    
跳转到主要内容

developerWorks 中国  >  WebSphere  >

基于WPS的电信业务集成场景,第六部分: 人工任务

developerWorks
文档选项

未显示需要 JavaScript 的文档选项


级别: 初级

曾 晓轩 (zengxx@cn.ibm.com), IBM中国开发中心的软件工程师

2006 年 6 月 05 日

本系列的前面几个部分对此项目的需求,架构,数据模型以及业务系统的接入等方面进行了介绍。WSCTI项目中的电信业务流程中也引入了人工任务,本文将介绍我们如何开发人工任务组件,以及如何使定制的客户端访问人工任务。

引言

企业的业务流程通常既会访问IT系统,也会引入人的参与,比如客服人员通知客户,施工人员开通服务等。人工任务(Human Task)是指业务流程中的活动(Activity)和人的交互。

WSCTI项目集成了多个电信业务系统,实现了一系列端到端的电信业务流程,本系列的前面几个部分对此项目的需求,架构,数据模型以及业务系统的接入等方面进行了介绍,参见参考资料。WSCTI项目中的电信业务流程中也引入了人工任务,本文将介绍我们如何开发人工任务组件,以及如何使定制的客户端访问人工任务。





回页首


WPS对人工任务的支持

人工任务是 WebSphere Process Server (WPS)中的独立组件,可以用来向员工分配任务或调用任何其他服务。人工任务管理器支持使用操作系统资源库, WebSphere 用户注册表,或者现有的 LDAP 目录访问人员信息。WPS 还支持人工任务的多级升调,其中包括电子邮件通知和优先级老化。

WPS 自带可扩展的 Web 客户机BPC Explorer应用程序,可以用于处理任务或者流程。该 Web 客户机基于一组可重用的 Java Server Faces (JSF) 组件,这些组件可以用于创建自定义客户机或者将人工任务功能嵌入其他的 Web 应用程序。同时,WPS也支持使用WebSphere Portal Server作为人工任务的客户机。

人工任务管理器支持四种类型的人工任务场景:机器-人(Machine-to-Human)场景,人-机器(Human-to-Machine)场景,人-人(Human-to-Human)场景,管理任务。和上一代的产品WBI Server Foundation相比较,WPS V6.0增加了基于SCA的人工任务,使用户可以灵活地替换系统中的自动服务和真正的人工实现。人工任务管理器为人工任务的相关应用提供了运行环境,负责进行任务调度。

更多关于人工任务的信息,可以参见参考资料。





回页首


WSCTI人工任务开发

人工任务组件

WSCTI项目中,当客户业务发生某种变化,需要人工通过电话等方式告知客户,发出人工任务给客服操作员,这是机器到人类型的人工任务。业务流程将会使用到这种服务,比如本系列第三部分业务流程开发中介绍的订单完成流程中,当整个订单全部完成后,需要通知客户其订单已完成。服务的接口CustomerNotification如图1。


图1 CustomerNotification接口
图1 CustomerNotification接口

其中使用的CustomerEvent的业务对象如图2,它包含了业务事件的相关信息和客户的具体信息,这样操作员收到人工任务后可以根据这些输入信息与客户联系,通知相关信息。


图2 CustomerEvent业务对象
图2 CustomerEvent业务对象

我们使用人工任务组件实现CustomerNotification接口,是机器对人的调用方式,发生服务调用的时候实际上就是将接口的输入数据发送给人,然后由人产生返回数据,并标识任务完成,这样调用就完成了。在组件的实现中,主要是选择将任务发送给哪些人也就是人工任务的接收者,客户端的设置,以及调升(Escalation)的设置。我们实现CustomerNotification接口的组件如图3。


图3 CustomerNotificationHTM人工任务组件
图3 CustomerNotificationHTM人工任务组件

对此我们按配置的内容分别解释如下:

1. 接收者设置。我们添加了两类客户通知任务的接收者,Potential Owner和Administrator。Potential Owner是指一组处理任务的人员,这里是指客服的操作人员。Administrator对任务可以行使管理员的权限,包括删除,转移任务等操作,这里不作详述,具体可以参见WPS信息中心。我们可以看看Potential Owner的设置,它就是查找出标识为操作员的一组人员,如图4


图4 Potential Owner设置
图4 Potential Owner设置

2. 客户端设置。WPS 可以支持BPC Explorer(WPS自带的应用程序),也支持集成WebSphere Portal Server。WSCTI使用自己开发的Web应用程序,所以这里没有设置。下面会有关于客户端更多的介绍。

3. 调升设置。当任务没有及时得到处理,就可以发生调升,也就是让更高层的人员知道任务的延误。我们可以根据任务的状态设置调升的时间,报告的人员等,如图5,到任务在提交以后20分钟没有完成的话,就会被调升。


图5 调升设置
图5 调升设置

这样,我们就完成了CustomerNotification服务的人工任务组件。我们还要将其以SCA Export的方式导出,这样其它的SCA模块就可以使用这个服务,如图6,CustomerNotificationExport是个SCA Export组件,它对其它的SCA模块提供了CustomerNotification接口的服务。


图6 CustomerNotification服务导出
图6 CustomerNotification服务导出

其它的模块将以SCA Import的方式导入CustomerNotificationExport,这样就可以使用CustomerNotification服务,将其作为参考服务。比如订单处理模块中,订单处理业务流程就使用此服务,组件之间的关系如图7。更多关于订单处理模块的介绍,参见本系列的第三部分。


图7 订单处理模块部分装配图
图7 订单处理模块部分装配图

在SalesOrderBPEL的实现中,使用CustomerNotification服务的方式通常都是首先创建CustomerEvent业务对象,填入通知的业务事件信息;然后调用CRM服务,根据客户标识查找客户的具体信息,填充到CustomerEvent业务对象中;最后调用CustomerNotification服务,生成人工任务,如图8。


图8 调用人工任务的业务流程
图8 调用人工任务的业务流程

访问人工任务

当人工任务由业务流程或其它组件发送出去后,其存在于WPS内部,而要是人真正访问到人工任务,需要使用用户界面将其表现出来,并提供人机交互的方法对任务进行操作。最常见的用户界面是Web的方式,WPS本身就提供了BPC Explorer应用程序,通过它可以看到WPS中发生的所有的人工任务,并对它们进行操作。在实际的集成系统中,我们常常会将这部分功能集成到客户自己的业务系统中,所以在WSCTI系统中,我们提供了另一个服务去访问WSCTI特定的人工任务,其接口HumanTask如图9。


图9 HumanTask接口
图9 HumanTask接口

其中retrieveCustomerEvents操作将从WPS中读取出所有通过CustomerNotification服务发出的用户事件,返回的CustomerEvents业务对象不仅包含了CustomerEvent业务对象序列,还包含了其对应的人工任务在WPS内部的唯一标识,以及发生的时间等信息,如图10。


图10 CustomerEvents业务对象
图10 CustomerEvents业务对象

retrieveEscalatedCustomerEvents操作与retrieveCustomerEvents类似,它读出的是部分通过CustomerNotification服务发出的用户事件,这些人工任务没有及时完成,需要客服操作员的更高层的人员如经理获知。

completeCustomerEvent操作提供了对人工任务的操作,当操作员完成了通知客户发生的业务事件后,通过Web客户端调用此方法,即完成了此人工任务。输入参数为前面的操作中取出的CustomerEvents业务对象中包含的人工任务的唯一标识。

我们使用了Java组件HumanTaskImpl去实现HumanTask接口,代码如图11。可以看到,它不需要继承某个HumanTask接口,而是实现了HumanTask接口的方法,就可以在SCA环境中提供服务。


图11 HumanTaskImpl.java源代码

public class HumanTaskImpl {
	private HumanTaskHandler handler;

	public HumanTaskImpl() {
		super();
		handler = new HumanTaskHandler();
	}

	private Object getMyService() {
		return (Object) ServiceManager.INSTANCE.locateService("self");
	}

	public DataObject retrieveCustomerEvents() {
		return handler.obtainCustomerEvents(false);
	}

	public Boolean completeCustomerEvent(String taskID) {
		return new Boolean(handler.completeTask(taskID));
	}

	public DataObject retrieveEscalatedCustomerEvents() {
		return handler.obtainCustomerEvents(true);
	}
}

HumanTaskImpl类中具体的实现都是通过HumanTaskHandler类,它的实现如图12。


图12 HamanTaskHandler.java源代码

public class HumanTaskHandler {

	private HumanTaskManagerService taskManagerService;

	public HumanTaskHandler() {
		super();
		InitialContext ctx=null;
		try {
			ctx = new InitialContext();
		} catch (NamingException e) {
			e.printStackTrace();
		}

		//获得HumanTaskManager服务

		Object myObj=null;
		try {
			myObj = ctx.lookup("com/ibm/task/api/HumanTaskManagerHome");
		} catch (NamingException e1) {
			e1.printStackTrace();
		}

		HumanTaskManagerHome myHome =	
		(HumanTaskManagerHome)javax.rmi.PortableRemoteObject.narrow(myObj,
		com.ibm.task.api.HumanTaskManagerHome.class);
		if(myHome != null)
		{
			try {
				taskManagerService = myHome.create();
			} catch(Exception e2) {
				e2.printStackTrace();
			} 
		}
	}

	/** 
	 *读取WPS中名为CustomerNotificationHTM的人工任务
	 * onlyEscalated表示是否只读取调升的任务
	 */
	public DataObject obtainCustomerEvents(boolean onlyEscalated) {
		BOFactory factory = (BOFactory) new
		ServiceManager().locateService("com/ibm/websphere/bo/BOFactory");
		//创建返回业务对象
		DataObject events =
		factory.create("http://PeonyLibrary","CustomerEvents");
		
		List tList = new ArrayList();
		
		if (taskManagerService!=null)
		{
				QueryResultSet result = null;
				TKIID tkiid = null;
				ClientObjectWrapper input = null;
				ArrayList idList = new ArrayList();
				ArrayList timeList = new ArrayList();
				if(onlyEscalated) {
					result =
					queryTask("TASK.TKIID","(TASK.STATE=TASK.STATE.STATE_READY
					OR TASK.STATE=TASK.STATE.STATE_CLAIMED) AND
					TASK.KIND=TASK.KIND.KIND_PARTICIPATING AND
					WORK_ITEM.REASON=WORK_ITEM.REASON.REASON_ADMINISTRATOR AND
					TASK.IS_ESCALATED=1 AND
					TASK.NAME='CustomerNotificationHTM'");
				}
				else {
					result =
					queryTask("TASK.TKIID","(TASK.STATE=TASK.STATE.STATE_READY
					OR TASK.STATE=TASK.STATE.STATE_CLAIMED) AND
					TASK.KIND=TASK.KIND.KIND_PARTICIPATING AND
					WORK_ITEM.REASON=WORK_ITEM.REASON.REASON_POTENTIAL_OWNER AND
					TASK.NAME='CustomerNotificationHTM'");
				}
				
				for(int a = 0; a < result.size(); a++)
				{
					if (a==0)
						result.first();
					else
						result.next();
					tkiid = (TKIID)result.getOID(1);					
					try {
						//解析任务的输入业务对象
						try {
							input = taskManagerService.
							getInputMessage(tkiid);
						} catch (RemoteException e) {
							e.printStackTrace();
						}
						if (input != null)
						{						
							BusObjImpl y = (BusObjImpl)input.getObject();
							DataObject p = y.getDataObject(0);	
							if(p != null) {
								tList.add(p);	
								idList.add(tkiid.toString());
								Task task = 
								taskManagerService.getTask(tkiid);
								
                              timeList.add(task.getActivationTime().getTime());
								
						
								DataObject customer =
								p.getDataObject("customer");
								if(customer != null)
									System.out.println("CustomerID=" +
									customer.getString("custID"));	
									
							}
						}
						
					} catch (Exception e) {
						e.printStackTrace();
					} 
				}
				events.setList("events", tList);
				events.setList("taskIDList", idList);
				events.setList("taskActivationTimeList", timeList);
				return events;
		} 
		
		return null;
	}

	/**
	 * 根据条件查询人工任务
	 */
	private QueryResultSet queryTask(String what, String where)
	{
		if (taskManagerService!=null)
		{
			QueryResultSet result = null;
			try {
				result = taskManagerService.query(what,where,null,null,null);
				return result;
			} catch (Exception e) {
				e.printStackTrace();
			} 
		}
		return null;
	}
	
	/**
	 * 完成指定的人工任务
	 * taskID为任务的标识
	 */
	public boolean completeTask(String taskID)
	{
		try {
			Task task = taskManagerService.getTask(taskID);
			if(task != null) {
				int state = task.getState();
				switch(state) {
					case Task.STATE_READY: 
					{
				 		taskManagerService.claim(taskID);
				 		taskManagerService.complete(taskID);
				 		break;
					}
					case Task.STATE_CLAIMED:
					{
				 		taskManagerService.complete(taskID);
				 		break;
					}
					default: 
					{
						break;
					}
				}				
				taskManagerService.delete(taskID);		
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		} 
	}
}

其中主要包括查询人工任务和完成任务两部分工作,都是通过由WPS提供的HumanTaskManagerService服务来完成。更多关于HumanTaskManagerService的详细信息及其API,可以参见WPS信息中心。

服务实现完成以后,需要将其导出,这样Web客户端才能使用。因为是供不支持SCA的JSP/Servlet使用的服务,我们需要将服务以Stand-alone Reference的方式导出,它对外提供的服务以HumanTask为接口,如图13。


图13 HumanTask服务导出
图13 HumanTask服务导出

Web客户端将会使用以HumanTask接口的服务,获取人工任务的数据CustomerEvents业务对象,对业务对象进行分析,然后在前端进行表现,提供了查询,完成任务等操作,界面如图14。实现的方式是通过在JSP/Servlet中使用SCA API调用HumanTask服务,这里不再赘述。


图14 人工任务Web界面
图14 人工任务Web界面




回页首


结束语

人工任务是业务流程中很重要的一个方面,WPS提供了对人工任务的良好的支持。本文介绍了WSCTI项目中实现的人工任务,以及客户端访问人工任务的实现。



参考资料

  1. 基于WPS的电信业务集成场景,第一部分:场景与系统架构是本系列的第一篇文章,介绍了WSCTI项目的背景,需求和系统架构。
  2. 基于WPS的电信业务集成场景,第二部分:数据建模及其实现是本系列的第二篇文章,介绍了WSCTI项目的数据模型。
  3. 基于WPS的电信业务集成场景,第三部分:业务流程开发以业务流程的案例介绍WSCTI项目如何开发复杂的业务流程。
  4. 基于WPS的电信业务集成场景,第四部分:集成WPS与数据库应用介绍如何在WSCTI中使用JCA JDBC Adapter动态提取数据库系统的信息,实现与服务开通系统的数据同步。
  5. 基于WPS的电信业务集成场景,第五部分:集成WPS与Web Services介绍WPS如何连接各种类型的WPS与.NET Web Services,实现数据通信。
  6. WebSphere业务流程管理信息中心包含了WebSphere Process Server和WebSphere Integration Developer等产品的文档。
  7. WebSphere Process Server V6 体系结构概述介绍了WPS的体系架构,其中也介绍了人工任务的相关信息。
  8. 如何在WPS V6.0 中正确建立业务流程引擎和人工任务管理器


关于作者

曾晓轩,IBM中国开发中心的软件工程师,主要从事WebSphere InterChange Server的开发和技术支持,以及WebSphere Process Server 软件的应用与服务支持。你可以通过zengxx@cn.ibm.com联系曾晓轩。




对本文的评价

太差! (1)
需提高 (2)
一般;尚可 (3)
好文章 (4)
真棒!(5)

建议?




回页首


IBM 公司保留在 developerWorks 网站上发表的内容的著作权。未经IBM公司或原始作者的书面明确许可,请勿转载。如果您希望转载,请通过 提交转载请求表单 联系我们的编辑团队。
    关于 IBM 隐私条约 联系 IBM 使用条款