【IT168 技术文档】
WebLogic Workshop提供了一种内建的控件,叫做Service控件,可以用于在WebLogic Workshop应用程序中调用外部的web服务。Service控件隐藏了调用外部web服务的全部细节,包括把参数数据编组到XML以及形成SOAP调用消息,最终发送到目标web服务的服务器上。
SOAP规范允许SOAP消息包含header。一些web服务要求他们的客户端在调用web服务时,把“out of band” 信息传送给SOAP header。本文描述了当通过Service 控件调用外部web服务时,如何创建SOAP header以及如何把header包含在输出的消息中。
当web服务使用XML SOAP进行通信时,基本的消息如下。
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
"optional headers"
</SOAP-ENV:Header>
<SOAP-ENV:Body>
"Message body" </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
SOAP Envelope包括两块主要内容。最有趣的是实际的消息,或者Body。但是在body之前还有一个可选的 Header。WebLogic Workshop创建和包括了消息的Envelope和Body。由于Header在SOAP规范和SOAP Schema中都是可选的,因此如果没有内容,Workshop就会忽略Header。然而,当作为另一个web服务的客户端时,通常就会要求包含SOAP Header,或者在一些web服务中,即使没有内容,也必须表示Header元素。在这种情况中,使用web服务控件时如何通知Workshop包含这些header呢?
Service控件界面包括setOutputHeaders(org.w3c.dom.Element[] )方法,可以用于在输出web服务调用请求中设置SOAP header。因此添加一个简单的元素数组就可以把header添加到发送消息中。但是简单性到此为止。注意,该方法接受了元素数组。如何处理这些数组在8.1 SP2中得到了改进。
使用8.1 SP1或者早期版本时,传递的数组必须是单个元素,即SOAP-ENV:Header和其后代。在数组或者元素中,多个条目位于SOAP-ENV:Header不支持的位置上。
从8.1 SP2开始,在数组中可以有多个元素,而且元素可以是SOAP-ENV:Header或者任何元素。如果SOAP-ENV:Header元素被表示,那个就会保留Header以开始构造所产生的Header 。如果它没有被表示,就会为它创建一个。每个后续数组都会被检测,并适当地移植到SOAP-ENV:Header或者现有SOAP-ENV:Header的孩子的树中。
元素还是一种接口,创建一个实例不需要什么新的操作。因此,必须有其他一些内容被当作工厂来创建该元素。
既然XMLBeans是一种相当简单的创建XML内容的方式,那么我们就首先来看一看它。Workshop知Soap Envelope Header文档中的XMLBean表示,因此,我们只使用它。
package myPackage;
import org.xmlsoap.schemas.soap.envelope.HeaderDocument;
import com.bea.xml.XmlException;
import org.w3c.dom.Element;
public class MyService implements com.bea.jws.WebService
{
/** @common:control */
private myPackage.MyServiceCtl myServiceControl;
static final long serialVersionUID = 1L;
/** * @common:operation */
public void myMethod()
{ HeaderDocument hd = null;
try
{
hd = HeaderDocument.Factory.parse(
"<SOAP-ENV:Header xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
"<my:content xmlns:my=\"http://my.com/uri/\">Content Text</my:content>" +
"</SOAP-ENV:Header>");
}
catch (XmlException xe)
{
//should do something here.
}
Element header = (Element) hd.newDomNode().getFirstChild();
myServiceControl.setOutputHeaders(new Element[] { header });
myServiceControl.serviceMethod("argument");
}
}
在这个例子中我们看到,Workshop知道表示SOAP Header的XMLBean文档。我们创建一个使用HeaderDocument.Factory.parse(String)的实例。String是我们想要包括在SOAP Header中的XML内容。任何操纵string或者XMLBean自身的普通方法都可用于创建该内容。
只要存在HeaderDocument,我们就可以使用newDomNode()方法获得Node。这个Node是XMLBeans在文档中用作占位符的合成根节点。使用getFirstChild()操作生成转换为Element的Header Node。然后,这个Element在服务控件中被传递到setOutputHeaders( Element[] )。
同样,org.w3c.dom.Document可以用作Element工厂。无需尝试编写关于DOM编程的教程,以下是如何创建Document的例子,然后把它用作一个工厂来创建Header Elements。
package myPackage;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class MyService implements com.bea.jws.WebService
{
/** @common:control */
private myPackage.MyServiceCtl myServiceControl;
static final long serialVersionUID = 1L;
/**
* @common:operation
*/
public void myMethod()
{
Document doc = null; //allocate a document
try
{
//create the document
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
doc = factory.newDocumentBuilder().newDocument();
}
catch (ParserConfigurationException pce)
{
//should do something here.
}
// create the <SOAP-ENV:Header> element
Element header = doc.createElementNS(
"http://schemas.xmlsoap.org/soap/envelope/",
"SOAP-ENV:Header");
// create the <my:Content> element
Element headerContent = doc.createElementNS(
"http://my.org/uri/",
"my:Content");
header.appendChild(headerContent);
// insert the text in the content node
headerContent.appendChild(doc.createTextNode("Content Text"));
Attr nsAttr = doc.createAttributeNS(
"http://www.w3.org/2000/xmlns/",
"xmlns:my");
nsAttr.setValue("http://my.org/uri/");
headerContent.setAttributeNodeNS(nsAttr);
myServiceControl.setOutputHeaders(new Element[] {header});
myServiceControl.serviceMethod("argument");
}
}
上述方法讲述了如何使用javax.xml.parsers.DocumentBuilder和javax.xml.parsers.DocumentBuilderFactory 创建Document,以及如何使用Document构造所需要的 Element。