dev2dev 首页 > 资源中心 > 技术文章
客户端调用WLI81 JPD的方法总结 第一部分
目录
说明
在WLI81中,一个Process(*.JPD) 可以生成WSDL文件,Process Control,Service Broker Control。所以客户端可以有多种方式调用该JPD。在WLI81中客户端可以通过下面这么多种方法调用一个JPD。

以上每种方式都有其自己的特点以及一定的适用范围,下面分别说明。
通过WLI81提供的JAVA API直接调用该JPD
通过BEA提供的mbean来调用。但是,启动工作流,必须要有管理员的权限,也就是必须获得管理员的上下文.执行该段代码的用户必须属于Administrator 组
try
{
String fd[] = new String[1];
fd[0]="1111";
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
p.put(Context.PROVIDER_URL, "t3://127.0.0.1");
p.put(Context.SECURITY_PRINCIPAL,"weblogic");
p.put(Context.SECURITY_CREDENTIALS,"weblogic");
Context ctx = new InitialContext(p);
RemoteWorklistManagerHome pwmh=(RemoteWorklistManagerHome)ctx.lookup("RemoteWorklistManagerBean");
RemoteWorklistManager rwmb=(RemoteWorklistManager)pwmh.create();
String s=rwmb.startProcess("/myappWeb/processes/process.jpd","clientRequest", fd);
}
catch(Exception e)
{
e.printStackTrace();
}
可以在JSP,JAVA客户端或PAGE FLOW中采用该方式直接调用JPD,这种方式比较简单直接。
使用该方式,调用JPD的CLIENT端必须和JPD在同一个DOMAIN中才可以.如果不在同一个DOMAIN,会抛出:
<2004-12-11 下午10时23分36秒 CST> <Error> <WLW> <000000> <Unable to find source
file myappWeb\processes\process.jpd>
com.bea.wli.worklist.api.ManagementException: Failed to get DispFile for service
/myappWeb/processes/process.jpd
at com.bea.wli.worklist.beans.session.RemoteWorklistManagerBean.startPro
cess(RemoteWorklistManagerBean.java:3702)
at com.bea.wli.worklist.beans.session.RemoteWorklistManagerBean_us8t1c_E
OImpl.startProcess(RemoteWorklistManagerBean_us8t1c_EOImpl.java:2168)
at com.bea.wli.worklist.beans.session.RemoteWorklistManagerBean_us8t1c_E
OImpl_WLSkel.invoke(Unknown Source)
如果把String s=rwmb.startProcess("/myappWeb/processes/process.jpd","clientRequest", fd);改为
String s=rwmb.startProcess("http://localhost:7001/myappWeb/processes/process.jpd ","clientRequest", fd);
仍然会抛出:
<2004-12-11 下午10时23分36秒 CST> <Error> <WLW> <000000> <Unable to find source
file http://localhost:7001/myappWeb/processes/process.jpd >
com.bea.wli.worklist.api.ManagementException: Failed to get DispFile for service
/myappWeb/processes/process.jpd
at com.bea.wli.worklist.beans.session.RemoteWorklistManagerBean.startPro
cess(RemoteWorklistManagerBean.java:3702)
at com.bea.wli.worklist.beans.session.RemoteWorklistManagerBean_us8t1c_E
OImpl.startProcess(RemoteWorklistManagerBean_us8t1c_EOImpl.java:2168)
at com.bea.wli.worklist.beans.session.RemoteWorklistManagerBean_us8t1c_E
OImpl_WLSkel.invoke(Unknown Source)
把JPD转化为一个Web Service进行调用
在Workshop中可以为一个JPD生成一个WSDL文件,然后客户端就可以以调用Web Service的方式调用该JPD。可以在支持Web Service的客户端中采用这种方式调用JPD。如在.NET平台上调用WLI81上的JPD就可以采用这种方式。
如果是在WORKSHOP中通过这种方式调用,可根据该WSDL文件生成SERVICE CONTROL,然后根据该SERVICE CONTROL还可以自动生成PAGE FLOW。如下图:

也可以在JSP中直接根据JPD生成的WSDL生成的SERVICE CONTROL,参考代码如下:
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ page import="NewFolder.JmsProcessControl"%>
<%@ taglib uri="netui-tags-databinding.tld" prefix="netui-data"%>
<%@ taglib uri="netui-tags-html.tld" prefix="netui"%>
<%@ taglib uri="netui-tags-template.tld" prefix="netui-template"%>
<netui-data:declareControl type="NewFolder.JmsProcessControl" controlId="JmsProcessControl"></netui-data:declareControl>
<%
JmsProcessControl jmsCtrl= (JmsProcessControl)pageContext.getAttribute("JmsProcessControl");
String ret=jmsCtrl.clientRequestwithReturn("eeeeeeeeeee");
System.out.println("r222et=" + ret);
%>
调用该JPD的CLIENT和该JPD可以不在同一个DOMAIN中。应该先根据该SERVICE CONTROL生成一个PAGEFLOW,然后在JSP中直接调用该SERVICE CONTROL才能够成功。不知道为怎么?不清楚通过PAGEFLOW和直接通过JSP这两种方式,性能有怎么差别?

如果没有先根据该SERVICE CONTROL生成一个PAGEFLOW,在JSP中无法成功调用该SERVICE CONTROL会抛出如下EXCEPTION:不管是在PRODUCT MODE还是在DEVELOP
<2004-12-18 下午09时20分06秒 CST> <Error> <HTTP> <BEA-101020> <[ServletContext(i
d=5238181,name=webproj,context-path=/webproj)] Servlet failed with Exception
java.lang.RuntimeException: com.bea.wlw.runtime.core.dispatcher.ServiceHandleExc
eption: Service at /webproj/NewFolder/JmsProcessControl.jcx not found
at com.bea.wlw.runtime.core.dispatcher.WlwProxyImpl._invoke(Lcom.bea.wlw
.runtime.core.request.ExecRequest;)Ljava.lang.Object;(WlwProxyImpl.java:345)
at com.bea.wlw.runtime.core.dispatcher.WlwProxyImpl.invoke(Ljava.lang.Ob
ject;Ljava.lang.reflect.Method;[Ljava.lang.Object;)Ljava.lang.Object;(WlwProxyIm
pl.java:315)
at $Proxy8.clientRequestwithReturn(Ljava.lang.String;)Ljava.lang.String;
(Unknown Source)
at jsp_servlet._newfolder.__untitled._jspService(Ljavax.servlet.http.Htt
pServletRequest;Ljavax.servlet.http.HttpServletResponse;)V(Untitled.jsp:10)
at weblogic.servlet.jsp.JspBase.service(Ljavax.servlet.ServletRequest;Lj
把JPD转化为一个Process Control,进行调用
可以通过把JPD转化为Process Control,然后调用Process Control的clientRequest()方法调用一个JPD。如在Workshop开发环境中。可以通过下面的方法在一个JSP中以Process Control的方式调用一个JPD。
在一个jsp的source view中,将要在该JSP中调用的Process Control拖入该jsp,然后可以通过pageContext得到Control的实例:调用该Process Control的clientRequest()启动该Process.
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ taglib uri="netui-tags-databinding.tld" prefix="netui-data"%>
<%@ taglib uri="netui-tags-html.tld" prefix="netui"%>
<%@ taglib uri="netui-tags-template.tld" prefix="netui-template"%>
<netui-data:declareControl type="process.demo.approveControl" controlId="approveControl"></netui-data:declareControl>
<%
approveControl ac=(lapproveControl)pageContext.getAttribute("approveControl");
ac. clientRequest (applyid);
%>
调用该JPD的客户端必须与该JPD位于同一个WLI Domain中。它允许一个工作流(JPD),Web Service(JWS)或pageflow(JPF)向一个工作流(Target JPD)发出调用请求,同时也可以接收Target JPD的Callback。Process Control通常用于父流程调用子流程,事务上下文通过Process Control从父流程传递到子流程中,即Target JPD与client处于同一个事务中。
把该JPD转化为一个Service Broker Control进行调用
Service Broker,从名字就可以知道它实现了对服务调用请求消息的代理功能。换而言之,服务代理接收服务调用请求消息,然后过滤服务调用请求消息,最后根据服务调用请求消息调用相应的服务。Service Broker一般用于:
- 通过参数实现动态服务调用
- 在流程中实现子流程调用
- 实现企业间的应用集成
以下通过一个例子说明Service Broker Control的使用,场景为Process A通过Service Broker Control调用Process B,二者位于不同的两个Domain中。由于Serivce Broker Control是一个Dymamic Control,可以在WliConsole中设置Selector来实现依照输入参数选择调用不同的JPD,从而实现对于Target JPD的动态调用。

- 生成Target JPD的WSDL文件

自动生成的WSDL文件中location部分默认标明localhost,为了在Client端可以找到Target JPD,需要将其中URL部分中的localhost更换为本机ip或机器名。
… …
<service name="paticipant">
<port name="paticipantSoap" binding="s0:paticipantSoap">
<soap:address location="http://CAITAO:7001/SBprocess/processes/paticipant.jpd"/>
</port>
</service>
… …
- 在Client端的Application中import Target JPD的WSDL文件
- 基于上述WSDL文件产生一个Service Broker Control,Process A即通过此Service Broker Control来调用Process B

- Service Broker Control在生成时需要设置一个Xquery,可以实现对clientRequest参数的抽取,从而依照用户输入参数调用不同的Target JPD(这一点在后面的Dynamic Selector会提及)。

- 生成的Service Broker Control有一个default的Http-url,说明默认的Service Broker Control调用此Url标识的Target JPD

Process A中只要调用配置好的Service Broker Control,即可调用http-url中指定的JPD资源。
- Service Broker是一个Dynamic Control,可以通过wliconsole来设置selector,达到依照用户输入来分发请求到不同的Target JPD的目的。具体实施如下:
- 屏蔽default的Http-Url,即在Service Broker Control的Property Editor中消去默认的Http-url。这一点非常重要,因为默认的http-url中指定的JPD资源可以屏蔽在wliconsole中Dynamic Selector指定的资源。
- 进入wliconsole->Process Configuration->View Dynamic Controls,定位您当前需要设置Dynamic Selector的process

- 选择Add Selector来添加选择条件

例如筛选条件为:若Selector Value为‘liangyi’时,调用URI为
http://10.130.2.139:7001/SBprocess/processes/paticipant.jpd 的Target JPD,修改后显示如下:

经过上述设置,只有当clientRequest中的XmlDocument经过Xquery查询后的字段值为‘liangyi’(此例中字段为Customer_Name)时才会调用End Point表明的Target JPD,其他的请求不能调用此Target JPD。
采用这种方式,调用该JPD的CLIENT和该JPD可以不在同一个DOMAIN中。
通过HTTP,HTTPS方式直接访问一个JPD所对应的URL进行调用


可以通过HTTP,HTTPS方式直接访问该JPD对应的URL。来调用该JPD,并可取的返回的结果。
只要是支持HTTP,HTTPS的客户端都可以通过该方式调用JPD。如可以在C,C++环境中通过该方式调用一个JPD。其代码如下:
<%@ page import="java.net.HttpURLConnection"%>
<%@ page import="java.net.URL"%>
<%@ page import="java.net.URLConnection"%>
<%
HttpURLConnection c = null;
InputStream is = null;
OutputStream os = null;
StringBuffer b = new StringBuffer();
try {
URL url = new URL("http://localhost:8001/Case_2_Web/processes/JmsProcess.jpd/clientRequestwithReturn");
c = (HttpURLConnection)url.openConnection();
c.setRequestMethod("POST");
c. setDoOutput(true);
//c.setRequestProperty("IF-Modified-Since", "29 Dec 2001 15:17:19 GMT");
//c.setRequestProperty("User-Agent","Profile/MIDP-1.0 Configuration/CLDC-1.0");
//c.setRequestProperty("Content-Language", "en-CA");
c.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
os = c.getOutputStream();
os.write(("reqStr=xxxxxxxxxxxxxx").getBytes());
os.flush();
is = c.getInputStream();
int ch;
while ((ch = is.read()) != -1)
{
b.append((char) ch);
System.out.print((char)ch);
}
}
finally
{
if(is!= null) {
is.close();
}
if(os != null) {
os.close();
}
if(c != null) {
c.disconnect();
}
}
%>
黑体部分也可以替换成下面这段代码,效率不知道会不会好些??
InputStreamReader isr = new InputStreamReader(c.getInputStream());
char[] resultBytes = new char[1024];
int rcount = isr.read(resultBytes, 0, 1024);
StringBuffer resp = new StringBuffer();
while(rcount!=-1)
{
resp = soapResponse.append(resultBytes, 0 , rcount);
rcount = isr.read(resultBytes, 0, 1024);
}
System.out.println("response: " + resp);
采用这种方式,其返回的结果是下面这种形式

需要从该XML中提取需要的结果。可以通过返回XML格式的字符串,然后对它进行解析。
如果被调用的JPD返回的是STRING,那么在CONSOLE上打出来的结果如下,不知道为怎么<>显示成其他的。

但如果被调用的JPD返回的是XMLOBJECT。那么在CONSOLE上打出来的结果如下:

然后可以通过如下方式进行解析:
int sp = this.incomeMSG.indexOf("<order_id>", 0) + 10;
int ep = this.incomeMSG.indexOf("</order_id>", sp);
String res_order_id = this.incomeMSG.substring(sp, ep);
System.out.println("order_id: " + res_order_id);
sp = this.incomeMSG.indexOf("<exe_province>", 0) + 14;
ep = this.incomeMSG.indexOf("</exe_province>", sp);
String res_exe_province = this.incomeMSG.substring(sp, ep);
System.out.println("exe_province: " + res_exe_province);
更好的方式是直接返回带相应SCHEMA的XML。如:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://ccbpoc.bea.com/BBOSS"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://ccbpoc.bea.com/BBOSS" elementFormDefault="qualified">
<xs:element name="BBOSS">
<xs:complexType>
<xs:sequence>
<xs:element name="order_id" type="xs:string"/>
<xs:element name="code" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
public com.bea.ccbpoc.bboss.BBOSSDocument clientReturn()
{
try{
bbb = BBOSSDocument.Factory.newInstance();
BBOSSDocument.BBOSS myb;
myb = bbb.addNewBBOSS();
myb.setCode("11111");
myb.setOrderId("ssssssssss");
}
catch(Exception e)
{
e.printStackTrace();
}
//#START: CODE GENERATED - PROTECTED SECTION - you can safely add code above this comment in this method. #//
// return
return bbb;
//#END : CODE GENERATED - PROTECTED SECTION - you can safely add code below this comment in this method. #//
}

- 如果不需要在程序中得到JPD的返回值,可以采用更简单的方式:如:
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%
String bureau= request.getParameter("inputStr");
if (bureau != null)
{
%>
<jsp:forward page="/processes/addnewSI.jpd/clientRequest">
</jsp:forward>
<%
}
else
{
%>
<form name="action_form" method="POST" action="./addnewSI.jsp">
<table align="center" width="%50" border="1">
<tr>
<td> order:</td>
<td>
<textarea cols=100 name=inputStr rows=10 style="border:solid 1px #464646"></textarea>
</td>
</tr>
<tr>
<td align="center"><input type=submit value=Test name="submit">
</td>
<td align="center"><input type=reset value=Reset name="reset">
</td>
</tr>
</table>
</form>
<%
}
%>
或直接调用:
<form name="action_form" method="POST" action="/processes/addnewSI.jpd/clientRequest ">
<table align="center" width="%50" border="1">
<tr>
<td> order:</td>>
<textarea cols=100 name=inputStr rows=10 style="border:solid 1px #464646"></textarea> </td>
</tr>
<tr>
<td align="center"><input type=submit value=Test name="submit">
</td>
<td align="center"><input type=reset value=Reset name="reset">
</td>
</tr>
</table>
</form>
注意:
<textarea cols=100 name=inputStr rows=10 style="border:solid 1px #464646"></textarea> 中的NAME: inputStr必须和JPD中的输入参数名一样.

该种方式只能在该CLIENT对应的JSP和该JPD在同一个DOMAIN中使用。在IE中会直接看该调用的结果。当在应用程序中无法得到JPD传回的结果.

- 如果CLIENT对应的JSP和该JPD不在同一个DOMAIN,可采用如下方式:response.sendRedirect("http://129.200.9.92:7601/Case_2_Web/processes/JmsProcess.jpd/clientRequestwithReturn?reqStr= dddddddddddd");

采用这种方式,JPD的输入参数只能采用STRING 方式,可以是一个或多个STRING,如果JPD的输入参数是XML格式,在CLIENT拼一个XML字符串,在JPD那里仍然无法正常传入。会报:
<?xml version="1.0" encoding="UTF-8"?><taskInfo xmlns="http://ubsspoc.bea.com/taskInfo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><owner>xcjing </ow
ner><dueDate> 20051212</dueDate><fromId>1</fromId> <toId>100</toId></taskInfo>
<2005-1-12 下午05时32分20秒 CST> <Error> <WLW> <000000> <Returning HTTP=500 dueto httpWriteFault msg=null,detail=null
com.bea.wlw.runtime.core.request.ResponseValidationException: java.lang.RuntimeException: Protocol 'form-get' not available on this operation. [ServiceException
]
at com.bea.wlw.runtime.core.bean.SyncDispatcherBean.invoke(Lcom.bea.wlw.runtime.core.request.Request;)Lcom.bea.wlw.runtime.core.request.Response;(SyncDi
spatcherBean.java:258)
本文第二部分:http://dev2dev.bea.com.cn/techdoc/20060405760.html
| 作者简介 |
|
dev2dev ID: xcjing,BEA 资深技术顾问,加入BEA中国多年,在门户技术、RFID解决方案上有着丰富的经验。 |
作者其它文章
|