Document方式是Web service缺省調用模式,和literal相組合,給我們調用Web service提供了極大的便利,省去了RPC調用方式的復雜類型序列化的問題,所以,Doucment調用方式在BPEL領域應用非常廣泛,下面介紹基于Axis利用Document方式來調用一個Web service.
1. Web service準備:
Web service你可以任意實現一個,我是利用Oracle BPEL,通過建立一個BPEL流程,然后把它發布為Web service(具體創建過程省略),這里重要的是Web service的WSDL文件,這是我們調用的門戶。
下面是我的Web service的WSDL文件內容:
<definitions
name="HelloWorld"
targetNamespace="http://xmlns.oracle.com/HelloWorld"
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:client="http://xmlns.oracle.com/HelloWorld"
>
<types>
<schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://xmlns.oracle.com/HelloWorld"
xmlns="http://www.w3.org/2001/XMLSchema">
<element name="HelloWorldProcessRequest">
<complexType>
<sequence>
<element name="input" type="string"/>
</sequence>
</complexType>
</element>
<element name="HelloWorldProcessResponse">
<complexType>
<sequence>
<element name="result" type="string"/>
</sequence>
</complexType>
</element>
</schema>
</types>
<message name="HelloWorldRequestMessage">
<part name="payload" element="client:HelloWorldProcessRequest"/>
</message>
<message name="HelloWorldResponseMessage">
<part name="payload" element="client:HelloWorldProcessResponse"/>
</message>
<portType name="HelloWorld">
<operation name="process">
<input message="client:HelloWorldRequestMessage"/>
<output message="client:HelloWorldResponseMessage"/>
</operation>
</portType>
<binding name="HelloWorldBinding" type="client:HelloWorld">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="process">
<soap:operation style="document" soapAction="process"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="HelloWorld">
<port name="HelloWorldPort" binding="client:HelloWorldBinding">
<soap:address location="http://robin:9700/orabpel/default/HelloWorld/1.0"/>
</port>
</service>
<plnk:partnerLinkType name="HelloWorld">
<plnk:role name="HelloWorldProvider">
<plnk:portType name="client:HelloWorld"/>
</plnk:role>
</plnk:partnerLinkType>
</definitions>
2. 編寫調用類,代碼如下:
import java.net.MalformedURLException;
import java.net.URL;
import java.rmi.RemoteException;
import java.util.Vector;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.rpc.ServiceException;
import org.apache.axis.client.Call;
import org.apache.axis.constants.Style;
import org.apache.axis.message.SOAPBodyElement;
import org.apache.xml.serialize.DOMSerializerImpl;
import org.apache.xml.serialize.OutputFormat;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class BPELServiceTest {
//service的命名空間
static final String ns = "http://xmlns.oracle.com/HelloWorld";
public static void main(String args[]){
Call call = null;
try {
call = createCall();
Vector rtn = (Vector) call.invoke(createRequest());
parse(rtn);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FactoryConfigurationError e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
* 創建Call對象,對設置相關屬性,注意:其中的屬性應該是通過分析WSDL文件由程序動態獲得來賦值,
* 這里全部簡化為靜態賦值
*/
static Call createCall() throws MalformedURLException, ServiceException{
org.apache.axis.client.Service s = new org.apache.axis.client.Service();
Call call = (Call) s.createCall();
call.setTargetEndpointAddress(new URL("http://robin:9700/orabpel/default/HelloWorld/1.0"));
call.setSOAPActionURI("process");
call.setOperationName("process");
call.setProperty(Call.OPERATION_STYLE_PROPERTY, Style.DOCUMENT.getName());
call.setPortName(new QName(ns, "HelloWorldPort"));
call.setPortTypeName(new QName(ns, "HelloWorld"));
return call;
}
/*
*創建請求參數,實際上就是構建DOM片斷,根據Web service對輸入參數的要求來構建,要多復雜,都可以實現,
*這就是Docuemnt的好處,省去了復雜對象的序列化。
*/
static Object[] createRequest() throws ParserConfigurationException, FactoryConfigurationError{
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = db.newDocument();
Element root = doc.createElementNS(ns, "HelloWorldProcessRequest");
Element input = doc.createElementNS(ns, "input");
input.appendChild(doc.createTextNode("robin"));
root.appendChild(input);
doc.appendChild(root);
return new Object[]{new SOAPBodyElement(root)};
}
// 對返回結果進行解析,并打印。
static void parse(Vector v) throws Exception{
Document doc = ((SOAPBodyElement) v.get(0)).getAsDocument();
Element root = doc.getDocumentElement();
OutputFormat of = new OutputFormat();
of.setIndent(4);
System.out.println(new DOMSerializerImpl().writeToString(root));
}
}
上述代碼運行輸出結果為:
<?xml version="1.0"?>
<HelloWorldProcessResponse xmlns="http://xmlns.oracle.com/HelloWorld">
<result xmlns="http://xmlns.oracle.com/HelloWorld">robin</result>
</HelloWorldProcessResponse>
上面的代碼很簡單,需要說明的是:采用Document調用,實際上invoke方法的參數是一個元素類型為SOAPBodyElement的對象數組,而返回結果是一個元素類型的SOAPBodyElement的Vector對象。