<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Fans Or Not &#187; Workflow</title>
	<atom:link href="http://www.orafans.net/category/workflow/feed" rel="self" type="application/rss+xml" />
	<link>http://www.orafans.net</link>
	<description>寒山问拾得</description>
	<lastBuildDate>Sun, 22 Aug 2010 02:48:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Oracle Workflow 终篇</title>
		<link>http://www.orafans.net/2009/10/oracle-workflow-final.html</link>
		<comments>http://www.orafans.net/2009/10/oracle-workflow-final.html#comments</comments>
		<pubDate>Thu, 08 Oct 2009 08:42:13 +0000</pubDate>
		<dc:creator>Zeeno</dc:creator>
				<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://www.orafans.org/?p=438</guid>
		<description><![CDATA[众所周知，在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了。 仅针对2.6.3版本及以上才有，因为2.6.2及以下版本没有相关的API。见Note. 363025.1]]></description>
			<content:encoded><![CDATA[<p>众所周知，在EBS历代版本中，Workflow的应用（包括业务事件）非常广泛。我觉得它最有价值的地方就在于，它采用的是PL/SQL语言开发。</p>
<p><a href="http://www.oracle.com/technology/products/ias/workflow/index.html">Oracle Workflow</a>内置于数据库中，拥有独立版本，也有EBS内置版本，通常用的都是EBS内置版本。所谓的内置，其实也只是除了工作流引擎之外的一套管理界面和工具。所以从版本上讲，Workflow版本是单独来讲，和EBS毫无关系。目前，EBS 11i和R12使用的Workflow版本都是一样的，最新版本是2.6.4。并且，该版本不会再有升级。如果EBS有R13版，如果R13还有Workflow，那它的版本依旧是2.6.4。当然，每个EBS版本都对此进行了少量改进，R12的Workflow增强了Web Services<sup><a href="http://www.orafans.net/2009/10/oracle-workflow-final.html#footnote_0_438" id="identifier_0_438" class="footnote-link footnote-identifier-link" title="仅针对2.6.3版本及以上才有，因为2.6.2及以下版本没有相关的API。见Note. 363025.1">1</a></sup>相关功能(仅仅是相关功能)。</p>
<p>现在，公开可下载的Workflow是2.6.3，2.6.4版本的Workflow包含在RDBMS 10.2中。在新的应用中，Oracle推荐用<a href="http://www.oracle.com/technology/products/ias/bpel/index.html">BPEL</a>，这是一套基于Java的工作流引擎，运行在Oracle SOA Suite上，但不是免费的。</p>
<p>如果你对PL/SQL情有独钟，或者认为它已经足够强大并且足够简单，可以继续使用Oracle Workflow 2.6版本，不过它已不再内置于新的数据库中，11g开始就没有了。</p>
<p>一款同样基于PL/SQL的工作流<a href="http://plflow.sourceforge.net/">PL/FLOW</a>，有兴趣的可以一看。如果不在乎是否免费，则完全可以转向BPEL。如果是一名Oracle ERP实施顾问，也可以开始深入学习BPEL了。</p>
<ol class="footnotes"><li id="footnote_0_438" class="footnote">仅针对2.6.3版本及以上才有，因为2.6.2及以下版本没有相关的API。见Note. 363025.1</li></ol>]]></content:encoded>
			<wfw:commentRss>http://www.orafans.net/2009/10/oracle-workflow-final.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>为什么要学工作流？</title>
		<link>http://www.orafans.net/2009/06/why-learn-workflow.html</link>
		<comments>http://www.orafans.net/2009/06/why-learn-workflow.html#comments</comments>
		<pubDate>Mon, 01 Jun 2009 09:17:36 +0000</pubDate>
		<dc:creator>Zeeno</dc:creator>
				<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://www.orafans.org/archives/369</guid>
		<description><![CDATA[很多人经常面对一种场面，就是在查找某环节的问题时，惊奇的发现自己又得面对工作流。虽然有点排斥，但是，您必须面对它，无处可避。本文所言的工作流通常是指Oracle Workflow，这是数据库内置的组件，在EBS系统中它被发扬光大了。不论哪个版本，工作流都是一个核心的组件，在11i系列认证中，它甚至作为独立的一块内容。 当您的团队开始谈论BPM时，您可能会想起BPEL。是的，在R12中，有一种更独特的流程管理技术被推荐给用户，但是Workflow依旧处于一个非常关键的位置。我之前曾罗列过11i中的几个标准的工作流，它们在控制业务流程方面起到了有效的作用。如果光看到这些，您可能把工作流等同于审批流程了，事实上这是非常片面的理解。现在，请打开你的浏览器（我是指11i中的），进入采购超级用户（或者其它职责），选择“流程”，如下图： 直接将流程和操作有机集成了。这也是一种工作流的应用。当然，也许您早知道这个功能并开始使用了。我也认同，把一些需要控制点的业务流程放在浏览器中，是一种不错的主意。这个和单据等审批流程类似，可以控制各个功能的执行时机。这些流程和审批层次一样，都是需要IT部门预先分析、设计并定义好的，但是如果用户，他可能刚入职，也可能子公司给他分配了新的角色，作为集团总部的您如何管理子公司各用户权限的分配呢？点击Web页面右上角的首选项，看到如下的内容： 如文字所示，“请求访问”就是用于自行申请权限（职责）的。回忆之前介绍用户层级管理时提到的，Provision Services和Self-Service and Approvals同样也用到了工作流。 以上都是除了审批之外的非典型工作流应用。只要您的业务中存在规则（rule-based），那么就可以使用工作流。还有很多地方可以发现工作流的应用，这里不一一举例了。大致划分的话，可以发现下面几个领域会用到工作流： 审批。比如采购订单审批，另有一些场合会使用AME。 任何有规则，需要控制流程的场所。比如进行复杂数据处理时，利用工作流非常直观的设计界面来设计处理流程，而不是塞到一段冗长的PL/SQL代码中。 业务事件。比如某些删除或更新操作可能需要通知其他系统，这时可以考虑订阅该事件，并实施特殊的逻辑。 异构系统的同步。可以将工作流和业务事件组合使用，在处理异构系统的数据同步时非常有用。比如您可能需要某个关键点触发一条手机短信。 发邮件。工作流的邮件功能已经非常强大，可以发HTML格式的邮件，也可以发附件。 投票。 如果您有心去统计，会发现11i中工作流的影子遍布在每个角落。工作流并不难懂，掌握了它，对理解11i内部工作机制有非常大的帮助。]]></description>
			<content:encoded><![CDATA[<p>很多人经常面对一种场面，就是在查找某环节的问题时，惊奇的发现自己又得面对工作流。虽然有点排斥，但是，您必须面对它，无处可避。本文所言的工作流通常是指Oracle Workflow，这是数据库内置的组件，在EBS系统中它被发扬光大了。不论哪个版本，工作流都是一个核心的组件，在11i系列认证中，它甚至作为独立的一块内容。</p>
<p>当您的团队开始谈论BPM时，您可能会想起BPEL。是的，在R12中，有一种更独特的流程管理技术被推荐给用户，但是Workflow依旧处于一个非常关键的位置。我之前曾罗列过<a href="http://www.orafans.org/archives/5">11i中的几个标准的工作流</a>，它们在控制业务流程方面起到了有效的作用。如果光看到这些，您可能把工作流等同于审批流程了，事实上这是非常片面的理解。现在，请打开你的浏览器（我是指11i中的），进入采购超级用户（或者其它职责），选择“流程”，如下图：</p>
<p><a href="http://www.orafans.net/2009/06/why-learn-workflow.html/attachment/20090601164658" rel="attachment wp-att-507"><img src="http://www.orafans.net/wp-content/uploads/2009/06/20090601164658.png" alt="" title="workflow" width="500" height="519" class="alignnone size-full wp-image-507" /></a></p>
<p>直接将流程和操作有机集成了。这也是一种工作流的应用。当然，也许您早知道这个功能并开始使用了。我也认同，把一些需要控制点的业务流程放在浏览器中，是一种不错的主意。这个和单据等审批流程类似，可以控制各个功能的执行时机。这些流程和审批层次一样，都是需要IT部门预先分析、设计并定义好的，但是如果用户，他可能刚入职，也可能子公司给他分配了新的角色，作为集团总部的您如何管理子公司各用户权限的分配呢？点击Web页面右上角的首选项，看到如下的内容：</p>
<p><a href="http://www.orafans.net/2009/06/why-learn-workflow.html/attachment/20090601165456" rel="attachment wp-att-510"><img src="http://www.orafans.net/wp-content/uploads/2009/06/20090601165456.png" alt="" title="20090601165456" width="580" height="141" class="alignnone size-full wp-image-510" /></a></p>
<p>如文字所示，“请求访问”就是用于自行申请权限（职责）的。回忆之前介绍<a href="http://www.orafans.org/archives/353">用户层级管理</a>时提到的，Provision Services和Self-Service and Approvals同样也用到了工作流。</p>
<p><span id="more-369"></span></p>
<p>以上都是除了审批之外的非典型工作流应用。只要您的业务中存在规则（rule-based），那么就可以使用工作流。还有很多地方可以发现工作流的应用，这里不一一举例了。大致划分的话，可以发现下面几个领域会用到工作流：</p>
<ol>
<li>审批。比如采购订单审批，另有一些场合会使用AME。</li>
<li>任何有规则，需要控制流程的场所。比如进行复杂数据处理时，利用工作流非常直观的设计界面来设计处理流程，而不是塞到一段冗长的PL/SQL代码中。</li>
<li>业务事件。比如某些删除或更新操作可能需要通知其他系统，这时可以考虑订阅该事件，并实施特殊的逻辑。</li>
<li>异构系统的同步。可以将工作流和业务事件组合使用，在处理异构系统的数据同步时非常有用。比如您可能需要某个关键点触发一条手机短信。</li>
<li>发邮件。工作流的邮件功能已经非常强大，可以发HTML格式的邮件，也可以发附件。</li>
<li>投票。</li>
</ol>
<p>如果您有心去统计，会发现11i中工作流的影子遍布在每个角落。工作流并不难懂，掌握了它，对理解11i内部工作机制有非常大的帮助。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.orafans.net/2009/06/why-learn-workflow.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>业务事件(Business Event) Tips</title>
		<link>http://www.orafans.net/2009/03/business-event-tips.html</link>
		<comments>http://www.orafans.net/2009/03/business-event-tips.html#comments</comments>
		<pubDate>Thu, 12 Mar 2009 06:22:31 +0000</pubDate>
		<dc:creator>Zeeno</dc:creator>
				<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://www.orafans.org/?p=323</guid>
		<description><![CDATA[之前的一篇文章《业务事件之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重新运作。 分步诊断 只有了解业务事件的整体架构后，才能更有效的找到问题真实症结所在。这里主要有三部分需要留意： 数据首先是被插入queue，此时可以使用预置文件FND: Debug Log Enabled和FND: Debug Log Level打开日志记录。Workflow用的是标准的FND_LOG包来记录日志的。 在调用Java程序时，系统首先去检查缓存，如果缓存中已经存在该对象，则不再从硬盘中读取。因而如果Java程序被调用过又有更新的话，需要重启应用才能生效。如果不重启，一些异常信息可能并不完整，比如NoClassDefFoundError，可能并不提供未找到的类名。 针对Java Deferred Agent Listener有单独的日志记录，需要进workflow manager中设置log level。诊断完毕后千万记得重新将log level设置回原先的值。Java程序中的log也会记录到这里。 标准的Log代码： private void log(String s, int i) { AppsLog appslog = [...]]]></description>
			<content:encoded><![CDATA[<p>之前的一篇文章《<a href="http://www.orafans.org/archives/222">业务事件之Java Rule Function</a>》简单介绍了Java Rule Function的使用。在Oracle Workflow 2.6.x体系中，针对Function Activity的External Java也是非常有用的，同样的，也提供了接口以供编写应用程序。这两种方式，对于在应用层和异构系统交互或者处理其他一些PL/SQL无法完成的事务时，是绝对的利器。</p>
<p>在利用业务事件做实际应用时，根据经验，需要注意下面几点：</p>
<h4>不要对JDBC Connection做close或release之类的操作。</h4>
<p>Java Deferred Agent Listener一旦起来后，如果某个Java Rule Funtion中做了关闭数据库链接的操作，则会导致相应的队列(wf_java_deferred)中数据无法被处理，你甚至无法再单独重启该listener。</p>
<p>当然，你依然可以通过重启 Workflow Agent Listener Service 来使Java Deferred Agent Listener重新运作。</p>
<h4>分步诊断</h4>
<p>只有了解业务事件的整体架构后，才能更有效的找到问题真实症结所在。这里主要有三部分需要留意：</p>
<ol>
<li>数据首先是被插入queue，此时可以使用预置文件<strong>FND: Debug Log Enabled</strong>和<strong>FND: Debug Log Level</strong>打开日志记录。Workflow用的是标准的FND_LOG包来记录日志的。</li>
<li>在调用Java程序时，系统首先去检查缓存，如果缓存中已经存在该对象，则不再从硬盘中读取。因而如果Java程序被调用过又有更新的话，需要重启应用才能生效。如果不重启，一些异常信息可能并不完整，比如NoClassDefFoundError，可能并不提供未找到的类名。</li>
<li>针对Java Deferred Agent Listener有单独的日志记录，需要进workflow manager中设置log level。诊断完毕后千万记得重新将log level设置回原先的值。Java程序中的log也会记录到这里。
</li>
</ol>
<p>标准的Log代码：</p>
<pre lang="java">
private void log(String s, int i) {
	AppsLog appslog = (AppsLog) wfCtx.getLog();
	if (appslog.isEnabled(i))
		appslog.write(this, s, i);
}
</pre>
<h4>Event参数传递</h4>
<p>虽然subscription也可以传递参数，但是它的参数格式很别扭：<code>var1=val1 var2=val2</code>，多个参数以空格间隔，组成一个字符串传递过来。还要自己写程序来解析，比较麻烦。而且关键是，这些参数是静态定义的，无法在raise event时动态创建。所以Java中一般使用event中传递过来的参数。</p>
<p>在Oracle EBS系统中，DB和应用使用两套不同的JVM。如果在DB层写Java Procedure，若是需要第三方库，则要通过loadjava来导入DB。而应用层则相对简单，直接上传到$JAVA_TOP相应目录下即可。一般来讲，此类处理异构系统之间的程序，是不会放在DB层来实现的。</p>
<p>此外，在定义Subscription时，若没有特殊需求，将Rule Data设置为Key会比Message更有效。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.orafans.net/2009/03/business-event-tips.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ORA-00600: kwqidrdq: loop</title>
		<link>http://www.orafans.net/2009/02/ora-00600-kwqidrdq-loop.html</link>
		<comments>http://www.orafans.net/2009/02/ora-00600-kwqidrdq-loop.html#comments</comments>
		<pubDate>Thu, 12 Feb 2009 08:51:02 +0000</pubDate>
		<dc:creator>Zeeno</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://www.orafans.org/?p=231</guid>
		<description><![CDATA[在新克隆的应用环境中启用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: [...]]]></description>
			<content:encoded><![CDATA[<p>在新克隆的应用环境中启用Workflow Deferred Agent Listener总是错误，错误信息为：</p>
<pre class="brush:text">
[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
</pre>
<p>检查Alert，日志显示:</p>
<pre class="brush:text">
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], [], [], []
</pre>
<p>通过pfiles查看9675进程，是oracleDEV，确定不是第三方程序引起的。这个错误的产生通常和AQ相关，而WF_DEFERRED正是基于AQ的，这样问题范围就缩小了。</p>
<p>解决步骤如下：</p>
<p>1. 用sysdba权限登录，停用AQ Time Managers：</p>
<pre class="brush:sql">alter system set aq_tm_processes = 0</pre>
<p>2. 检查相应的QUEUE_TABLE：</p>
<pre class="brush:sql">
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);</pre>
<p>如果存在记录，则删除之。</p>
<p>3. 重启AQ Time Managers：</p>
<pre class="brush:sql">alter system set aq_tm_processes = 1</pre>
<p>问题解决。还有一种更简单的方式，就是重建QUEUE_TABLE，不过这需要在不丢失数据的前提下。</p>
<p>Ref Metalink: <a href="https://metalink.oracle.com/CSP/main/showdoc?db=NOT&#038;id=1070715.6">1070715.6</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.orafans.net/2009/02/ora-00600-kwqidrdq-loop.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>业务事件之Java Rule Function</title>
		<link>http://www.orafans.net/2009/02/business-event-java-rule-function.html</link>
		<comments>http://www.orafans.net/2009/02/business-event-java-rule-function.html#comments</comments>
		<pubDate>Tue, 03 Feb 2009 09:22:14 +0000</pubDate>
		<dc:creator>Zeeno</dc:creator>
				<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://www.orafans.org/?p=222</guid>
		<description><![CDATA[工作流中一个非常有用的组件是业务事件(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 [...]]]></description>
			<content:encoded><![CDATA[<p>工作流中一个非常有用的组件是业务事件(Business Event)，它可以和异构系统进行互通消息。自Oracle Application Suite 11.5.10后，业务事件就支持Java程序了。如果不考虑使用数据库的功能（透明网关、Web Services）等，对于Oracle EBS而言，业务事件就是最优先的选择了。</p>
<p>Metalink上找不到相应的开发文档，Oracle Workflow Developer’s Guide 中提到过，但是很简略。和PL/SQL写rule function一样，使用Java也需要注意规范，必须使用该接口：</p>
<pre lang="java">
public interface SubscriptionInterface
{
    void onBusinessEvent(Subscription eo, BusinessEvent event, WorkflowContext ctx)
    throws BusinessEventException;
}
</pre>
<p>这三个参数作用：<br />
<strong>eo</strong> 用于获取Subscription相关信息，比如phase或参数。<br />
<strong>event</strong> BE对象，如event name, event key等。<br />
<strong>ctx</strong> 工作流相关上下文，比如数据库链接句柄、日志对象等。</p>
<p>下面是一个简单的例子：</p>
<pre lang="java">
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!");
	}
}
</pre>
<p>具体的配置过程可以直接参考文档，创建业务事件、订阅，将class文件放入相应目录中即可。<br />
需要留意的是，class文件要和应用的jvm版本一致，否则会导致如下错误：<br />
<code><br />
[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)<br />
</code></p>
<p>由于系统缓存的问题，第一次调用后有修改，可能需要重启应用。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.orafans.net/2009/02/business-event-java-rule-function.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>工作流之强制同步处理模式</title>
		<link>http://www.orafans.net/2009/01/workflow-force-synchronization-mode.html</link>
		<comments>http://www.orafans.net/2009/01/workflow-force-synchronization-mode.html#comments</comments>
		<pubDate>Tue, 13 Jan 2009 08:26:11 +0000</pubDate>
		<dc:creator>Zeeno</dc:creator>
				<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://www.orafans.org/?p=216</guid>
		<description><![CDATA[往往，对于工作流的强制同步(Forced Synchronous)处理模式，可以仅仅当做一段SQL代码来理解，事实上它也仅在一个SESSION内执行结束。对于某些逻辑处理，工作流图形化的设计方式非常容易理解，并且容易维护和扩展，多数情况下比PL/SQL代码更容易维护——我们的代码质量总是太差，除了程序员没人看得懂。 相对于普通的工作流(同步、异步）来说，它主要的区别就是响应及时。它不会保存任何工作流信息，这也就意味着无法在监控页面查询到工作流状态。工作流会将所有运行状态和变量存在工作流相关的表中，当使用强制同步处理模式时，所有变量仅在内存里保存（实际上是一些RECORD类型的变量），当SESSION结束自动清除。 额外的一些限制有： 不能使用通知活动。 仅存在于单个Session中，不能Commit。 无法使用错误处理流程。 On Revisit仅允许LOOP属性。 不能使用主从活动。 不能并行处理。 不能使用各类延迟处理的活动，比如Defer、Wait。 不能使用工作流后台处理引擎。 不能记录到工作流表。 仅允许少量的API调用。 (更详细的说明，可以参考工作流API文档) 使用强制同步处理模式的方法是设置ITEM_TYPE为#SYNC，或者wf_engine.eng_synch。如果在不启动DEBUG跟踪的前提下试图诊断工作流，则可以通过指定一个唯一的ITEM_TYPE来进行操作，即返回到普通的同步模式。 对于复杂权限的判断、帐户的生成，或其他存在多个逻辑判断的情形，使用工作流比在代码中控制要清晰很多，和设计文档中的流程图几乎一致。]]></description>
			<content:encoded><![CDATA[<p>往往，对于工作流的强制同步(Forced Synchronous)处理模式，可以仅仅当做一段SQL代码来理解，事实上它也仅在一个SESSION内执行结束。对于某些逻辑处理，工作流图形化的设计方式非常容易理解，并且容易维护和扩展，多数情况下比PL/SQL代码更容易维护——我们的代码质量总是太差，除了程序员没人看得懂。</p>
<p>相对于普通的工作流(同步、异步）来说，它主要的区别就是响应及时。它不会保存任何工作流信息，这也就意味着无法在监控页面查询到工作流状态。工作流会将所有运行状态和变量存在工作流相关的表中，当使用强制同步处理模式时，所有变量仅在内存里保存（实际上是一些RECORD类型的变量），当SESSION结束自动清除。</p>
<p>额外的一些限制有：</p>
<ol>
<li>不能使用通知活动。</li>
<li>仅存在于单个Session中，不能Commit。</li>
<li>无法使用错误处理流程。</li>
<li>On Revisit仅允许LOOP属性。</li>
<li>不能使用主从活动。</li>
<li>不能并行处理。</li>
<li>不能使用各类延迟处理的活动，比如Defer、Wait。</li>
<li>不能使用工作流后台处理引擎。</li>
<li>不能记录到工作流表。</li>
<li>仅允许少量的API调用。</li>
</ol>
<p>(更详细的说明，可以参考工作流API文档)</p>
<p>使用强制同步处理模式的方法是设置ITEM_TYPE为#SYNC，或者wf_engine.eng_synch。如果在不启动DEBUG跟踪的前提下试图诊断工作流，则可以通过指定一个唯一的ITEM_TYPE来进行操作，即返回到普通的同步模式。</p>
<p>对于复杂权限的判断、帐户的生成，或其他存在多个逻辑判断的情形，使用工作流比在代码中控制要清晰很多，和设计文档中的流程图几乎一致。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.orafans.net/2009/01/workflow-force-synchronization-mode.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unsupported type EVENT ?</title>
		<link>http://www.orafans.net/2009/01/unsupported-type-event.html</link>
		<comments>http://www.orafans.net/2009/01/unsupported-type-event.html#comments</comments>
		<pubDate>Sat, 10 Jan 2009 10:25:45 +0000</pubDate>
		<dc:creator>Zeeno</dc:creator>
				<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://www.orafans.org/?p=213</guid>
		<description><![CDATA[碰到了估计不会再碰第二次的问题，记录一下。测试环境上载新的工作流时，系统报如下错误： 1406: Workflow definition contains unsupported feature, cannot be uploaded to this database. 1603: Unsupported type EVENT in attribute XMLTRANSFORM/NEWDOCUMENT 1603: Unsupported type EVENT in attribute XMLTRANSFORM/EVENT 1603: Unsupported type EXTJAVA in function WFSTD/XMLTRANSFORM 1603: Unsupported type EVENT in attribute XMLGETTAGVALUE/EVENT 1603: Unsupported type EXTJAVA in function WFSTD/XMLGETTAGVALUE 1603: Unsupported type EVENT in attribute XMLCOMPARETEXT/EVENT [...]]]></description>
			<content:encoded><![CDATA[<p>碰到了估计不会再碰第二次的问题，记录一下。测试环境上载新的工作流时，系统报如下错误：</p>
<pre class="brush:text">
1406: Workflow definition contains unsupported feature, cannot be uploaded to this database.
1603: Unsupported type EVENT in attribute XMLTRANSFORM/NEWDOCUMENT
1603: Unsupported type EVENT in attribute XMLTRANSFORM/EVENT
1603: Unsupported type EXTJAVA in function WFSTD/XMLTRANSFORM
1603: Unsupported type EVENT in attribute XMLGETTAGVALUE/EVENT
1603: Unsupported type EXTJAVA in function WFSTD/XMLGETTAGVALUE
1603: Unsupported type EVENT in attribute XMLCOMPARETEXT/EVENT
1603: Unsupported type EXTJAVA in function WFSTD/XMLCOMPARETEXT
1603: Unsupported type EVENT in attribute XMLCOMPARENUMBER/EVENT
1603: Unsupported type EXTJAVA in function WFSTD/XMLCOMPARENUMBER
1603: Unsupported type EVENT in attribute XMLCOMPAREDATE/EVENT
1603: Unsupported type EXTJAVA in function WFSTD/XMLCOMPAREDATE
1603: Unsupported type EVENT in attribute SETEVENTPROPERTY/EVENT
1603: Unsupported type EVENT in attribute GETEVENTPROPERTY/EVENT
1603: Unsupported type EVENT in attribute COMPAREEVENTPROPERTY/EVENT
</pre>
<p>这些Function和Attribute都来自于WFSTD，也就是不应该发生的错误。因为之前出现过配置问题，所以第一反应还是检查配置，无果。</p>
<p>于是想到了检查一下标准Definition清单，看看究竟是否支持EVENT和EXTJAVA。进入Diagnostics Tools，执行Workflow Definition Details检查，提示系统Workflow版本为2.5.0，不支持此操作，怪哉。</p>
<pre class="brush:sql">
SELECT * FROM wf_resources wr WHERE wr.NAME LIKE 'WF_VERSION'
</pre>
<p>显示果然是2.5.0，而实际的版本应当是2.6.0。手工修改之(为什么变成2.5.0，原因未知，但是应该不是正常情况下所能产生的，所以放心修改)。重新检查Diagnostics报告，发现上述错误信息中的Function都是被支持的。于是重新上载工作流定义，正常，问题解决。</p>
<p>看来Oracle仅仅是通过版本号来检查某特性是否被支持，而不是根据单独的特性来判断。</p>
<p>一点经验：Diagnostics Tools是个好东西啊，如果我早点用这个，能节省好多时间 <img src='http://www.orafans.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.orafans.net/2009/01/unsupported-type-event.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>工作流之超时处理</title>
		<link>http://www.orafans.net/2008/12/workflow-timeout.html</link>
		<comments>http://www.orafans.net/2008/12/workflow-timeout.html#comments</comments>
		<pubDate>Thu, 25 Dec 2008 01:49:56 +0000</pubDate>
		<dc:creator>Zeeno</dc:creator>
				<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://www.orafans.org/?p=209</guid>
		<description><![CDATA[在用Workflow Builder绘制工作流的时候，说简单点就是做两件事：定义Activity(活动)和Transition(移动)。Activity可以是复杂的逻辑运算，也可以是简单的判断、通知和反馈。对于需要回应的活动（比如审批意见），因为各种因素可能令响应者并未在预想的时间内做出反馈，这时就需要制定超时策略，否则，随着时间的推移，系统中将存在大量的遗留数据，这些数据很可能无法被清理。 例子：如果一天内未审批，则视为拒绝： 如果活动超时，工作流会标识该活动为超时状态。如果是通知，并且要求回应，则会发送一封取消通知的邮件给执行者(Performer)。对于是否接收取消通知邮件，取决于个人首选项是否选择接收电子邮件。如果是EBS内置版本，则可以在全局设置中禁止发送取消通知邮件。 如果活动定义了超时属性但是没有Timeout这个Transition流向下面的活动，则系统会根据该活动或父流程的相关定义来触发错误流程。对于超时处理，必须启动工作流后台流程，一个建议的频率是1到24小时。]]></description>
			<content:encoded><![CDATA[<p>在用Workflow Builder绘制工作流的时候，说简单点就是做两件事：定义Activity(活动)和Transition(移动)。Activity可以是复杂的逻辑运算，也可以是简单的判断、通知和反馈。对于需要回应的活动（比如审批意见），因为各种因素可能令响应者并未在预想的时间内做出反馈，这时就需要制定超时策略，否则，随着时间的推移，系统中将存在大量的遗留数据，这些数据很可能无法被清理。</p>
<p>例子：如果一天内未审批，则视为拒绝：<br />
<a title="ImageShack - Image And Video Hosting" href="http://img378.imageshack.us/my.php?image=20081225091923hz8.png" target="_blank"><img src="http://img378.imageshack.us/img378/3144/20081225091923hz8.png" border="0" alt="" /></a></p>
<p>如果活动超时，工作流会标识该活动为超时状态。如果是通知，并且要求回应，则会发送一封取消通知的邮件给执行者(Performer)。对于是否接收取消通知邮件，取决于个人首选项是否选择接收电子邮件。如果是EBS内置版本，则可以在全局设置中禁止发送取消通知邮件。</p>
<p>如果活动定义了超时属性但是没有Timeout这个Transition流向下面的活动，则系统会根据该活动或父流程的相关定义来触发错误流程。对于超时处理，必须启动工作流后台流程，一个建议的频率是1到24小时。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.orafans.net/2008/12/workflow-timeout.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Oracle 工作流优化概要</title>
		<link>http://www.orafans.net/2008/12/oracle-workflow-optimize.html</link>
		<comments>http://www.orafans.net/2008/12/oracle-workflow-optimize.html#comments</comments>
		<pubDate>Mon, 15 Dec 2008 07:17:19 +0000</pubDate>
		<dc:creator>Zeeno</dc:creator>
				<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://www.orafans.org/?p=204</guid>
		<description><![CDATA[对于Oracle工作流的优化方式主要分两大类，一类是流程设计上的优化，一类是数据库性能的优化。 流程设计优化： 仔细选择同步处理和异步处理模式。如果选择同步处理模式，则在提交后系统立即进行工作流处理，在流程结束前，前端程序将一直处于等待状态。如果选择异步处理模式，程序提交工作流后控制权立即返回，工作流后台引擎会根据设定的频率在后台进行处理。另外一种很少用到的处理模式是强制同步，系统不将数据插入数据库，直接用一个SQL，并且在一个Session中处理完毕。 尽量减少项目属性（通常用于存储全局变量）。当工作流启动时，系统会将这些属性全部拷贝一份，因而这会直接印影响工作流启动速度。另外，这些属性最好引用或保存静态变量，而不要去引用存放在数据库中的值。 尽量减少消息属性。如果需要在消息中存放不同的变量，也建议用最少的消息属性来实现，比如用Document来动态生成消息内容。 减少子流程，因为这需要消耗额外的DML操作和状态信息拷贝。 延迟活动。这是缩短响应时间最简单有效的办法之一，让一些需要较多处理时间的活动在后台交给工作流引擎处理，主流程则继续。 数据库性能优化： 分区。这通常在安装阶段即可进行，当然，在后期也可以进行。操作步骤可参考之前的文章《给工作流大表分区》。 清理过期数据。清理过期的运行时数据和WF_CONTROL数据，减少数据表大小。 最简单的优化方式，自然是在DB进行优化，比如定期清理。但是从设计角度考虑，同步、异步和延迟处理的配合使用，是更为得体的方式。各种方式，因时而异，因人而异。]]></description>
			<content:encoded><![CDATA[<p>对于Oracle工作流的优化方式主要分两大类，一类是流程设计上的优化，一类是数据库性能的优化。</p>
<p>流程设计优化：</p>
<ol>
<li>仔细选择同步处理和异步处理模式。<br />如果选择同步处理模式，则在提交后系统立即进行工作流处理，在流程结束前，前端程序将一直处于等待状态。如果选择异步处理模式，程序提交工作流后控制权立即返回，工作流后台引擎会根据设定的频率在后台进行处理。另外一种很少用到的处理模式是强制同步，系统不将数据插入数据库，直接用一个SQL，并且在一个Session中处理完毕。</li>
<li>尽量减少项目属性（通常用于存储全局变量）。当工作流启动时，系统会将这些属性全部拷贝一份，因而这会直接印影响工作流启动速度。另外，这些属性最好引用或保存静态变量，而不要去引用存放在数据库中的值。</li>
<li>尽量减少消息属性。如果需要在消息中存放不同的变量，也建议用最少的消息属性来实现，比如用Document来动态生成消息内容。</li>
<li>减少子流程，因为这需要消耗额外的DML操作和状态信息拷贝。</li>
<li>延迟活动。这是缩短响应时间最简单有效的办法之一，让一些需要较多处理时间的活动在后台交给工作流引擎处理，主流程则继续。</li>
</ol>
<p>数据库性能优化：</p>
<ol>
<li>分区。这通常在安装阶段即可进行，当然，在后期也可以进行。操作步骤可参考之前的文章《<a href="http://www.orafans.org/index.php/archives/198">给工作流大表分区</a>》。</li>
<li>清理过期数据。清理过期的运行时数据和WF_CONTROL数据，减少数据表大小。</li>
</ol>
<p>最简单的优化方式，自然是在DB进行优化，比如定期清理。但是从设计角度考虑，同步、异步和延迟处理的配合使用，是更为得体的方式。各种方式，因时而异，因人而异。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.orafans.net/2008/12/oracle-workflow-optimize.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>工作流之大表分区</title>
		<link>http://www.orafans.net/2008/12/workflow-table-partition.html</link>
		<comments>http://www.orafans.net/2008/12/workflow-table-partition.html#comments</comments>
		<pubDate>Fri, 12 Dec 2008 06:22:51 +0000</pubDate>
		<dc:creator>Zeeno</dc:creator>
				<category><![CDATA[Workflow]]></category>

		<guid isPermaLink="false">http://www.orafans.org/?p=198</guid>
		<description><![CDATA[如果打过了Patch 348000 (ORACLE APPLICATIONS RELEASE 11.5.10.2 MAINTENANCE PACK)，那么工作流管理员指南(115wfag.pdf)里的对于关键表分区的介绍就过时了。进去看wfupartb.sql，你可以看到它提示已经被新的程序所取代。 新的文件是wfpart.sql，在 $FND_TOP/patch/115/sql 路径下。参考SQL文件头的使用说明执行，会在utl_file_dir目录（需要手工指定一个目录）下生成wfpart.sql，这才是具体的分区创建语句。不过需要留意的是，默认生成的wfpart.sql有个BUG（参见Note:329738.1），创建WF_ITEM_ACTIVITY_STATUSES_N4这个索引时会报错并自动终止退出，因此需要先手工修改wfpart.sql，加上以下Index创建语句： create index WF_ITEM_ACTIVITY_STATUSES_N4 on WF_ITEM_ACTIVITY_STATUSES (ASSIGNED_USER,ITEM_TYPE) pctfree 10 initrans 10 tablespace [your_table_space] storage (initial 40K next 1048576 freelists 32 freelist groups 4 pctincrease 0 ) logging; 注意：需要注释掉原来的Alter语句： alter index WFN_WF_ITEM_ACTIVITY_STATUSES_ rename to WF_ITEM_ACTIVITY_STATUSES_N4 由于执行的都是DDL语句，因此一旦出错将无法自动回滚，在执行前需要备份关键表，分别为： WF_ITEM_ACTIVITY_STATUSES WF_ITEM_ACTIVITY_STATUSES_H WF_ITEM_ATTRIBUTE_VALUES WF_ITEMS 如果是在等到感觉到性能问题了再来进行分区，等待的过程将相当漫长……如果想要撤销分区，则以同样方式执行wfunpart.sql。]]></description>
			<content:encoded><![CDATA[<p>如果打过了Patch 348000 (ORACLE APPLICATIONS RELEASE 11.5.10.2 MAINTENANCE PACK)，那么工作流管理员指南(115wfag.pdf)里的对于关键表分区的介绍就过时了。进去看wfupartb.sql，你可以看到它提示已经被新的程序所取代。</p>
<p>新的文件是wfpart.sql，在 $FND_TOP/patch/115/sql 路径下。参考SQL文件头的使用说明执行，会在utl_file_dir目录（需要手工指定一个目录）下生成wfpart.sql，这才是具体的分区创建语句。不过需要留意的是，默认生成的wfpart.sql有个BUG（参见Note:329738.1），创建WF_ITEM_ACTIVITY_STATUSES_N4这个索引时会报错并自动终止退出，因此需要先手工修改wfpart.sql，加上以下Index创建语句：</p>
<pre class="brush:sql">
create index WF_ITEM_ACTIVITY_STATUSES_N4
 on WF_ITEM_ACTIVITY_STATUSES (ASSIGNED_USER,ITEM_TYPE)
 pctfree 10
 initrans 10
 tablespace [your_table_space]
 storage (initial 40K next 1048576
 freelists 32 freelist groups 4
 pctincrease 0 )
 logging;</pre>
<p>注意：需要注释掉原来的Alter语句：</p>
<pre class="brush:sql">
alter index WFN_WF_ITEM_ACTIVITY_STATUSES_ rename to WF_ITEM_ACTIVITY_STATUSES_N4</pre>
<p>由于执行的都是DDL语句，因此一旦出错将无法自动回滚，在执行前需要备份关键表，分别为：</p>
<ol>
<li>WF_ITEM_ACTIVITY_STATUSES</li>
<li>WF_ITEM_ACTIVITY_STATUSES_H</li>
<li>WF_ITEM_ATTRIBUTE_VALUES</li>
<li>WF_ITEMS</li>
</ol>
<p>如果是在等到感觉到性能问题了再来进行分区，等待的过程将相当漫长……如果想要撤销分区，则以同样方式执行wfunpart.sql。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.orafans.net/2008/12/workflow-table-partition.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
