Oct 08 2009

Oracle Workflow 终篇

Category: WorkflowZeeno @ 16:42

众所周知,在EBS历代版本中,Workflow的应用(包括业务事件)非常广泛。我觉得它最有价值的地方就在于,它采用的是PL/SQL语言开发。

Oracle Workflow内置于数据库中,拥有独立版本,也有EBS内置版本,通常用的都是EBS内置版本。所谓的内置,其实也只是除了工作流引擎之外的一套管理界面和工具。所以从版本上讲,Workflow版本是单独来讲,和EBS毫无关系。目前,EBS 11i和R12使用的Workflow版本都是一样的,最新版本是2.6.4。并且,该版本不会再有升级。如果EBS有R13版,如果R13还有Workflow,那它的版本依旧是2.6.4。当然,每个EBS版本都对此进行了少量改进,R12的Workflow增强了Web Services1相关功能(仅仅是相关功能)。

现在,公开可下载的Workflow是2.6.3,2.6.4版本的Workflow包含在RDBMS 10.2中。在新的应用中,Oracle推荐用BPEL,这是一套基于Java的工作流引擎,运行在Oracle SOA Suite上,但不是免费的。

如果你对PL/SQL情有独钟,或者认为它已经足够强大并且足够简单,可以继续使用Oracle Workflow 2.6版本,不过它已不再内置于新的数据库中,11g开始就没有了。

一款同样基于PL/SQL的工作流PL/FLOW,有兴趣的可以一看。如果不在乎是否免费,则完全可以转向BPEL。如果是一名Oracle ERP实施顾问,也可以开始深入学习BPEL了。

  1. 仅针对2.6.3版本及以上才有,因为2.6.2及以下版本没有相关的API。见Note. 363025.1 []


Jun 01 2009

为什么要学工作流?

Category: WorkflowZeeno @ 17:17

很多人经常面对一种场面,就是在查找某环节的问题时,惊奇的发现自己又得面对工作流。虽然有点排斥,但是,您必须面对它,无处可避。本文所言的工作流通常是指Oracle Workflow,这是数据库内置的组件,在EBS系统中它被发扬光大了。不论哪个版本,工作流都是一个核心的组件,在11i系列认证中,它甚至作为独立的一块内容。

当您的团队开始谈论BPM时,您可能会想起BPEL。是的,在R12中,有一种更独特的流程管理技术被推荐给用户,但是Workflow依旧处于一个非常关键的位置。我之前曾罗列过11i中的几个标准的工作流,它们在控制业务流程方面起到了有效的作用。如果光看到这些,您可能把工作流等同于审批流程了,事实上这是非常片面的理解。现在,请打开你的浏览器(我是指11i中的),进入采购超级用户(或者其它职责),选择“流程”,如下图:

Image Hosted by ImageShack.us

直接将流程和操作有机集成了。这也是一种工作流的应用。当然,也许您早知道这个功能并开始使用了。我也认同,把一些需要控制点的业务流程放在浏览器中,是一种不错的主意。这个和单据等审批流程类似,可以控制各个功能的执行时机。这些流程和审批层次一样,都是需要IT部门预先分析、设计并定义好的,但是如果用户,他可能刚入职,也可能子公司给他分配了新的角色,作为集团总部的您如何管理子公司各用户权限的分配呢?点击Web页面右上角的首选项,看到如下的内容:

如文字所示,“请求访问”就是用于自行申请权限(职责)的。回忆之前介绍用户层级管理时提到的,Provision Services和Self-Service and Approvals同样也用到了工作流。

Continue reading “为什么要学工作流?”


Mar 12 2009

业务事件(Business Event) Tips

Category: WorkflowZeeno @ 14:22

之前的一篇文章《业务事件之Java Rule Function》简单介绍了Java Rule Function的使用。在Oracle Workflow 2.6.x体系中,针对Function Activity的External Java也是非常有用的,同样的,也提供了接口以供编写应用程序。这两种方式,对于在应用层和异构系统交互或者处理其他一些PL/SQL无法完成的事务时,是绝对的利器。

在利用业务事件做实际应用时,根据经验,需要注意下面几点:

不要对JDBC Connection做close或release之类的操作。

Java Deferred Agent Listener一旦起来后,如果某个Java Rule Funtion中做了关闭数据库链接的操作,则会导致相应的队列(wf_java_deferred)中数据无法被处理,你甚至无法再单独重启该listener。

当然,你依然可以通过重启 Workflow Agent Listener Service 来使Java Deferred Agent Listener重新运作。

分步诊断

只有了解业务事件的整体架构后,才能更有效的找到问题真实症结所在。这里主要有三部分需要留意:

  1. 数据首先是被插入queue,此时可以使用预置文件FND: Debug Log EnabledFND: Debug Log Level打开日志记录。Workflow用的是标准的FND_LOG包来记录日志的。
  2. 在调用Java程序时,系统首先去检查缓存,如果缓存中已经存在该对象,则不再从硬盘中读取。因而如果Java程序被调用过又有更新的话,需要重启应用才能生效。如果不重启,一些异常信息可能并不完整,比如NoClassDefFoundError,可能并不提供未找到的类名。
  3. 针对Java Deferred Agent Listener有单独的日志记录,需要进workflow manager中设置log level。诊断完毕后千万记得重新将log level设置回原先的值。Java程序中的log也会记录到这里。

标准的Log代码:

private void log(String s, int i) {
	AppsLog appslog = (AppsLog) wfCtx.getLog();
	if (appslog.isEnabled(i))
		appslog.write(this, s, i);
}

Event参数传递

虽然subscription也可以传递参数,但是它的参数格式很别扭:var1=val1 var2=val2,多个参数以空格间隔,组成一个字符串传递过来。还要自己写程序来解析,比较麻烦。而且关键是,这些参数是静态定义的,无法在raise event时动态创建。所以Java中一般使用event中传递过来的参数。

在Oracle EBS系统中,DB和应用使用两套不同的JVM。如果在DB层写Java Procedure,若是需要第三方库,则要通过loadjava来导入DB。而应用层则相对简单,直接上传到$JAVA_TOP相应目录下即可。一般来讲,此类处理异构系统之间的程序,是不会放在DB层来实现的。

此外,在定义Subscription时,若没有特殊需求,将Rule Data设置为Key会比Message更有效。


Feb 12 2009

ORA-00600: kwqidrdq: loop

Category: Database, WorkflowZeeno @ 16:51

在新克隆的应用环境中启用Workflow Deferred Agent Listener总是错误,错误信息为:

[Feb 12, 2009 3:34:45 PM CST]:1234424085866:Thread[inboundThreadGroup1,5,inboundThreadGroup]:0:-1:test.domain.com.cn:10.0.0.2:-1:-1:ERROR:[SVC-GSM-WFALSNRSVC-12681-10002 : oracle.apps.fnd.wf.bes.AgentListenerProcessor.read()]:Could not executeUpdate() on { CALL WF_EVENT.LISTEN ( p_agent_name => :1, p_wait => :2, p_correlation => :3, p_deq_condition => null, p_message_count => :4, p_max_error_count => :5 )} -> java.sql.SQLException: ORA-00600: internal error code, arguments: [kwqidrdq: loop], [0], [0], [0], [0], [], [], []
ORA-06512: at "APPS.WF_EVENT", line 1560
ORA-06512: at line 1

检查Alert,日志显示:

Thu Feb 12 16:09:55 2009
Errors in file /u08/code/dev/proddb/9.2.0/admin/DEV_test/udump/dev_ora_9675.trc:
ORA-00600: internal error code, arguments: [kwqidrdq: loop], [0], [0], [0], [0], [], [], []

通过pfiles查看9675进程,是oracleDEV,确定不是第三方程序引起的。这个错误的产生通常和AQ相关,而WF_DEFERRED正是基于AQ的,这样问题范围就缩小了。

解决步骤如下:

1. 用sysdba权限登录,停用AQ Time Managers:

alter system set aq_tm_processes = 0

2. 检查相应的QUEUE_TABLE:

SELECT * FROM applsys.aq$_wf_deferred_i i
 WHERE NOT EXISTS
 (SELECT t.msgid FROM applsys.wf_deferred t WHERE i.msgid = t.msgid);

SELECT * FROM applsys.aq$_wf_deferred_h h
 WHERE NOT EXISTS
 (SELECT t.msgid FROM applsys.wf_deferred t WHERE h.msgid = t.msgid);

SELECT * FROM applsys.aq$_wf_deferred_t ti
 WHERE NOT EXISTS
 (SELECT t.msgid FROM applsys.wf_deferred t WHERE ti.msgid = t.msgid);

如果存在记录,则删除之。

3. 重启AQ Time Managers:

alter system set aq_tm_processes = 1

问题解决。还有一种更简单的方式,就是重建QUEUE_TABLE,不过这需要在不丢失数据的前提下。

Ref Metalink: 1070715.6


Feb 03 2009

业务事件之Java Rule Function

Category: WorkflowZeeno @ 17:22

工作流中一个非常有用的组件是业务事件(Business Event),它可以和异构系统进行互通消息。自Oracle Application Suite 11.5.10后,业务事件就支持Java程序了。如果不考虑使用数据库的功能(透明网关、Web Services)等,对于Oracle EBS而言,业务事件就是最优先的选择了。

Metalink上找不到相应的开发文档,Oracle Workflow Developer’s Guide 中提到过,但是很简略。和PL/SQL写rule function一样,使用Java也需要注意规范,必须使用该接口:

public interface SubscriptionInterface
{
    void onBusinessEvent(Subscription eo, BusinessEvent event, WorkflowContext ctx)
    throws BusinessEventException;
}

这三个参数作用:
eo 用于获取Subscription相关信息,比如phase或参数。
event BE对象,如event name, event key等。
ctx 工作流相关上下文,比如数据库链接句柄、日志对象等。

下面是一个简单的例子:

package oracle.apps.cux.sms;

import oracle.apps.fnd.wf.bes.BusinessEvent;
import oracle.apps.fnd.wf.bes.BusinessEventException;
import oracle.apps.fnd.wf.bes.SubscriptionInterface;
import oracle.apps.fnd.wf.bes.server.Subscription;
import oracle.apps.fnd.wf.common.WorkflowContext;

public class CuxSmsTransporter implements SubscriptionInterface {
	public void onBusinessEvent(Subscription eo, BusinessEvent event,
			WorkflowContext ctx) throws BusinessEventException {
		System.out.println("Hello Subscription!");
	}
}

具体的配置过程可以直接参考文档,创建业务事件、订阅,将class文件放入相应目录中即可。
需要留意的是,class文件要和应用的jvm版本一致,否则会导致如下错误:

[Feb 3, 2009 3:59:18 PM CST]:1233647958026:Thread[inboundThreadGroup1,5,inboundThreadGroup]:0:-1:erptest.orafans.com:10.0.0.2:-1:-1:ERROR:[fnd.wf.bes.EventDispatcher.executeSubscription()]:Could not instantiate Subscription -> java.lang.UnsupportedClassVersionError: oracle/apps/cux/sms/CuxSmsTransporter (Unsupported major.minor version 50.0)

由于系统缓存的问题,第一次调用后有修改,可能需要重启应用。


Jan 13 2009

工作流之强制同步处理模式

Category: WorkflowZeeno @ 16:26

往往,对于工作流的强制同步(Forced Synchronous)处理模式,可以仅仅当做一段SQL代码来理解,事实上它也仅在一个SESSION内执行结束。对于某些逻辑处理,工作流图形化的设计方式非常容易理解,并且容易维护和扩展,多数情况下比PL/SQL代码更容易维护——我们的代码质量总是太差,除了程序员没人看得懂。

相对于普通的工作流(同步、异步)来说,它主要的区别就是响应及时。它不会保存任何工作流信息,这也就意味着无法在监控页面查询到工作流状态。工作流会将所有运行状态和变量存在工作流相关的表中,当使用强制同步处理模式时,所有变量仅在内存里保存(实际上是一些RECORD类型的变量),当SESSION结束自动清除。

额外的一些限制有:

  1. 不能使用通知活动。
  2. 仅存在于单个Session中,不能Commit。
  3. 无法使用错误处理流程。
  4. On Revisit仅允许LOOP属性。
  5. 不能使用主从活动。
  6. 不能并行处理。
  7. 不能使用各类延迟处理的活动,比如Defer、Wait。
  8. 不能使用工作流后台处理引擎。
  9. 不能记录到工作流表。
  10. 仅允许少量的API调用。

(更详细的说明,可以参考工作流API文档)

使用强制同步处理模式的方法是设置ITEM_TYPE为#SYNC,或者wf_engine.eng_synch。如果在不启动DEBUG跟踪的前提下试图诊断工作流,则可以通过指定一个唯一的ITEM_TYPE来进行操作,即返回到普通的同步模式。

对于复杂权限的判断、帐户的生成,或其他存在多个逻辑判断的情形,使用工作流比在代码中控制要清晰很多,和设计文档中的流程图几乎一致。


Next Page »