1 Eylül 2009 Salı

bpel fault handling

Understanding fault handling mechanism of bpel took time for me, so lets note down the issue..

i want to explain bpel fault handling in 2 steps.. In step 1, there is a bpel process which does nothing except for throwing an exception. In step 2, there is a sample web service throwing a user defined exception and bpel catches and throws that exception..

Process without web service :

Here are the files for the bpel module:
FaultWsdl.wsdl


<?xml version="1.0" encoding="UTF-8"?>
<definitions name="wsdl" targetNamespace="http://j2ee.netbeans.org/wsdl/wsdl"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://j2ee.netbeans.org/wsdl/wsdl"
xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns0="http://xml.netbeans.org/schema/schema">
<types>
<xsd:schema targetNamespace="http://j2ee.netbeans.org/wsdl/wsdl">
<xsd:import schemaLocation="schema.xsd" namespace="http://xml.netbeans.org/schema/schema"/>
</xsd:schema>
</types>
<message name="wsdlOperationRequest">
<part name="part1" type="xsd:string"/>
</message>
<message name="wsdlOperationResponse">
<part name="part1" type="xsd:string"/>
</message>
<message name="wsdlOperationFault">
<part name="part1" element="ns0:faultstr"/>
</message>
<portType name="wsdlPortType">
<operation name="wsdlOperation">
<input name="input1" message="tns:wsdlOperationRequest"/>
<output name="output1" message="tns:wsdlOperationResponse"/>
<fault name="fault1" message="tns:wsdlOperationFault"/>
</operation>
</portType>
<binding name="wsdlBinding" type="tns:wsdlPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="wsdlOperation">
<soap:operation/>
<input name="input1">
<soap:body use="literal" namespace="http://j2ee.netbeans.org/wsdl/wsdl"/>
</input>
<output name="output1">
<soap:body use="literal" namespace="http://j2ee.netbeans.org/wsdl/wsdl"/>
</output>
<fault name="fault1">
<soap:fault use="literal" name="fault1" namespace="http://j2ee.netbeans.org/wsdl/wsdl"/>
</fault>
</operation>
</binding>
<service name="wsdlService">
<port name="wsdlPort" binding="tns:wsdlBinding">
<soap:address location="http://localhost:${HttpDefaultPort}/wsdlService/wsdlPort"/>
</port>
</service>
<plnk:partnerLinkType name="wsdl">
<!-- A partner link type is automatically generated when a new port type is added. Partner link types are used by BPEL processes.
In a BPEL process, a partner link represents the interaction between the BPEL process and a partner service. Each partner link is associated with a partner link type.
A partner link type characterizes the conversational relationship between two services. The partner link type can have one or two roles.-->
<plnk:role name="wsdlPortTypeRole" portType="tns:wsdlPortType"/>
</plnk:partnerLinkType>
</definitions>


schema.xsd i think jaxws wants the schema in a seperate file than the wsdl, at least netbeans web service client generation wizard does!


<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://xml.netbeans.org/schema/schema"
xmlns:tns="http://xml.netbeans.org/schema/schema"
elementFormDefault="qualified">
<xsd:element name="faultstr" type="xsd:string"></xsd:element>
</xsd:schema>


FaultProcess.bpel


<?xml version="1.0" encoding="UTF-8"?>
<process
name="FaultProcess"
targetNamespace="http://enterprise.netbeans.org/bpel/BpelFault1/Process1"
xmlns="http://docs.oasis-open.org/wsbpel/2.0/process/executable"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:sxt="http://www.sun.com/wsbpel/2.0/process/executable/SUNExtension/Trace"
xmlns:sxed="http://www.sun.com/wsbpel/2.0/process/executable/SUNExtension/Editor"
xmlns:tns="http://enterprise.netbeans.org/bpel/BpelFault1/Process1">
<import namespace="http://j2ee.netbeans.org/wsdl/wsdl" location="FaultWsdl.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"/>
<partnerLinks>
<partnerLink name="PartnerLink1" xmlns:tns="http://j2ee.netbeans.org/wsdl/wsdl" partnerLinkType="tns:wsdl" myRole="wsdlPortTypeRole"/>
</partnerLinks>
<variables>
<variable name="Fault1FaultVar" xmlns:tns="http://j2ee.netbeans.org/wsdl/wsdl" messageType="tns:wsdlOperationFault"/>
<variable name="WsdlOperationOut" xmlns:tns="http://j2ee.netbeans.org/wsdl/wsdl" messageType="tns:wsdlOperationResponse"/>
<variable name="WsdlOperationIn" xmlns:tns="http://j2ee.netbeans.org/wsdl/wsdl" messageType="tns:wsdlOperationRequest"/>
</variables>
<sequence>
<receive name="Receive1" createInstance="yes" partnerLink="PartnerLink1" operation="wsdlOperation" xmlns:tns="http://j2ee.netbeans.org/wsdl/wsdl" portType="tns:wsdlPortType" variable="WsdlOperationIn"/>
<assign name="Assign1">
<copy>
<from>'This error is thrown from the bpel process'</from>
<to variable="Fault1FaultVar" part="part1"/>
</copy>
<copy>
<from variable="Fault1FaultVar" part="part1"/>
<to variable="WsdlOperationOut" part="part1"/>
</copy>
</assign>
<reply name="Reply1" partnerLink="PartnerLink1" operation="wsdlOperation" xmlns:tns="http://j2ee.netbeans.org/wsdl/wsdl" portType="tns:wsdlPortType" faultName="tns:fault1" variable="Fault1FaultVar"/>
</sequence>
</process>


and offcourse the client call code:


try {
org.netbeans.j2ee.wsdl.wsdl.WsdlService service = new org.netbeans.j2ee.wsdl.wsdl.WsdlService();
org.netbeans.j2ee.wsdl.wsdl.WsdlPortType port = service.getWsdlPort();
javax.xml.ws.Holder part1 = new javax.xml.ws.Holder();
part1.value = new String("test");
port.wsdlOperation(part1);
} catch (org.netbeans.j2ee.wsdl.wsdl.WsdlOperationFault ex) {
System.out.println("fault: " + ex.getFaultInfo() );
}


The expected output is :


fault: This error is thrown from the bpel process


and done :) However, when web service thrown exceptions are considered, not so easy :(

Process catching exception thrown by invoked web service:

The sample web service:

MyWebService.java


package ws;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

@WebService()
public class MyWebService {

@WebMethod(operationName = "operation")
public String operation(@WebParam(name = "parameter")
String parameter) throws MyException {
throw new MyException("Exception thrown from web service :) ");
}
}


and the exception class..

MyException.java


package ws;

public class MyException extends Exception {
private String errorCode;

public MyException() {
}

public MyException(String msg) {
super(msg);
}

public String getErrorCode() {
return errorCode;
}

public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
}


Now the bpel module files:

FaultCatchProcess.bpel


<?xml version="1.0" encoding="UTF-8"?>
<process
name="FaultCatchProcess"
targetNamespace="http://enterprise.netbeans.org/bpel/BpelFault2/FaultCatchProcess"
xmlns="http://docs.oasis-open.org/wsbpel/2.0/process/executable"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:sxt="http://www.sun.com/wsbpel/2.0/process/executable/SUNExtension/Trace"
xmlns:sxed="http://www.sun.com/wsbpel/2.0/process/executable/SUNExtension/Editor"
xmlns:tns="http://enterprise.netbeans.org/bpel/BpelFault2/FaultCatchProcess" xmlns:ns0="http://ws/">
<import namespace="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" location="FaultCatchWsdl.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"/>
<import namespace="http://enterprise.netbeans.org/bpel/MyWebServiceServiceWrapper" location="MyWebServiceServiceWrapper.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"/>
<import namespace="http://ws/" location="MyWebServiceService.wsdl" importType="http://schemas.xmlsoap.org/wsdl/"/>
<partnerLinks>
<partnerLink name="PartnerLink2" xmlns:tns="http://enterprise.netbeans.org/bpel/MyWebServiceServiceWrapper" partnerLinkType="tns:MyWebServiceLinkType" partnerRole="MyWebServiceRole"/>
<partnerLink name="PartnerLink1" xmlns:tns="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" partnerLinkType="tns:FaultCatchWsdl" myRole="FaultCatchWsdlPortTypeRole"/>
</partnerLinks>
<variables>
<variable name="FaultToBpel" xmlns:tns="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" messageType="tns:FaultCatchWsdlOperationFault"/>
<variable name="OperationOut" xmlns:tns="http://ws/" messageType="tns:operationResponse"/>
<variable name="OperationIn" xmlns:tns="http://ws/" messageType="tns:operation"/>
<variable name="FaultCatchWsdlOperationOut" xmlns:tns="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" messageType="tns:FaultCatchWsdlOperationResponse"/>
<variable name="FaultCatchWsdlOperationIn" xmlns:tns="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" messageType="tns:FaultCatchWsdlOperationRequest"/>
</variables>
<faultHandlers>
<catch faultName="ns0:MyException" faultVariable="myExceptionFromWs" faultMessageType="ns0:MyException">
<sequence name="Sequence1">
<assign name="Assign3">
<copy>
<from variable="myExceptionFromWs" part="fault"/>
<to variable="FaultToBpel" part="part1"/>
</copy>
</assign>
<reply name="Reply2" partnerLink="PartnerLink1" operation="FaultCatchWsdlOperation" xmlns:tns="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" portType="tns:FaultCatchWsdlPortType" faultName="tns:fault1" variable="FaultToBpel"/>
</sequence>
</catch>
</faultHandlers>
<sequence>
<receive name="Receive1" createInstance="yes" partnerLink="PartnerLink1" operation="FaultCatchWsdlOperation" xmlns:tns="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" portType="tns:FaultCatchWsdlPortType" variable="FaultCatchWsdlOperationIn"/>
<assign name="Assign1">
<copy>
<from variable="FaultCatchWsdlOperationIn" part="part1"/>
<to variable="OperationIn" part="parameters"/>
</copy>
</assign>
<invoke name="Invoke1" partnerLink="PartnerLink2" operation="operation" xmlns:tns="http://ws/" portType="tns:MyWebService" inputVariable="OperationIn" outputVariable="OperationOut"/>
<assign name="Assign2">
<copy>
<from variable="OperationOut" part="parameters"/>
<to variable="FaultCatchWsdlOperationOut" part="part1"/>
</copy>
</assign>
<reply name="Reply1" partnerLink="PartnerLink1" operation="FaultCatchWsdlOperation" xmlns:tns="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" portType="tns:FaultCatchWsdlPortType" variable="FaultCatchWsdlOperationOut"/>
</sequence>
</process>


FaultCatchWsdl.wsdl


<?xml version="1.0" encoding="UTF-8"?>
<definitions name="FaultCatchWsdl" targetNamespace="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl" xmlns:ns="http://ws/" xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<types>
<xsd:schema targetNamespace="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl">
<xsd:import namespace="http://ws/" schemaLocation="MyWebServiceService.xsd"/>
</xsd:schema>
</types>
<message name="FaultCatchWsdlOperationRequest">
<part name="part1" type="ns:operation"/>
</message>
<message name="FaultCatchWsdlOperationResponse">
<part name="part1" type="ns:operationResponse"/>
</message>
<message name="FaultCatchWsdlOperationFault">
<part name="part1" element="ns:MyException"/>
</message>
<portType name="FaultCatchWsdlPortType">
<operation name="FaultCatchWsdlOperation">
<input name="input1" message="tns:FaultCatchWsdlOperationRequest"/>
<output name="output1" message="tns:FaultCatchWsdlOperationResponse"/>
<fault name="fault1" message="tns:FaultCatchWsdlOperationFault"/>
</operation>
</portType>
<binding name="FaultCatchWsdlBinding" type="tns:FaultCatchWsdlPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="FaultCatchWsdlOperation">
<soap:operation/>
<input name="input1">
<soap:body use="literal" namespace="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl"/>
</input>
<output name="output1">
<soap:body use="literal" namespace="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl"/>
</output>
<fault name="fault1">
<soap:fault use="literal" name="fault1" namespace="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl"/>
</fault>
</operation>
</binding>
<service name="FaultCatchWsdlService">
<port name="FaultCatchWsdlPort" binding="tns:FaultCatchWsdlBinding">
<soap:address location="http://localhost:${HttpDefaultPort}/FaultCatchWsdlService/FaultCatchWsdlPort"/>
</port>
</service>
<plnk:partnerLinkType name="FaultCatchWsdl">
<!-- A partner link type is automatically generated when a new port type is added. Partner link types are used by BPEL processes.
In a BPEL process, a partner link represents the interaction between the BPEL process and a partner service. Each partner link is associated with a partner link type.
A partner link type characterizes the conversational relationship between two services. The partner link type can have one or two roles.-->
<plnk:role name="FaultCatchWsdlPortTypeRole" portType="tns:FaultCatchWsdlPortType"/>
</plnk:partnerLinkType>
</definitions>


The following wsdl and xsd are local copies for the web service wsdl..

MyWebServiceService.wsdl


<?xml version="1.0" encoding="UTF-8"?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.3.1-hudson-749-SNAPSHOT. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.3.1-hudson-749-SNAPSHOT. -->
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://ws/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://ws/" name="MyWebServiceService">
<types>
<xsd:schema>
<xsd:import namespace="http://ws/" schemaLocation="MyWebServiceService.xsd"></xsd:import>
</xsd:schema>
</types>
<message name="operation">
<part name="parameters" element="tns:operation"></part>
</message>
<message name="operationResponse">
<part name="parameters" element="tns:operationResponse"></part>
</message>
<message name="MyException">
<part name="fault" element="tns:MyException"></part>
</message>
<portType name="MyWebService">
<operation name="operation">
<input message="tns:operation"></input>
<output message="tns:operationResponse"></output>
<fault message="tns:MyException" name="MyException"></fault>
</operation>
</portType>
<binding name="MyWebServicePortBinding" type="tns:MyWebService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"></soap:binding>
<operation name="operation">
<soap:operation soapAction=""></soap:operation>
<input>
<soap:body use="literal"></soap:body>
</input>
<output>
<soap:body use="literal"></soap:body>
</output>
<fault name="MyException">
<soap:fault name="MyException" use="literal"></soap:fault>
</fault>
</operation>
</binding>
<service name="MyWebServiceService">
<port name="MyWebServicePort" binding="tns:MyWebServicePortBinding">
<soap:address location="http://localhost:8080/BpelFaultWS1/MyWebServiceService"></soap:address>
</port>
</service>
</definitions>


MyWebServiceService.xsd


<?xml version="1.0" encoding="UTF-8"?><!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is JAX-WS RI 2.1.3.1-hudson-749-SNAPSHOT. -->
<xs:schema xmlns:tns="http://ws/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" targetNamespace="http://ws/">

<xs:element name="MyException" type="tns:MyException"></xs:element>

<xs:element name="operation" type="tns:operation"></xs:element>

<xs:element name="operationResponse" type="tns:operationResponse"></xs:element>

<xs:complexType name="operation">
<xs:sequence>
<xs:element name="parameter" type="xs:string" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="operationResponse">
<xs:sequence>
<xs:element name="return" type="xs:string" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>

<xs:complexType name="MyException">
<xs:sequence>
<xs:element name="errorCode" type="xs:string" minOccurs="0"></xs:element>
<xs:element name="message" type="xs:string" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>

MyWebServiceServiceWrapper.wsdl
<?xml version="1.0" encoding="UTF-8"?>

<definitions
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="MyWebServiceServiceWrapper" targetNamespace="http://enterprise.netbeans.org/bpel/MyWebServiceServiceWrapper" xmlns:tns="http://enterprise.netbeans.org/bpel/MyWebServiceServiceWrapper" xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype" xmlns:ns="http://ws/">
<import location="MyWebServiceService.wsdl" namespace="http://ws/"/>
<plnk:partnerLinkType name="MyWebServiceLinkType">
<plnk:role name="MyWebServiceRole" portType="ns:MyWebService"/>
</plnk:partnerLinkType>
</definitions>


However, i think there is a bug here when bpel called from a java or web client.. Yes, the exception thrown by the web service is caught properly, but the detail info just disappears :( While testing via test module of the composite app, there is not such bug..

Here is the test with xml:

input

<soapenv:Envelope xsi:schemaLocation="http://schemas.xmlsoap.org/soap/envelope/ http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:faul="http://j2ee.netbeans.org/wsdl/FaultCatchWsdl">
<soapenv:Body>
<faul:FaultCatchWsdlOperation>
<part1>
<!--Optional:-->
<parameter>test</parameter>
</part1>
</faul:FaultCatchWsdlOperation>
</soapenv:Body>
</soapenv:Envelope>


output


<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.xmlsoap.org/soap/envelope/ http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode xmlns="">SOAP-ENV:Client</faultcode>
<faultstring xmlns="">fault1</faultstring>
<detail xmlns="">
<MyException xmlns="http://ws/">
<message>Exception thrown from web service :) </message>
</MyException>
</detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>


here the client call:


try {
org.netbeans.j2ee.wsdl.faultcatchwsdl.FaultCatchWsdlService service = new org.netbeans.j2ee.wsdl.faultcatchwsdl.FaultCatchWsdlService();
org.netbeans.j2ee.wsdl.faultcatchwsdl.FaultCatchWsdlPortType port = service.getFaultCatchWsdlPort();
ws.Operation part1 = new ws.Operation();
part1.setParameter("test");
ws.OperationResponse result = port.faultCatchWsdlOperation(part1);
System.out.println("Result = "+result);
} catch (org.netbeans.j2ee.wsdl.faultcatchwsdl.FaultCatchWsdlOperationFault ex) {
System.out.println("My exception is : " + ex.getFaultInfo().getMessage());
}


and the output:

My exception is : null

PS: i wrote down whole files to make trying the code easier..
You know, most portions of the files are automatically generated..

Btw, my ide is Netbeans 6.5 and i deploy to glassfish v2, and i use openesb for bpel..
Ooohh, done finally :)

Edit on 03/09/2009, 12:07 : The format of the post was a mess, so it is fixed by now..
The next post is about the bug mentioned here (in red)..

Hiç yorum yok:

Yorum Gönder