<?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>Open your thoughts &#187; Webservice</title>
	<atom:link href="http://blog.baturu.com/index.php/tag/webservice/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.baturu.com</link>
	<description>James Gosling is not on the Java road any more !</description>
	<lastBuildDate>Fri, 20 Aug 2010 02:33:20 +0000</lastBuildDate>
	<language>zh-cn</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
	
<!-- Start Of Script Generated By WP-PostViews Plus -->
<script type='text/javascript' src='http://blog.baturu.com/wp-includes/js/jquery/jquery.js?ver=1.4.2'></script>
<script type="text/javascript">
/* <![CDATA[ */
/* ]]> */
</script>
<!-- End Of Script Generated By WP-PostViews Plus -->
	<item>
		<title>Tutorial of SOAP with Attachments API for Java</title>
		<link>http://blog.baturu.com/index.php/2009/10/21/tutorial_of_soap_with_attachments_api_for_java.html</link>
		<comments>http://blog.baturu.com/index.php/2009/10/21/tutorial_of_soap_with_attachments_api_for_java.html#comments</comments>
		<pubDate>Wed, 21 Oct 2009 07:42:01 +0000</pubDate>
		<dc:creator>javafuns</dc:creator>
				<category><![CDATA[SOA]]></category>
		<category><![CDATA[SAAJ]]></category>
		<category><![CDATA[SOAP]]></category>
		<category><![CDATA[Webservice]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://blog.baturu.com/?p=1067</guid>
		<description><![CDATA[随着web 服务、SOA 概念的兴起，和诸多 SOA 应用的实践，Java 阵营也审时度势，趁势推出相应的 API 以应对这一变化。SOAP 是 Java web 服务栈中很基础的一项技术，web 服务间以 SOAP 消息来互相通信。
SOAP with Attachments API for Java(简称 SAAJ) 就是 Java 阵营为访问 web 服务所提供的基础设施，它简化了对 SOAP 的处理。
SAAJ 包含 2 部分 APIs，其一用于创建消息，添加消息内容，其二则用于建立连接，发送 SOAP 消息。]]></description>
			<content:encoded><![CDATA[<p>随着web 服务、SOA 概念的兴起，和诸多 SOA 应用的实践，Java 阵营也审时度势，趁势推出相应的 API 以应对这一变化。SOAP 是 Java web 服务栈中很基础的一项技术，web 服务间以 SOAP 消息来互相通信。<br />
SOAP with Attachments API for Java(简称 SAAJ) 就是 Java 阵营为访问 web 服务所提供的基础设施，它简化了对 SOAP 的处理。<br />
SAAJ 包含 2 部分 APIs，其一用于创建消息，添加消息内容，其二则用于建立连接，发送 SOAP 消息。</p>
<p><strong>一. 创建 SOAP 消息</strong></p>
<p>SOAP 消息的 XML 文档结构在前一篇文章中已有图示。其中，SAAJ APIs 中的 SOAPMessage 类表示一个 SOAP 消息，SOAPPart 类表示 SOAP part，SOAPEnvelope 接口表示 SOAP envelope，等等。很多 SAAJ APIs 的接口都继承了 DOM 接口。<br />
当创建一个 SOAPMessage 时，该 SOAPMessage 会自动创建并包含 SOAP 消息所必须的部分：一个新的 SOAPMessage 对象会包含一个 SOAPPart 对象，这个 SOAPPart 则包含有一个 SOAPEnvelope 对象，该 SOAPEnvelope 对象会包含一个空的SOAPHeader 对象，紧接着是一个空的 SOAPBody 对象。SOAPHeader 在 SOAP 消息中是可选的，这里之所以自动创建它，是因为我们在 SOAP 消息中经常会使用到它。<br />
<span id="more-1067"></span></p>
<pre name="code" class="java">MessageFactory factory = MessageFactory.newInstance();
SOAPMessage message = factory.createMessage();</pre>
<p>默认是创建 SOAP 1.1 的消息，如果想要创建 SOAP 1.2 消息，那么代码如下：</p>
<pre name="code" class="java">MessageFactory factory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);</pre>
<p>如果既想创建 SOAP 1.1 消息，又想创建 SOAP 1.2 消息，那么代码如下：</p>
<pre name="code" class="java">MessageFactory factory = MessageFactory.newInstance(SOAPConstants.DYNAMIC_SOAP_PROTOCOL
);</pre>
<p>接着，向消息中添加内容。</p>
<p>首先取得 SOAPMessage 中的 SOAPPart 对象：</p>
<pre name="code" class="java">SOAPPart soapPart = message.getSOAPPart();</pre>
<p>然后，我们从 SOAPPart 中取出 SOAPEnvelope 对象：</p>
<pre name="code" class="java">SOAPEnvelope envelope = soapPart.getEnvelope();</pre>
<p>有了 SOAPEnvelope 对象，就可以得到它的 SOAPHeader 和 SOAPBody 了。</p>
<pre name="code" class="java">SOAPHeader header = envelope.getHeader();
SOAPBody body = envelope.getBody();</pre>
<p>不过，你可能觉得做了这么多的工作才取得 SOAPHeader 和 SOAPBody 是不是太麻烦了？ SAAJ APIs 提供了便捷通道，直接通过 SOAPMessage 就可以获得 SOAPHeader 和 SOAPBody 对象：</p>
<pre name="code" class="java">SOAPHeader header = message.getSOAPHeader();
SOAPBody body = message.getSOAPBody();</pre>
<p>由于 SOAPHeader 是可选的，如果你不需要它，便可以去掉它，可以使用 DOM 接口的方法来删除：</p>
<pre name="code" class="java">header.detachNode();</pre>
<p>下面向 SOAPBody 对象中添加内容：</p>
<pre name="code" class="java">SOAPBody body = message.getSOAPBody();
QName bodyName = new QName("http://wombat.ztrade.com", "GetLastTradePrice", "m");
SOAPBodyElement bodyElement = body.addBodyElement(bodyName);
QName name = new QName("symbol");
SOAPElement symbol = bodyElement.addChildElement(name);
symbol.addTextNode("SUNW");</pre>
<p>这时的 SOAPBody 内容如下所示：<br />
<code><br />
&lt;SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"&gt;<br />
&lt;SOAP-ENV:Body&gt;<br />
&lt;m:GetLastTradePrice xmlns:m="http://wombat.ztrade.com"&gt;<br />
&lt;symbol&gt;SUNW&lt;/symbol&gt;<br />
&lt;/m:GetLastTradePrice&gt;<br />
&lt;/SOAP-ENV:Body&gt;<br />
&lt;/SOAP-ENV:Envelope&gt;</code></p>
<p>如果你有一个以文件形式存在的 SOAP 消息，那么如下方式会使用创建一个 SOAPMessage 更便捷：</p>
<pre name="code" class="java">
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
dbFactory.setNamespaceAware(true);
DocumentBuilder builder = dbFactory.newDocumentBuilder();
Document document = builder.parse("file:///music/order/soap.xml");
DOMSource domSource = new DOMSource(document);

SOAPPart soapPart = message.getSOAPPart();
soapPart.setContent(domSource);
</pre>
<p>当然，如果已有一个 DOM document，想将它通过 SOAP 发送出去，SAAJ APIs 也提供了便捷方式：</p>
<pre name="code" class="java">
SOAPBody body = message.getSOAPBody();
SOAPBodyElement docElement = body.addDocument(document);
</pre>
<p>一个 SOAPMessage 可以包含一个或多个 attachment part，在 SAAJ APIs 中，使用 AttachmentPart 类表示 attachment part。由于 AttachmentPart 在 SOAPMessage 中是可选的，因此必须自己亲自动手去创建和添加它。如果一个 SOAPMessage 对象有一个或多个 attachments, 则每个 AttachmentPart 对象必须有一个 MIME header 用于指示它所包含的数据的类型。</p>
<p><strong>二. 创建连接并发送 SOAP 消息</strong></p>
<p>当消息已经创建好后，可以使用各种机制发送(例如JMS 或 JAXM)。在 SAAJ APIs 中，也提供了简单的发送机制。它使用 SOAPConnection 代表连接，SOAPConnection 对象是一中 point-to-point 连接，意味着它是直接从发送方到目标。<br />
首先创建连接 SOAPConnection 对象：</p>
<pre name="code" class="java">
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
SOAPConnection connection = soapConnectionFactory.createConnection();
</pre>
<p>发送消息：</p>
<pre name="code" class="java">
java.net.URL endpoint = new URL("http://wombat.ztrade.com/quotes");
SOAPMessage response = connection.call(message, endpoint);
</pre>
<p>一个连接使用了相当多的资源，所以使用结束后应尽早关闭：</p>
<pre name="code" class="java">
connection.close();
</pre>
<p>处理响应内容：</p>
<pre name="code" class="java">
SOAPBody soapBody = response.getSOAPBody();
java.util.Iterator iterator = soapBody.getChildElements(bodyName);
SOAPBodyElement bodyElement = (SOAPBodyElement)iterator.next();
String lastPrice = bodyElement.getValue();
System.out.print("The last price for SUNW is ");
System.out.println(lastPrice);
</pre>
<p><strong>三. 带附件的 SOAP 消息</strong></p>
<p>SAAJ APIs 中有 3 种方式创建附件。<br />
第一种：创建一个没有内容的附件</p>
<pre name="code" class="java">
AttachmentPart attachment = message.createAttachmentPart();
String stringContent = "Update address for Sunny Skies " + "Inc., to 10 Upbeat Street, Pleasant Grove, CA 95439";
attachment.setContent(stringContent, "text/plain");
attachment.setContentId("update_address");
message.addAttachmentPart(attachment);
</pre>
<p>setContent 方法的第一个参数 Object 是附件内容，第二个参数 String 则是 MIME 内容类型。MIME 内容类型会写入到 AttachmentPart 的 Header，且这个 MIME content type 是唯一强制要有的。SAAJ 提供了 Content-Type, Content-Id, and Content-Location headers 的 getter 和 setter 方法。</p>
<p>另外 2 个 SOAPMessage.createAttachment 方法会创建带内容的附件。其中一个方法，其参数类似于 AttachmentPart.setContent，它的 Object 可以是一个 String, 一个 stream, 一个 javax.xml.transform.Source object, 或者一个 javax.activation.DataHandler object。<br />
另外一个方法则需要参数 DataHandler object，来自于 JavaBeans Activation Framework (JAF) APIs. 使用一个 DataHandler object 是相当直观的。首先，为想要添加到附件中的文件创建一个 java.net.URL object。然后创建一个 DataHandler object：</p>
<pre name="code" class="java">
URL url = new URL("http://greatproducts.com/gizmos/img.jpg");
DataHandler dataHandler = new DataHandler(url);
AttachmentPart attachment = message.createAttachmentPart(dataHandler);
attachment.setContentId("attached_image");
message.addAttachmentPart(attachment);
</pre>
<p>这里之所以没有设置 MIME content type header，是因为 DataHandler 会含有这方面的信息。</p>
<p>访问附件内容：</p>
<pre name="code" class="java">
java.util.Iterator iterator = message.getAttachments();
while (iterator.hasNext()) {
AttachmentPart attachment = (AttachmentPart)iterator.next();
String id = attachment.getContentId();
String type = attachment.getContentType();
System.out.print("Attachment " + id + " has content type " + type);
if (type.equals("text/plain")) {
Object content = attachment.getContent();
System.out.println("Attachment contains:\n" + content);
}
}
</pre>
<p><strong>四. 创建 SOAPFault</strong><br />
for SOAP 1.1</p>
<pre name="code" class="java">
SOAPBody body = message.getSOAPBody();
SOAPFault fault = body.addFault();
QName faultName =
new QName(SOAPConstants.URI_NS_SOAP_ENVELOPE, "Server");
fault.setFaultCode(faultName);
fault.setFaultActor("http://gizmos.com/orders");
fault.setFaultString("Server not responding");
</pre>
<p>还可以向 SOAPFault 对象添加详细信息：</p>
<pre name="code" class="java">
Detail detail = fault.addDetail();
QName entryName = new QName("http://gizmos.com/orders/", "order", "PO");
DetailEntry entry = detail.addDetailEntry(entryName);
entry.addTextNode("Quantity element does not have a value");
QName entryName2 = new QName("http://gizmos.com/orders/", "order", "PO");
DetailEntry entry2 = detail.addDetailEntry(entryName2);
entry2.addTextNode("Incomplete address: no zip code");
</pre>
<p>注意：一个 SOAPFault 对象只能有一个 Detail 对象。</p>
<p>获取 SOAPFault 信息：</p>
<pre name="code" class="java">
SOAPBody body = newMessage.getSOAPBody();
if ( body.hasFault() ) {
SOAPFault newFault = body.getFault();
QName code = newFault.getFaultCodeAsQName();
String string = newFault.getFaultString();
String actor = newFault.getFaultActor();
System.out.println("SOAP fault contains: ");
System.out.println(" Fault code = " + code.toString());
System.out.println(" Local name = " + code.getLocalPart());
System.out.println(" Namespace prefix = " + code.getPrefix() + ", bound to " + code.getNamespaceURI());
System.out.println(" Fault string = " + string);
if ( actor != null ) {
System.out.println(" Fault actor = " + actor);
}
</pre>
<p>访问详细信息：</p>
<pre name="code" class="java">
Detail newDetail = newFault.getDetail();
if (newDetail != null) {
Iterator entries = newDetail.getDetailEntries();
while ( entries.hasNext() ) {
DetailEntry newEntry = (DetailEntry)entries.next();
String value = newEntry.getValue();
System.out.println(" Detail entry = " + value);
}
}
</pre>
<p><strong>五. 参考资料</strong></p>
<ol>
<li>The Java™ Web Services Tutorial (For Java Web Services Developer’s Pack, v2.0)</li>
</ol>
<h3  class="related_post_title">Related Posts:</h3><ul class="related_post"><li>2009/07/19 -- <a href="http://blog.baturu.com/index.php/2009/07/19/smtp_transport_binding_for_soap.html" title="SMTP Transport Binding for SOAP">SMTP Transport Binding for SOAP</a></li><li>2009/07/07 -- <a href="http://blog.baturu.com/index.php/2009/07/07/which-style-of-wsdl-should-i-use-reship.html" title="Which style of WSDL should I use? (reship)">Which style of WSDL should I use? (reship)</a></li><li>2009/10/15 -- <a href="http://blog.baturu.com/index.php/2009/10/15/structures_of_soap_with_attachments.html" title="Structures of SOAP with Attachments">Structures of SOAP with Attachments</a></li><li>2008/07/29 -- <a href="http://blog.baturu.com/index.php/2008/07/29/whats-new-in-wsdl-20.html" title="What&#8217;s New in WSDL 2.0">What&#8217;s New in WSDL 2.0</a></li><li>2008/07/19 -- <a href="http://blog.baturu.com/index.php/2008/07/19/uddi-v302-uddi-programmers-apis-custody-and-ownership-transfer-api-set.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Custody and Ownership Transfer API Set">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Custody and Ownership Transfer API Set</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.baturu.com/index.php/2009/10/21/tutorial_of_soap_with_attachments_api_for_java.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Structures of SOAP with Attachments</title>
		<link>http://blog.baturu.com/index.php/2009/10/15/structures_of_soap_with_attachments.html</link>
		<comments>http://blog.baturu.com/index.php/2009/10/15/structures_of_soap_with_attachments.html#comments</comments>
		<pubDate>Thu, 15 Oct 2009 14:28:40 +0000</pubDate>
		<dc:creator>javafuns</dc:creator>
				<category><![CDATA[SOA]]></category>
		<category><![CDATA[SOAP]]></category>
		<category><![CDATA[Webservice]]></category>

		<guid isPermaLink="false">http://blog.baturu.com/?p=1051</guid>
		<description><![CDATA[还是图形看起来更直观： &#8212;- Related Posts:2009/10/21 -- Tutorial of SOAP with Attachments API for Java2009/07/19 -- SMTP Transport Binding for SOAP2009/07/07 -- Which style of WSDL should I use? (reship)2008/07/19 -- UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Custody and Ownership Transfer API Set2008/07/15 -- UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Value Set API [...]]]></description>
			<content:encoded><![CDATA[<p>还是图形看起来更直观：</p>
<div class="wp-caption alignnone" style="width: 519px"><img alt="SOAP Message with No Attachments" src="http://tjkl1q.blu.livefilestore.com/y1pxGWDkICAYSBrS0KLL2fA5AJSYwXQX7YkErKonpo3qmHpuW1JCNJtfjOWLLwEGB6-FwT4eA5TfiViEau5sZrn6Q/SOPAMessageWithNoAttachments.jpg" title="SOAP Message with No Attachments" width="506" height="674" /><p class="wp-caption-text">SOAP Message with No Attachments</p></div>
<p>&#8212;-</p>
<div class="wp-caption alignnone" style="width: 519px"><img alt="SOAP Message with Attachments" src="http://tjkl1q.blu.livefilestore.com/y1pZqPBCfgbl5gbZaaoQpdfrqtFlr4sLPYAY0LmbWmndkFJZnVYX94_nLnXF7Jyf8ovaLn2i_QjP9GrJpeKOzTrLA/SOPAMessageWithAttachments.jpg" title="SOAP Message with Attachments" width="509" height="600" /><p class="wp-caption-text">SOAP Message with Attachments</p></div>
<h3  class="related_post_title">Related Posts:</h3><ul class="related_post"><li>2009/10/21 -- <a href="http://blog.baturu.com/index.php/2009/10/21/tutorial_of_soap_with_attachments_api_for_java.html" title="Tutorial of SOAP with Attachments API for Java">Tutorial of SOAP with Attachments API for Java</a></li><li>2009/07/19 -- <a href="http://blog.baturu.com/index.php/2009/07/19/smtp_transport_binding_for_soap.html" title="SMTP Transport Binding for SOAP">SMTP Transport Binding for SOAP</a></li><li>2009/07/07 -- <a href="http://blog.baturu.com/index.php/2009/07/07/which-style-of-wsdl-should-i-use-reship.html" title="Which style of WSDL should I use? (reship)">Which style of WSDL should I use? (reship)</a></li><li>2008/07/19 -- <a href="http://blog.baturu.com/index.php/2008/07/19/uddi-v302-uddi-programmers-apis-custody-and-ownership-transfer-api-set.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Custody and Ownership Transfer API Set">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Custody and Ownership Transfer API Set</a></li><li>2008/07/15 -- <a href="http://blog.baturu.com/index.php/2008/07/15/uddi-v302-uddi-programmers-apis-value-set-api-set.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Value Set API Set">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Value Set API Set</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.baturu.com/index.php/2009/10/15/structures_of_soap_with_attachments.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SMTP Transport Binding for SOAP</title>
		<link>http://blog.baturu.com/index.php/2009/07/19/smtp_transport_binding_for_soap.html</link>
		<comments>http://blog.baturu.com/index.php/2009/07/19/smtp_transport_binding_for_soap.html#comments</comments>
		<pubDate>Sun, 19 Jul 2009 15:37:40 +0000</pubDate>
		<dc:creator>javafuns</dc:creator>
				<category><![CDATA[SOA]]></category>
		<category><![CDATA[SOAP]]></category>
		<category><![CDATA[UDDI]]></category>
		<category><![CDATA[Webservice]]></category>
		<category><![CDATA[WSDL]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://blog.baturu.com/?p=984</guid>
		<description><![CDATA[SOAP 除了可以 bind 到 HTTP 上外, 也可以 bind 到 SMTP 上. 其实个人感觉, SOAP bind 到 SMTP 上的场景很少会使用到, 通常限于 one-way operation (比如通知等不需要响应). 如果需要实现 request/response, 那么是需要多做一些工作的(下文会有叙述). soap:binding element 的 transport 属性需指定一个 http://xxx(例如:http://schemas.xmlsoap.org/soap/smtp) URL 来表明所要 binding 的 protocol. 似乎这个 URL 是任意形式, 只要能让调用方知道要使用什么协议即可. 在 soap:address 要给定 mailto:xxxx@xxx.xxx 这样形式的 URI. &#60;service name="StockQuoteServiceBinding_service"&#62; &#60;port name="StockQuoteServiceBinding_port" binding="binding:StockQuoteServiceBinding"&#62; &#60;soap:address location="mailto:getQuote@test.com"/&#62; &#60;/port&#62; &#60;/service&#62; 注意: [...]]]></description>
			<content:encoded><![CDATA[<p>SOAP 除了可以 bind 到 HTTP 上外, 也可以 bind 到 SMTP 上. 其实个人感觉, SOAP bind 到 SMTP 上的场景很少会使用到, 通常限于 one-way operation (比如通知等不需要响应). 如果需要实现 request/response, 那么是需要多做一些工作的(下文会有叙述).</p>
<p>soap:binding element 的 transport 属性需指定一个 http://xxx(例如:http://schemas.xmlsoap.org/soap/smtp) URL 来表明所要 binding 的 protocol. 似乎这个 URL 是任意形式, 只要能让调用方知道要使用什么协议即可. 在 soap:address 要给定 mailto:xxxx@xxx.xxx 这样形式的 URI.</p>
<pre>    &lt;service name="StockQuoteServiceBinding_service"&gt;
        &lt;port name="StockQuoteServiceBinding_port"
                binding="binding:StockQuoteServiceBinding"&gt;
            &lt;soap:address location="mailto:getQuote@test.com"/&gt;
        &lt;/port&gt;
    &lt;/service&gt;</pre>
<p>注意: 在 soap:address element 中, 可能会有一些扩展元素, 例如smtp server, smtp username, smtp password, etc.</p>
<p>在需要 request / response 语义情况下, 需使用标准的 Message-Id 和 In-Reply-To SMTP header 来实现这一目标. 请求包含一个 Message-Id header, 相应的响应则在 In-Reply-To header 中使用请求的 Message-Id header 值, 同时也创建一个新的 Message-Id header. 这样, 在请求与响应之间便建立了关联.</p>
<p>请求:</p>
<pre>To: &lt;soap@example.org&gt;
 From: &lt;soap@client.com&gt;
 Reply-To: &lt;soap@client.com&gt;
 Date: Tue, 15 Nov 2001 23:27:00 -0700
 Message-Id: &lt;1F75D4D515C3EC3F34FEAB51237675B5@client.com&gt;
 MIME-Version: 1.0
 Content-Type: text/xml; charset=utf-8
 Content-Transfer-Encoding: QUOTED-PRINTABLE

 &lt;?xml version=3D"1.0" encoding=3D"UTF-8"?&gt;
 &lt;SOAP-ENV:Envelope SOAP-ENV:encodingStyle=3D"http://schemas.xmlsoap.org/soap/encoding/"
 xmlns:SOAP-ENC=3D"http://schemas.xmlsoap.org/soap/encoding/"
 xmlns:SOAP-ENV=3D"http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:xsd=3D"http://www.w3.org/2001/XMLSchema"
 xmlns:xsi=3D"http://www.w3.org/2001/XMLSchema-instance"&gt;
 &lt;SOAP-ENV:Body&gt;
 &lt;m:echoString xmlns:m=3D"http://soapinterop.org/"&gt;
 &lt;inputString&gt;get your SOAP over SMTP here !&lt;/inputString&gt;
 &lt;/m:echoString&gt;
 &lt;/SOAP-ENV:Body&gt;
 &lt;/SOAP-ENV:Envelope&gt;</pre>
<p>响应:</p>
<pre>To: &lt;soap@client.com&gt;
 From: &lt;soap@example.org&gt;
 Date: Tue, 13 Nov 2001 23:27:00 -0700
 In-Reply-To: &lt;1F75D4D515C3EC3F34FEAB51237675B5@client.com&gt;
 Message-Id: &lt;FF75D4D515C3EC3F34FEAB51237675B5@soap.example.org&gt;
 MIME-Version: 1.0
 Content-Type: TEXT/XML; charset=utf-8
 Content-Transfer-Encoding: QUOTED-PRINTABLE

 &lt;?xml version=3D"1.0" encoding=3D"UTF-8"?&gt;
 &lt;SOAP-ENV:Envelope SOAP-ENV:encodingStyle=3D"http://schemas.xmlsoap.org/soap/encoding/"
 xmlns:SOAP-ENC=3D"http://schemas.xmlsoap.org/soap/encoding/"
 xmlns:SOAP-ENV=3D"http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:xsd=3D"http://www.w3.org/2001/XMLSchema"
 xmlns:xsi=3D"http://www.w3.org/2001/XMLSchema-instance"&gt;
 &lt;SOAP-ENV:Body&gt;
 &lt;m:echoStringResponse xmlns:m=3D"http://soapinterop.org/"&gt;
 &lt;return&gt;get your SOAP over SMTP here !&lt;/return&gt;
 &lt;/m:echoStringResponse&gt;
 &lt;/SOAP-ENV:Body&gt;
 &lt;/SOAP-ENV:Envelope&gt;</pre>
<h4>Resources:</h4>
<ol>
<li> <a href="http://www.pocketsoap.com/specs/smtpbinding/" target="_blank">http://www.pocketsoap.com/specs/smtpbinding/</a></li>
<li><a href="http://people.apache.org/~pzf/SMTPBase64Binding.html" target="_blank">http://people.apache.org/~pzf/SMTPBase64Binding.html</a></li>
</ol>
<h3  class="related_post_title">Related Posts:</h3><ul class="related_post"><li>2009/07/07 -- <a href="http://blog.baturu.com/index.php/2009/07/07/which-style-of-wsdl-should-i-use-reship.html" title="Which style of WSDL should I use? (reship)">Which style of WSDL should I use? (reship)</a></li><li>2008/07/19 -- <a href="http://blog.baturu.com/index.php/2008/07/19/uddi-v302-uddi-programmers-apis-custody-and-ownership-transfer-api-set.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Custody and Ownership Transfer API Set">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Custody and Ownership Transfer API Set</a></li><li>2008/07/15 -- <a href="http://blog.baturu.com/index.php/2008/07/15/uddi-v302-uddi-programmers-apis-value-set-api-set.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Value Set API Set">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Value Set API Set</a></li><li>2008/07/13 -- <a href="http://blog.baturu.com/index.php/2008/07/13/uddi-v302-uddi-programmers-apis-security-policy-api-set.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Security Policy API Set">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Security Policy API Set</a></li><li>2008/07/07 -- <a href="http://blog.baturu.com/index.php/2008/07/07/uddi-v302-uddi-programmers-apis-publication-api-set-3.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Publication API Set(3)">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Publication API Set(3)</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.baturu.com/index.php/2009/07/19/smtp_transport_binding_for_soap.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Which style of WSDL should I use? (reship)</title>
		<link>http://blog.baturu.com/index.php/2009/07/07/which-style-of-wsdl-should-i-use-reship.html</link>
		<comments>http://blog.baturu.com/index.php/2009/07/07/which-style-of-wsdl-should-i-use-reship.html#comments</comments>
		<pubDate>Tue, 07 Jul 2009 08:40:25 +0000</pubDate>
		<dc:creator>javafuns</dc:creator>
				<category><![CDATA[SOA]]></category>
		<category><![CDATA[schema]]></category>
		<category><![CDATA[SOAP]]></category>
		<category><![CDATA[UDDI]]></category>
		<category><![CDATA[Webservice]]></category>
		<category><![CDATA[WSDL]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://blog.baturu.com/?p=973</guid>
		<description><![CDATA[A Web Services Description Language (WSDL) binding style can be RPC or document. The use can be encoded or literal. How do you determine which combination of style and use to use? The author describes the WSDL and SOAP messages for each combination to help you decide.]]></description>
			<content:encoded><![CDATA[<div class="ibm-column ibm-first">
<div class="author"><a class="dwauthor" rel="#authortip1" href="http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/?S_TACT=105AGX52&amp;S_CMP=content#author1">Russell Butek</a> (<a href="mailto:butek@us.ibm.com?subject=Which%20style%20of%20WSDL%20should%20I%20use?&amp;cc=flanders@us.ibm.com">butek@us.ibm.com</a>), SOA and Web services consultant, IBM</div>
<div id="authortip1" class="dwauthor-onload-state ibm-no-print" style="display: none;">
<div>
<div>
<div>
<div>Russell Butek is an SOA and Web services consultant for IBM. He has been one of the developers of IBM WebSphere Web services engine. He has also been a member the JAX-RPC Java Specification Request (JSR) expert group. He was involved in the implementation of Apache&#8217;s AXIS SOAP engine, driving AXIS 1.0 to comply with JAX-RPC 1.0.</div>
</div>
</div>
</div>
</div>
<p style="padding-left: 30px;"><strong>Date:</strong> 24 May  2005 (Published 31 Oct  2003)<br />
<strong>Level: </strong> Advanced</p>
<p><strong>Summary:</strong> A Web Services Description Language (WSDL) binding style can be RPC or document. The use can be encoded or literal. How do you determine which combination of style and use to use? The author describes the WSDL and SOAP messages for each combination to help you decide.</div>
<h2><a name="N10043"><span class="atitle">Introduction</span></a></h2>
<p>A WSDL document describes a Web service. A WSDL binding describes how the service is bound to a messaging protocol, particularly the SOAP messaging protocol. A WSDL SOAP binding can be either a Remote Procedure Call (RPC) style binding or a document style binding. A SOAP binding can also have an encoded use or a literal use. This gives you four style/use models:</p>
<ol>
<li>RPC/encoded</li>
<li>RPC/literal</li>
<li>Document/encoded</li>
<li>Document/literal</li>
</ol>
<p>Add to this collection a pattern which is commonly called the document/literal wrapped pattern and you have five binding styles to choose from when creating a WSDL file. Which one should you choose?</p>
<p>Before I go any further, let me clear up some confusion that many of us have stumbled over. The terminology here is very unfortunate: RPC versus document. These terms imply that the RPC style should be used for RPC programming models and that the document style should be used for document or messaging programming models. That is <em>not</em> the case at all. The style has nothing to do with a programming model. It merely dictates how to translate a WSDL binding to a SOAP message. Nothing more. You can use either style with any programming model.</p>
<p>Likewise, the terms <em>encoded</em> and <em>literal</em> are only meaningful for the WSDL-to-SOAP mapping, though, at least here, the traditional meanings of the words make a bit more sense.</p>
<p>For this discussion, let&#8217;s start with the Java method in <a href="http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/?S_TACT=105AGX52&amp;S_CMP=content#listing1">Listing 1</a> and apply the JAX-RPC Java-to-WSDL rules to it (see <a href="http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/?S_TACT=105AGX52&amp;S_CMP=content#resources">Resources</a> for the JAX-RPC 1.1 specification).</p>
<p><a name="listing1"><strong>Listing 1. Java method</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td class="code-outline">
<pre class="displaycode">public void myMethod(int x, float y);</pre>
</td>
</tr>
</tbody>
</table>
<div class="ibm-alternate-rule">
<hr /></div>
<h2><a name="N10082"><span class="atitle">RPC/encoded</span></a></h2>
<p>Take the method in <a href="http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/?S_TACT=105AGX52&amp;S_CMP=content#listing1">Listing 1</a> and run it through your favorite Java-to-WSDL tool, specifying that you want it to generate RPC/encoded WSDL. You should end up with something like the WSDL snippet in <a href="http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/?S_TACT=105AGX52&amp;S_CMP=content#listing2">Listing 2</a>.<br />
<a name="listing2"><strong>Listing 2. RPC/encoded WSDL for myMethod</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td class="code-outline">
<pre class="displaycode">&lt;message name="myMethodRequest"&gt;
    &lt;part name="x" type="xsd:int"/&gt;
    &lt;part name="y" type="xsd:float"/&gt;
&lt;/message&gt;
&lt;message name="empty"/&gt;

&lt;portType name="PT"&gt;
    &lt;operation name="myMethod"&gt;
        &lt;input message="myMethodRequest"/&gt;
        &lt;output message="empty"/&gt;
    &lt;/operation&gt;
&lt;/portType&gt;

&lt;binding .../&gt;
&lt;!-- I won't bother with the details, just assume it's RPC/encoded. --&gt;</pre>
</td>
</tr>
</tbody>
</table>
<p>Now invoke this method with &#8220;5&#8243; as the value for parameter <code>x</code> and &#8220;5.0&#8243; for parameter <code>y</code>.  That sends a SOAP message which looks something like <a href="http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/?S_TACT=105AGX52&amp;S_CMP=content#listing3">Listing 3</a>.<br />
<a name="listing3"><strong>Listing 3. RPC/encoded SOAP message for myMethod</strong></a></p>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tbody>
<tr>
<td class="code-outline">
<pre class="displaycode">&lt;soap:envelope&gt;
    &lt;soap:body&gt;
        &lt;myMethod&gt;
            &lt;x xsi:type="xsd:int"&gt;5&lt;/x&gt;
            &lt;y xsi:type="xsd:float"&gt;5.0&lt;/y&gt;
        &lt;/myMethod&gt;
    &lt;/soap:body&gt;
&lt;/soap:envelope&gt;</pre>
</td>
</tr>
</tbody>
</table>
<div class="ibm-container ibm-alt-header dw-container-sidebar">
<h3>A note about prefixes and namespaces</h3>
<div class="ibm-container-body">
<p>For the most part, for brevity, I ignore namespaces and prefixes in the listings in this article. I do use a few prefixes that you can assume are defined with the following namespaces:</p>
<ul>
<li>xmlns:xsd=&#8221;http://www.w3.org/2001/XMLSchema&#8221;</li>
<li>xmlns:xsi=&#8221;http://www.w3.org/2001/XMLSchema-instance&#8221;</li>
<li>xmlns:soap=&#8221;http://schemas.xmlsoap.org/soap/envelope/&#8221;</li>
</ul>
<p>For a discussion about namespaces and the WSDL-to-SOAP mapping, see paper &#8220;Handle namespaces in SOAP messages you create by hand&#8221; (see <a href="http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/?S_TACT=105AGX52&amp;S_CMP=content#resources">Resources</a>).</div>
</div>
<p>There are a number of things to notice about the WSDL and SOAP message for this RPC/encoded example:</p>
<h3><a name="N100D8"><span class="smalltitle">Strengths</span></a></h3>
<ul>
<li>The WSDL is about as straightforward as it&#8217;s possible for WSDL to be.</li>
<li>The operation name appears in the message, so the receiver has an easy time dispatching this message to the implementation of the operation.</li>
</ul>
<h3><a name="N100EA"><span class="smalltitle">Weaknesses</span></a></h3>
<ul>
<li>The type encoding info (such as <code>xsi:type="xsd:int"</code>) is usually just overhead which degrades throughput performance.</li>
<li>You cannot easily validate this message since only the <code>&lt;x ...&gt;5&lt;/x&gt;</code> and <code>&lt;y ...&gt;5.0&lt;/y&gt;</code> lines contain things defined in a schema; the rest of the <code>soap:body</code> contents comes from WSDL definitions.</li>
<li>Although it is legal WSDL, RPC/encoded is not WS-I compliant.</li>
</ul>
<p>Is there a way to keep the strengths and remove the weaknesses? Possibly. Let&#8217;s look at the RPC/literal style.</p>
<h3  class="related_post_title">Related Posts:</h3><ul class="related_post"><li>2009/07/19 -- <a href="http://blog.baturu.com/index.php/2009/07/19/smtp_transport_binding_for_soap.html" title="SMTP Transport Binding for SOAP">SMTP Transport Binding for SOAP</a></li><li>2008/07/29 -- <a href="http://blog.baturu.com/index.php/2008/07/29/whats-new-in-wsdl-20.html" title="What&#8217;s New in WSDL 2.0">What&#8217;s New in WSDL 2.0</a></li><li>2008/07/19 -- <a href="http://blog.baturu.com/index.php/2008/07/19/uddi-v302-uddi-programmers-apis-custody-and-ownership-transfer-api-set.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Custody and Ownership Transfer API Set">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Custody and Ownership Transfer API Set</a></li><li>2008/07/15 -- <a href="http://blog.baturu.com/index.php/2008/07/15/uddi-v302-uddi-programmers-apis-value-set-api-set.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Value Set API Set">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Value Set API Set</a></li><li>2008/07/13 -- <a href="http://blog.baturu.com/index.php/2008/07/13/uddi-v302-uddi-programmers-apis-security-policy-api-set.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Security Policy API Set">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Security Policy API Set</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.baturu.com/index.php/2009/07/07/which-style-of-wsdl-should-i-use-reship.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>软件及服务的松耦合</title>
		<link>http://blog.baturu.com/index.php/2009/04/20/software_and_service_loose_coupling.html</link>
		<comments>http://blog.baturu.com/index.php/2009/04/20/software_and_service_loose_coupling.html#comments</comments>
		<pubDate>Mon, 20 Apr 2009 07:50:35 +0000</pubDate>
		<dc:creator>javafuns</dc:creator>
				<category><![CDATA[Design Patterns]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[DesignPatterns]]></category>
		<category><![CDATA[Webservice]]></category>

		<guid isPermaLink="false">http://blog.baturu.com/?p=791</guid>
		<description><![CDATA[软件的模块性: 模块可分解性（Modular Decomposability）——如果一种软件构造方法能有助于把一个软件问题分解为若干较简单的子问题、并用一个简单的结构将这些子问题连接起来、而且能够独立地对各个子问题作进一步分解，那么该方法就满足模块可分解性。 模块可组合性（Modular Composability）——如果一种方法，由它生产出的软件元素，未来可在不同于最初被开发的环境中通过彼此自由组合的方式来产生新的系统，那么该方法就满足模块可组合性。 模块可理解性（Modular Understandability）——如果一种方法，由它生产出的软件，人类读者无需了解其他模块（或最多只需研究少许其他模块）便可理解每一个模块，那么该方法就有利于模块可理解性。 模块连续性（Modular Continuity）——如果一种方法，在由它得到的软件架构中，功能规格上的微小改动只会引起一个（或少量）模块的变化，那么该方法就满足模块连续性。 模块保护性（Modular Protection）——如果一种方法，在由它得到的架构中，一个模块在运行时出现异常条件不会影响到该模块之外（或最多只蔓延到少数周边模块），那么该方法就满足模块保护性。 服务的模块性: 可分解性（Decomposability）——如果一种方法能有助于把一个软件问题分解为若干较简单的子问题、并用一个简单的结构将这些子问题连接起来、而且能够独立地对各个子问题作进一步分解，那么该方法就满足可分解性。 可组合性（Composability）——如果一种方法，由它生产出的软件元素，未来可在不同于最初被开发的环境中通过彼此自由组合的方式来产生新的系统，那么该方法就满足可组合性。 可理解性（Understandability）——如果一种方法，由它生产出的软件，人类读者无需了解其他模块（或最多只需研究少许其他模块）便可理解每一个模块，那么该方法就有利于可理解性。 连续性（Continuity）——如果一种方法，在由它得到的软件架构中，功能规格上的微小改动只会引起一个（或少量）模块的变化，那么该方法就满足连续性。 保护性（Protection）——如果一种方法，在由它得到的架构中，一个模块在运行时出现异常条件不会影响到该模块之外（或最多只蔓延到少数周边模块），那么该方法就满足保护性。 自查性（Introspection）——如果一个方法，由它得到的架构提供了“允许在运行时查询并检查模块结构及模块间通信结构”的机制，那么该方法就满足自查性。 远程性（Remoteability）——如果一个方法，由它得到的架构提供了“允许托管于不同物理环境下的不同模块与之进行模块通信”的机制，那么该方法就满足远程性。 异步性（Asynchronicity）——如果一个方法，由它得到的架构不假定模块调用将被立即响应，那么该方法就满足异步性。换言之，它假定网络或被调用模块有延迟。 面向文档（Document Orientedness）——如果一个方法，在由它得到的架构中，内部模块间的通信消息均是明确定义且互相知道的、而且各次调用之间不存在隐式的状态共享，那么该方法就是面向文档的。 标准化的协议信封（Standardized Protocol Envelope）——如果一个方法，由它得到的架构要求所有模块通信都共用一种通用信封消息格式，那么该方法就满足标准协议信封。 分散式管理（Decentralized Administration）——如果一个方法，由它得到的架构不需要对所有模块进行集中管理，那么该方法就符合分散式管理。 原文: SOA定义的松耦合 Loose Coupling in SOA Defined Related Posts:2010/02/01 -- Differences between WADL and WSDL 2.0 HTTP binding2009/10/21 -- Tutorial of SOAP with Attachments API for Java2009/10/15 -- [...]]]></description>
			<content:encoded><![CDATA[<h4>软件的模块性:</h4>
<ol id="gjvg5">
<li id="gjvg6">模块可分解性（Modular Decomposability）——如果一种软件构造方法能有助于把一个软件问题分解为若干较简单的子问题、并用一个简单的结构将这些子问题连接起来、而且能够独立地对各个子问题作进一步分解，那么该方法就满足模块可分解性。</li>
<li id="gjvg7">模块可组合性（Modular Composability）——如果一种方法，由它生产出的软件元素，未来可在不同于最初被开发的环境中通过彼此自由组合的方式来产生新的系统，那么该方法就满足模块可组合性。</li>
<li id="gjvg8">模块可理解性（Modular Understandability）——如果一种方法，由它生产出的软件，人类读者无需了解其他模块（或最多只需研究少许其他模块）便可理解每一个模块，那么该方法就有利于模块可理解性。</li>
<li id="gjvg9">模块连续性（Modular Continuity）——如果一种方法，在由它得到的软件架构中，功能规格上的微小改动只会引起一个（或少量）模块的变化，那么该方法就满足模块连续性。</li>
<li id="gjvg10">模块保护性（Modular Protection）——如果一种方法，在由它得到的架构中，一个模块在运行时出现异常条件不会影响到该模块之外（或最多只蔓延到少数周边模块），那么该方法就满足模块保护性。</li>
</ol>
<h4>服务的模块性:</h4>
<ol id="gjvg23">
<li id="gjvg24">可分解性（Decomposability）——如果一种方法能有助于把一个软件问题分解为若干较简单的子问题、并用一个简单的结构将这些子问题连接起来、而且能够独立地对各个子问题作进一步分解，那么该方法就满足可分解性。</li>
<li id="gjvg25">可组合性（Composability）——如果一种方法，由它生产出的软件元素，未来可在不同于最初被开发的环境中通过彼此自由组合的方式来产生新的系统，那么该方法就满足可组合性。</li>
<li id="gjvg26">可理解性（Understandability）——如果一种方法，由它生产出的软件，人类读者无需了解其他模块（或最多只需研究少许其他模块）便可理解每一个模块，那么该方法就有利于可理解性。</li>
<li id="gjvg27">连续性（Continuity）——如果一种方法，在由它得到的软件架构中，功能规格上的微小改动只会引起一个（或少量）模块的变化，那么该方法就满足连续性。</li>
<li id="gjvg28">保护性（Protection）——如果一种方法，在由它得到的架构中，一个模块在运行时出现异常条件不会影响到该模块之外（或最多只蔓延到少数周边模块），那么该方法就满足保护性。</li>
<li id="gjvg29">自查性（Introspection）——如果一个方法，由它得到的架构提供了“允许在运行时查询并检查模块结构及模块间通信结构”的机制，那么该方法就满足自查性。</li>
<li id="gjvg30">远程性（Remoteability）——如果一个方法，由它得到的架构提供了“允许托管于不同物理环境下的不同模块与之进行模块通信”的机制，那么该方法就满足远程性。</li>
<li id="gjvg31">异步性（Asynchronicity）——如果一个方法，由它得到的架构不假定模块调用将被立即响应，那么该方法就满足异步性。换言之，它假定网络或被调用模块有延迟。</li>
<li id="gjvg32">面向文档（Document Orientedness）——如果一个方法，在由它得到的架构中，内部模块间的通信消息均是明确定义且互相知道的、而且各次调用之间不存在隐式的状态共享，那么该方法就是面向文档的。</li>
<li id="gjvg33">标准化的协议信封（Standardized Protocol Envelope）——如果一个方法，由它得到的架构要求所有模块通信都共用一种通用信封消息格式，那么该方法就满足标准协议信封。</li>
<li id="gjvg35">分散式管理（Decentralized Administration）——如果一个方法，由它得到的架构不需要对所有模块进行集中管理，那么该方法就符合分散式管理。</li>
</ol>
<p>原文:</p>
<ol>
<li><a title="SOA定义的松耦合" href="http://www.infoq.com/cn/news/2008/06/loose-coupling-soa" target="_blank">SOA定义的松耦合</a></li>
<li><a id="ri8." title="Loose Coupling in SOA Defined" href="http://www.infoq.com/news/2008/06/loose-coupling-soa">Loose Coupling in SOA Defined</a></li>
<li></li>
</ol>
<h3  class="related_post_title">Related Posts:</h3><ul class="related_post"><li>2010/02/01 -- <a href="http://blog.baturu.com/index.php/2010/02/01/differences_between_wadl_and_wsdl_20_http_binding.html" title="Differences between WADL and WSDL 2.0 HTTP binding">Differences between WADL and WSDL 2.0 HTTP binding</a></li><li>2009/10/21 -- <a href="http://blog.baturu.com/index.php/2009/10/21/tutorial_of_soap_with_attachments_api_for_java.html" title="Tutorial of SOAP with Attachments API for Java">Tutorial of SOAP with Attachments API for Java</a></li><li>2009/10/15 -- <a href="http://blog.baturu.com/index.php/2009/10/15/structures_of_soap_with_attachments.html" title="Structures of SOAP with Attachments">Structures of SOAP with Attachments</a></li><li>2009/09/25 -- <a href="http://blog.baturu.com/index.php/2009/09/25/a_simple_pojo_factory.html" title="一个简单的 POJO factory 实现">一个简单的 POJO factory 实现</a></li><li>2009/07/19 -- <a href="http://blog.baturu.com/index.php/2009/07/19/smtp_transport_binding_for_soap.html" title="SMTP Transport Binding for SOAP">SMTP Transport Binding for SOAP</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.baturu.com/index.php/2009/04/20/software_and_service_loose_coupling.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>设计与开发 JAX-WS 2.0 Web 服务</title>
		<link>http://blog.baturu.com/index.php/2008/12/04/design-and-develop-webservice-with-jax-ws-20.html</link>
		<comments>http://blog.baturu.com/index.php/2008/12/04/design-and-develop-webservice-with-jax-ws-20.html#comments</comments>
		<pubDate>Thu, 04 Dec 2008 09:54:49 +0000</pubDate>
		<dc:creator>javafuns</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[JAX-WS]]></category>
		<category><![CDATA[Webservice]]></category>

		<guid isPermaLink="false">http://blog.baturu.com/?p=257</guid>
		<description><![CDATA[Naveen Balani, 开发经理, IBM2007 年 11 月 29 日 通过使用 Java™ API for XML Web Services (JAX-WS) 技术设计和开发 Web 服务，可以带来很多好处，能简化 Web 服务的开发和部署，并能加速 Web 服务的开发。通过此教程，可以了解如何开发将其功能作为 Web 服务公开的示例订单处理程序，从而进行所有这些工作以及其他任务。完成了此教程后，您将能够应用这些概念和新获得的知识，来使用 JAX-WS 技术为应用程序开发 Web 服务。 JAX-WS 简介 为何使用 JAX-WS？ JAX-WS 是用于简化使用 Java 构造 Web 服务和 Web 服务客户机的工作的技术。该技术提供了完整的 Web 服务堆栈，可减少开发和部署 Web 服务的任务。JAX-WS 支持 WS-I Basic Profile 1.1，后者可确保使用 JAX-WS 堆栈开发的 Web 服务能够供采用 [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: right;">Naveen Balani, 开发经理, IBM2007 年 11 月 29 日</p>
<p>通过使用 Java™ API for XML Web Services (JAX-WS) 技术设计和开发 Web 服务，可以带来很多好处，能简化 Web 服务的开发和部署，并能加速 Web 服务的开发。通过此教程，可以了解如何开发将其功能作为 Web 服务公开的示例订单处理程序，从而进行所有这些工作以及其他任务。完成了此教程后，您将能够应用这些概念和新获得的知识，来使用 JAX-WS 技术为应用程序开发 Web 服务。</p>
<h3><strong>JAX-WS 简介</strong></h3>
<h4>为何使用 JAX-WS？</h4>
<p>JAX-WS 是用于简化使用 Java 构造 Web 服务和 Web 服务客户机的工作的技术。该技术提供了完整的 Web 服务堆栈，可减少开发和部署 Web 服务的任务。JAX-WS 支持 WS-I Basic Profile 1.1，后者可确保使用 JAX-WS 堆栈开发的 Web 服务能够供采用 WS-I Basic Profile 标准使用任意语言开发的任意客户机使用。JAX-WS 还包括了 Java Architecture for XML Binding (JAXB) 和 SOAP with Attachments API for Java (SAAJ)。</p>
<p>JAXB 提供了一种非常方便的方法来将 XML 模式映射到 Java 代码的表示形式，从而支持数据绑定功能。JAXB 消除了将 SOAP 消息中的 XML 模式消息转换为 Java 代码的工作，因而不必全面了解 XML 和 SOAP 解析。JAXB 规范定义 Java 和 XML 模式之间的绑定。SAAJ 提供了标准的方法来处理 SOAP 消息中包含的 XML 附件。</p>
<p>而且，JAX-WS 提供了用于将传统 Java 对象（Plain Old Java Object，POJO）类转换为 Web 服务的 Annotation 库，从而加速了 Web 服务的开发工作。另外，它还指定了从采用 Web 服务描述语言（Web Services Description Language，WSDL）定义的服务到实现该服务的 Java 类之间的详细映射。采用 WSDL 定义的任意复杂类型都通过遵循 JAXB 规范定义的映射来映射为 Java 类。JAX-WS 之前与 Java Platform, Enterprise Edition (Java EE) 5 绑定。而 JAX-WS 2.0 规范是作为 Java Community Process (JCP) 的 JSR 224 开发的。</p>
<h4>开发 Web 服务</h4>
<h5>契约优先方法与代码优先方法</h5>
<p>进入 JAX-WS 时代的最好方法莫过于首先开发一个 Web 服务。可以采用以下两种方法之一开发 Web 服务：</p>
<ul>
<li>契约优先：从 WSDL 契约着手，生成 Java 类来实现服务。</li>
<li>代码优先：从 Java 类着手，使用 Annotation 来生成 WSDL 文件和 Java 接口。</li>
</ul>
<p>契约优先 WSDL 方法需要对用于定义消息格式的 WSDL 和 XML 模式定义（XML Schema Definition，XSD）有良好的理解。如果您对 Web 服务相当陌生，最好从代码优先方法着手，本教程中将使用此方法开发 Web 服务。</p>
<p>代码优先 Web 服务开发</p>
<p>使用代码优先方法时，将从实现希望作为服务公开的功能的 Java 类或类入手。在已经提供了 Java 实现且需要将实现作为服务公开的情况下，代码优先方法尤为有用。<span id="more-257"></span></p>
<p>开发订单处理 Web 服务</p>
<p>让我们首先创建一个订单处理 Web 服务，用于接受订单信息、配送信息和订购物品并最终生成确认 ID 作为响应。订单处理服务的代码如清单 1 中所示。这是一个虚拟实现，将在控制台输出客户 ID 和物品数量，然后输出虚拟订单 ID A1234。（可以在本文的下载部分下载完整的应用程序源代码。）将源代码解压到 C 盘，会在其中创建一个名为 JAXWS-Tutorial 的文件夹。此文件夹包含对应的源代码，如清单 1 中所示。</p>
<p>清单 1. 订单处理 Web 服务实现</p>
<pre name="code" class="java">package com.ibm.jaxws.tutorial.service;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import com.ibm.jaxws.tutorial.service.bean.OrderBean;

//JWS annotation that specifies that the portType name of the
//Web service is "OrderProcessPort," the service name
//is "OrderProcess," and the targetNamespace used in the generated
//WSDL is "http://jawxs.ibm.tutorial/jaxws/orderprocess."

@WebService(serviceName = "OrderProcess",
        portName = "OrderProcessPort",
        targetNamespace = "http://jawxs.ibm.tutorial/jaxws/orderprocess")

//JWS annotation that specifies the mapping of the service onto the
// SOAP message protocol. In particular, it specifies that the SOAP messages
//are document literal.
@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,use=SOAPBinding.Use.LITERAL,
            parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)

public class OrderProcessService {

    @WebMethod
    public OrderBean processOrder(OrderBean orderBean) {

        // Do processing...
        System.out.println("processOrder called for customer"
                + orderBean.getCustomer().getCustomerId());

        // Items ordered are
        if (orderBean.getOrderItems() != null) {
            System.out.println("Number of items is "
                    + orderBean.getOrderItems().length);
        }

        //Process order.

        //Set the order ID.
        orderBean.setOrderId("A1234");

        return orderBean;
    }
}</pre>
<p>OrderBean 中包含订单信息，如清单 2 中所示。具体来说，其中包含对客户、订单项和配送地址对象的引用。</p>
<p>清单 2. 包含订单信息的 OrderBean 类</p>
<pre name="code" class="java">package com.ibm.jaxws.tutorial.service.bean;

public class OrderBean {

    private Customer customer;

    private Address shippingAddress;

    private OrderItem[] orderItems;

    private String orderId;

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }

    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    public Address getShippingAddress() {
        return shippingAddress;
    }

    public void setShippingAddress(Address shippingAddress) {
        this.shippingAddress = shippingAddress;
    }

    public OrderItem[] getOrderItems() {
        return orderItems;
    }

    public void setOrderItems(OrderItem[] orderItems) {
        this.orderItems = orderItems;
    }
}</pre>
<p>开发 JAX-WS Web 服务的起点是一个使用 javax.jws.WebService Annotation 进行了标注的 Java 类。所使用的 JAX-WS Annotation 属于 Web Services Metadata for the Java Platform 规范 (JSR-181) 的一部分。您可能已经注意到了，OrderProcessService 使用 WebService Annotation 进行了标注，而后者将类定义为了 Web 服务端点。</p>
<p>OrderProcessService 类（带有 @javax.jws.WebService Annotation 的类）隐式地定义了服务端点接口（Service Endpoint Interface，SEI），用于声明客户机可以对服务调用的方法。除了使用 @WebMethod Annotation 标注且 exclude 元素设置为 true 的方法外，类中定义的所有公共方法都会映射到 WSDL 操作。@WebMethod Annotation 是可选的，用于对 Web 服务操作进行自定义。除了 exclude 元素外，javax.jws.WebMethod Annotation 还提供 operation name 和 action 元素，用于在 WSDL 文档中自定义操作的 name 属性和 SOAP action 元素。这些属性是可选的；如果未定义，会从类名称派生缺省值。</p>
<p>实现 Web 服务后，需要生成部署服务所需的所有构件，然后将 Web 服务打包为部署构件（通常为 WAR 文件），并将 WAR 文件部署到任何支持 JAX-WS 2.0 规范的兼容服务器上。通常生成的构件是提供基于服务接口将 Java 对象转换为 XML、WSDL 文件和 XSD 模式的功能的类。</p>
<p>出于测试目的，Java 6 绑定了一个轻量级 Web 服务器，可以通过调用简单的 API 调用将 Web 服务发布到该服务器上。接下来我们将了解如何使用此方法测试 Web 服务。</p>
<h3>发布服务</h3>
<h4>生成 JAX-WS 构件</h4>
<p>运行 wsgen 工具，以生成订单处理 Web 服务的 JAX-WS 可移植构件。此工具将读取 Web SEI 类，并生成 Web 服务部署和调用所需的所有构件。wsgen 工具生成需要发布的 Web 服务的 WSDL 文件和 XSD 模式。</p>
<p>为了生成 JAX-WS 构件，首先需要编译服务和 Bean 源文件：</p>
<ul>
<li>打开命令提示符，并进入到 c:\JAXWS-Tutorial目录。</li>
<li>运行以下命令，以编译 Java 文件，并将类文件放入其各自文件夹中：</li>
</ul>
<p style="padding-left: 30px;">javac com\ibm\jaxws\tutorial\service\*.java com\ibm\jaxws\tutorial\service\bean\*.java</p>
<ul>
<li>运行以下命令，以生成 JAX-WS 构件：</li>
</ul>
<p style="padding-left: 30px;">wsgen -cp . com.ibm.jaxws.tutorial.service.OrderProcessService -wsdl</p>
<p>wsgen 工具提供了大量的选项，例如，其中提供了 -wsdl 选项，用于生成服务的 WSDL 和模式构件。运行此命令后，应该在 JAXWS-Tutorial 文件夹中看到生成的 OrderProcess.wsdl 和 OrderProcess_schema1.xsd，而且会看到在 com\ibm\jaxws\tutorial\service\jaxws 文件夹中创建了 JAX-WS 构件。</p>
<p>生成了构件后，运行以下 Web 服务发布器客户机，以发布订单处理 Web 服务。</p>
<ul>
<li>从 c:\JAXWS-Tutorial 文件夹运行以下命令，以编译 OrderWebServicePublisher：</li>
</ul>
<p style="padding-left: 30px;">javac com\ibm\jaxws\tutorial\service\publish\OrderWebServicePublisher.java</p>
<ul>
<li>然后运行以下命令：</li>
</ul>
<p style="padding-left: 30px;">java com.ibm.jaxws.tutorial.service.publish.OrderWebServicePublisher</p>
<p>运行 Java 程序后，应该看到以下消息： The Web service is published at http://localhost:8080/OrderProcessWeb/orderprocess. To stop running the Web service, terminate this Java process.<br />
这会将订单 Web 服务发布到 http://localhost:8080/OrderProcessWeb/orderprocess。可以通过显示订单处理 Web 服务生成的 WSDL 来验证 Web 服务是否在运行：</p>
<ul>
<li>打开浏览器，并导航到 http://localhost:8080/OrderProcessWeb/orderprocess?wsdl。</li>
</ul>
<h4>分析 OrderWebServicePublisher</h4>
<p>在分析 WSDL 和模式构件前，让我们分析一下 OrderWebServicePublisher 的代码。清单 3 提供了 OrderWebServicePublisher 客户机的源代码。<br />
清单 3. 用于发布订单处理 Web 服务的代码</p>
<pre name="code" class="java">package com.ibm.jaxws.tutorial.service.publish;

import javax.xml.ws.Endpoint;

import com.ibm.jaxws.tutorial.service.OrderProcessService;

public class OrderWebServicePublisher {

    public static void main(String[] args) {

Endpoint.publish("http://localhost:8080/OrderProcessWeb/orderprocess",
                new OrderProcessService());

    }

}</pre>
<p>通过 Endpoint.publish() 方法，可以方便地发布和测试 JAX-WS Web 服务。publish() 接受两个参数：Web 服务的位置和 JAX-WS Web 服务实现类。publish() 方法在指定的 URL（本例中为本地主机，端口为 8080）创建轻量级 Web 服务器，并将 Web 服务部署到该位置。此轻量级 Web 服务器在 Java 虚拟机（Java Virtual Machine，JVM）中运行，可通过调用 endpoint.stop() 方法以有条件的方式终止，或终止 OrderWebServicePublisher 客户机。</p>
<h4>分析生成的 WSDL</h4>
<p>要查看生成的订单处理 Web 服务 WSDL，在浏览器中键入以下 URL 位置： http://localhost:8080/OrderProcessWeb/orderprocess?wsdl.</p>
<p>让我们分析 WSDL 一些重要方面的内容，并了解如何基于 JAX-WS 元数据生成 WSDL 和模式构件，首先要分析的是生成的 XSD。此内容使用 xsd:import 标记导入到 WSDL 文件中（请参见清单 4）；schemaLocation 指定 XSD 的位置。<br />
清单 4. 包含订单处理模式定义的 WSDL 文件<br />
&lt;types&gt;<br />
&lt;xsd:schema&gt;<br />
&lt;xsd:import namespace=&#8221;http://jawxs.ibm.tutorial/jaxws/orderprocess&#8221;<br />
schemaLocation=&#8221;OrderProcess_schema1.xsd&#8221;/&gt;<br />
&lt;/xsd:schema&gt;<br />
&lt;/types&gt;</p>
<p>在浏览器中打开 schemaLocation (http://localhost:8080/OrderProcessWeb/orderprocess?xsd=1)，以查看模式定义在浏览器中呈现的情况。让我们分析一下其中的情况：模式定义最开始是 targetNamspace 和 tns 声明，映射到在 OrderProcessService 的 @WebService Annotation 中定义的 targetNamespace http://jawxs.ibm.tutorial/jaxws/orderprocess。清单 5 给出了对应的代码。<br />
清单 5. 模式（Schema）命名空间声明</p>
<p>&lt;xs:schema version=&#8221;1.0&#8243;<br />
targetNamespace=&#8221;http://jawxs.ibm.tutorial/jaxws/orderprocess&#8221;<br />
xmlns:tns=&#8221;http://jawxs.ibm.tutorial/jaxws/orderprocess&#8221;<br />
xmlns:xs=&#8221;http://www.w3.org/2001/XMLSchema&#8221;&gt;</p>
<p>前面指定的 wsgen 工具命令生成两个包装 Bean 类，ProcessOrder 和 ProcessOrderResponse，分别包含订单处理 Web 服务的输入和输出消息。将基于这些包装 Bean 类生成以下模式元素：</p>
<ul>
<li>processOrder 属于 processOrder 类型，表示其中包含一个元素，且此元素的名称为 arg0，类型为 orderBean。可以看到，在 ProcessOrder 类和 processOrder 复杂类型之间存在一对一映射。</li>
</ul>
<ul>
<li>processOrderResponse 与 processOrderResponse 类型类似，后者的定义映射到 ProcessOrderResponse 类。</li>
</ul>
<p>让我们仔细分析一下清单 6 中的代码。<br />
清单 6. processOrder 的模式声明</p>
<p>&lt;xs:element name=&#8221;processOrder&#8221; type=&#8221;tns:processOrder&#8221;/&gt;<br />
&lt;xs:element name=&#8221;processOrderResponse&#8221; type=&#8221;tns:processOrderResponse&#8221;/&gt;<br />
&lt;xs:complexType name=&#8221;processOrder&#8221;&gt;<br />
&lt;xs:sequence&gt;<br />
&lt;xs:element name=&#8221;arg0&#8243; type=&#8221;tns:orderBean&#8221; minOccurs=&#8221;0&#8243;/&gt;<br />
&lt;/xs:sequence&gt;<br />
&lt;/xs:complexType&gt;</p>
<p>清单 7 中所示的 orderBean 类型定义映射到 OrderBean 类。orderBean 类型定义包括：</p>
<ul>
<li>一个 customer 元素，其类型为 customer。</li>
</ul>
<ul>
<li>一个 orderId，其类型为 string。</li>
</ul>
<ul>
<li>orderItems（它为数组类型，因为其将 maxOccurs 属性指定为 unbounded），其类型为 orderItem。</li>
</ul>
<ul>
<li>shippingAddress，其类型为 address。</li>
</ul>
<p>清单 7. processOrder 的模式声明</p>
<p>&lt;xs:complexType name=&#8221;orderBean&#8221;&gt;<br />
&lt;xs:sequence&gt;<br />
&lt;xs:element name=&#8221;customer&#8221; type=&#8221;tns:customer&#8221; minOccurs=&#8221;0&#8243; /&gt;<br />
&lt;xs:element name=&#8221;orderId&#8221; type=&#8221;xs:string&#8221; minOccurs=&#8221;0&#8243; /&gt;<br />
&lt;xs:element nillable=&#8221;true&#8221; maxOccurs=&#8221;unbounded&#8221; name=&#8221;orderItems&#8221;<br />
type=&#8221;tns:orderItem&#8221; minOccurs=&#8221;0&#8243; /&gt;<br />
&lt;xs:element name=&#8221;shippingAddress&#8221; type=&#8221;tns:address&#8221;<br />
minOccurs=&#8221;0&#8243; /&gt;<br />
&lt;/xs:sequence&gt;<br />
&lt;/xs:complexType</p>
<p>类似地，模式的其余部分 customer、orderItems 和 address 分别映射到 Customer、OrderItem 和 Address Java Bean。<br />
分析了模式定义后，接下来让我们回头来看看 WSDL 中的消息定义，如清单 8 中所示。WSDL 指定消息 processOrder 和 processOrderResponse，其所属的元素为 processOrder 和 processOrderResponse（我们已经讨论了其模式定义）。portType 指定操作 processOrder，其输入消息为 processOrder，而输出消息为 processOrderResponse。<br />
清单 8. WSDL 文档中的 processOrder 消息元素</p>
<p>&lt;message name=&#8221;processOrder&#8221;&gt;<br />
&lt;part element=&#8221;tns:processOrder&#8221; name=&#8221;parameters&#8221; /&gt;<br />
&lt;/message&gt;<br />
&lt;message name=&#8221;processOrderResponse&#8221;&gt;<br />
&lt;part element=&#8221;tns:processOrderResponse&#8221; name=&#8221;parameters&#8221; /&gt;<br />
&lt;/message&gt;<br />
&lt;portType name=&#8221;OrderProcessService&#8221;&gt;<br />
&lt;operation name=&#8221;processOrder&#8221;&gt;<br />
&lt;input message=&#8221;tns:processOrder&#8221; /&gt;<br />
&lt;output message=&#8221;tns:processOrderResponse&#8221; /&gt;<br />
&lt;/operation&gt;<br />
&lt;/portType&gt;</p>
<p>接下来定义了 WSDL 绑定。此绑定将 soap:binding 样式定义为 document，soap:body 使用 literal 标记指定操作 processOrder 的输入和输出消息格式。生成的 WSDL 定义映射到 @SOAPBinding Annotation（已在 OrderProcessService 类上定义，请参见清单 9）。<br />
清单 9. WSDL 文档的绑定信息</p>
<p>&lt;binding name=&#8221;OrderProcessPortBinding&#8221; type=&#8221;tns:OrderProcessService&#8221;&gt;<br />
&lt;soap:binding style=&#8221;document&#8221; transport=&#8221;http://schemas.xmlsoap.org/soap/http&#8221; /&gt;<br />
&lt;operation name=&#8221;processOrder&#8221;&gt;<br />
&lt;soap:operation soapAction=&#8221;" /&gt;<br />
&lt;input&gt;<br />
&lt;soap:body use=&#8221;literal&#8221; /&gt;<br />
&lt;/input&gt;<br />
&lt;output&gt;<br />
&lt;soap:body use=&#8221;literal&#8221; /&gt;<br />
&lt;/output&gt;<br />
&lt;/operation&gt;<br />
&lt;/binding&gt;</p>
<p>接下来定义 WSDL 服务。这将指定端口和对应的绑定类型，以及服务的实际位置。此位置通常为 HTTP 位置，在本例中为 http://localhost:8080/OrderProcessWeb/orderprocess。可以在清单 10 中了解到具体的情况。<br />
清单 10. WSDL 文档的服务信息</p>
<p>&lt;service name=&#8221;OrderProcess&#8221;&gt;<br />
&lt;port name=&#8221;OrderProcessPort&#8221; binding=&#8221;tns:OrderProcessPortBinding&#8221;&gt;<br />
&lt;soap:address location=&#8221;http://localhost:8080/OrderProcessWeb/orderprocess&#8221; /&gt;<br />
&lt;/port&gt;</p>
<p>我们已经对生成的 WSDL 和模式构件进行了分析。清单 11 给出了一个示例 SOAP 请求消息，此消息是在 Web 服务客户机调用 processOrder 操作时发送的。<br />
清单 11. processOrder 操作的示例 SOAP 消息</p>
<p>&lt;?xml version=&#8221;1.0&#8243;?&gt;<br />
&lt;soapenv:Envelope xmlns:soapenv=&#8221;http://schemas.xmlsoap.org/soap/envelope/&#8221;<br />
xmlns:ns1=&#8221; http://jawxs.ibm.tutorial/jaxws/orderprocess&#8221;<br />
xmlns:xsd=&#8221;http://www.w3.org/2001/XMLSchema&#8221;&gt;<br />
&lt;soapenv:Body&gt;<br />
&lt;ns1:processOrder&gt;<br />
&lt;arg0&gt;<br />
&lt;customer&gt;&lt;customerId&gt;A123&lt;/customerId&gt;<br />
&lt;firstName&gt;John&lt;/firstName&gt;&lt;lastName&gt;Smith&lt;/lastName&gt;&lt;/customer&gt;<br />
&lt;orderItems&gt;&lt;itemId&gt;11&lt;/itemId&gt;&lt;qty&gt;11&lt;/qty&gt;&lt;/orderItems&gt;<br />
&lt;/arg0&gt;<br />
&lt;/ns1:processOrder&gt;<br />
&lt;/soapenv:Body&gt;<br />
&lt;/soapenv:Envelope&gt;</p>
<h3>创建 Web 服务客户机</h3>
<h4>从 WSDL 创建 Web 服务客户机</h4>
<p>在本部分，我们将了解如何从 WSDL 创建 Web 服务客户机。JAX-WS 提供了名为 wsimport 的工具，用于从 WSDL 生成 JAX-WS 可移植构件。生成的可移植构件通常包括以下内容：</p>
<ul>
<li>SEI</li>
</ul>
<ul>
<li>服务（需要实现的服务实现类）</li>
</ul>
<ul>
<li>从模式类型生成的 JAXB 生成类</li>
</ul>
<ul>
<li>从 wsdl:fault 映射的异常类（如果有）</li>
</ul>
<p>客户机使用生成的构件调用 Web 服务。Web 服务客户机并不需要处理任何 SOAP 格式（如创建或解析 SOAP 消息）。这将由 JAX-WS 运行时予以处理，此运行时将使用生成的构件代码（JAXB 生成类）。Web 服务将处理 Java 代码（JAXB 生成类），从而减少了开发 Web 服务客户机和对 Web 服务调用操作的工作。</p>
<p>先使用 wsimport 工具从 OrderProcess WSDL 生成 JAX-WS 构件。然后要创建 Web 服务客户机，后者使用生成的构件代码调用订单处理 Web 服务。要生成 JAX-WS 构件，贤进入到 JAXWS-Tutorial 目录，并运行清单 12 中所示的 wsimport 命令。不过，进行操作前，请确保已经按照生成 JAX-WS 构件部分中的步骤 5 所述的方法，通过运行 OrderWebServicePublisher 发布了 Web 服务。</p>
<p>清单 12. 用于生成供 Web 服务客户机使用的 JAX-WS 构件的 wsimport 命令</p>
<p>wsimport -keep -p com.ibm.jaxws.tutorial.service.client</p>
<p>http://localhost:8080/OrderProcessWeb/orderprocess?wsdl</p>
<p>-keep 选项指示保留生成的文件，-p 选项指定需要在其中生成构件的包名称。http://localhost:8080/OrderProcessWeb/orderprocess?wsdl 指定 WSDL 文件的位置。以下构件是从 OrderProcessService WSDL 生成的：</p>
<ul>
<li>JAXB 类（Address、Customer, OrderBean 和 OrderItem）：通过读取 OrderProcessService WSDL 中定义的模式定义生成</li>
</ul>
<ul>
<li>RequestWrapper 和 ResponseWrapper 类（ProcessOrder 和 ProcessOrderResponse）：包装 document literal-wrapped 样式类型的输入和输出</li>
</ul>
<ul>
<li>服务类 (OrderProcess)：客户机用于请求 Web 服务的类</li>
</ul>
<ul>
<li>服务接口 (OrderProcessService)：包含着用于服务实现接口的类</li>
</ul>
<p>接下来了解一下如何使用上面生成的构件创建 Web 服务客户机。com\ibm\jaxws\tutorial\service\client 文件夹中提供了一个示例参考代码。Web 服务客户机的代码如清单 13 中所示。<br />
清单 13. 订单处理 Web 服务客户机的代码清单</p>
<pre name="code" class="java">package com.ibm.jaxws.tutorial.service.client;

import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.namespace.QName;

public class OrderClient {

    final QName qName = new QName(
            "http://jawxs.ibm.tutorial/jaxws/orderprocess", "OrderProcess");

    public static void main(String[] args) {
        if (args.length != 1) {
            System.out
                    .println("Specify the URL of the OrderProcess Web Service");
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error:  The previous line is longer than the max of 90 characters ---------|
            System.exit(-1);
        }
        URL url = getWSDLURL(args[0]);
        OrderClient client = new OrderClient();
        client.processOrder(url);
    }

    private static URL getWSDLURL(String urlStr) {
        URL url = null;
        try {
            url = new URL(urlStr);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        return url;
    }

    public void processOrder(URL url) {

        OrderProcess orderProcessingService = new OrderProcess(url, qName);

        System.out.println("Service is" + orderProcessingService);

        OrderBean order = populateOrder();

        OrderProcessService port = orderProcessingService.getOrderProcessPort();
        OrderBean orderResponse = port.processOrder(order);

        System.out.println("Order id is " + orderResponse.getOrderId());

    }

    private OrderBean populateOrder() {

        OrderBean order = new OrderBean();
        Customer customer = new Customer();
        customer.setCustomerId("A123");
        customer.setFirstName("John");
        customer.setLastName("Smith");
        order.setCustomer(customer);

        // Populate Order Item.
        OrderItem item = new OrderItem();
        item.setItemId("11");
        item.setQty(11);

        order.getOrderItems().add(item);
        return order;
    }
}</pre>
<p>上面列出的 Web 服务客户机代码执行以下任务：</p>
<ul>
<li>通过传入 OrderProcess Web 服务的 WSDL URL 和服务的 QName 创建 OrderProcess 类的实例。</li>
<li>创建 OrderBean 的实例，并使用 populateOrder() 方法填充订单信息。</li>
<li>对服务调用 getOrderProcessPort()，以检索到服务的代理（也称为端口）。端口实现服务所定义的接口。</li>
<li>调用端口的 processOrder 方法，并同时传入在上面的第二个列表项目中创建的 OrderBean 实例。</li>
<li>从服务获得 OrderBean 响应并输出订单 ID。</li>
</ul>
<h3>运行 Web 服务客户机</h3>
<p>要运行 Web 服务客户机，请首先从 JAXWS-Tutorial 文件夹运行以下命令来编译 Web 服务客户机：</p>
<p style="padding-left: 30px;">javac com\ibm\jaxws\tutorial\service\client\OrderClient.java</p>
<p>通过使用以下命令提供订单处理 Web 服务的 WSDL URL 来运行 Web 服务客户机：</p>
<p style="padding-left: 30px;">java com.ibm.jaxws.tutorial.service.client.OrderClient http://localhost:8080/OrderProcessWeb/orderprocess?wsdl</p>
<p>运行 Web 服务客户机时，会在控制台看到以下输出（OrderWebServicePublisher 在控制台中运行）：</p>
<p style="padding-left: 30px;">processOrder called for customer A123 Number of items is 1</p>
<p>在运行 Web 服务客户机的控制台中，会得到以下输出：</p>
<p style="padding-left: 30px;">Order id is A1234</p>
<p>如上面的客户机代码中所示，并不会处理调用 Web 服务操作时使用的任何基于 SOAP 或 XML 的格式；相反，需要处理的是输入和输出消息的 JAXB 生成类，并使用服务接口和服务类对象（充当 Web 服务调用的存根）。存根负责从 JAXB Annotation 创建 SOAP 请求，并将 SOAP 响应转换回 Java 对象。</p>
<p>您现在已经成功地创建和发布了 Web 服务，并通过 Web 服务客户机成功地执行了此服务。</p>
<h3>总结</h3>
<p>在本教程中，我们了解了如何使用代码优先的开发方法和 JAX-WS 技术设计和开发 Web 服务。JAX-WS 是一个非常不错的选择，因为其中提供了完整的 Web 服务堆栈，以简化 Web 服务的开发和部署。</p>
<p>本教程中开发的订单处理 Web 服务使用 Document 样式的 Web 服务，可确保服务使用者和服务提供者使用 XML 文档进行通信。XML 文档遵循定义良好的契约，而此类契约通常都是使用 XML 模式定义创建的。XML 模式格式指定服务使用者能够调用和遵循的业务消息的契约。Document 样式的 Web 服务应该是开发企业 Web 服务的首选方法。</p>
<h3>关于作者</h3>
<p>Naveen Balani 在 IBM India 担任 WebSphere Business Services Fabric 的开发经理。他是 developerWorks 的固定投稿人，撰写过关于 Web 服务、ESB、JMS、SOA、体系结构、开放源代码框架、语义 Web、J2ME、Persuasive Computing、Spring、Ajax 和各种 IBM 产品的大量文章。他目前正在与人合著一本关于 Spring 2 与 Web 服务的书。</p>
<h3  class="related_post_title">Related Posts:</h3><ul class="related_post"><li>2008/11/21 -- <a href="http://blog.baturu.com/index.php/2008/11/21/jax-ws-to-develop-a-webservice.html" title="JAX-WS 开发 web service">JAX-WS 开发 web service</a></li><li>2010/08/15 -- <a href="http://blog.baturu.com/index.php/2010/08/15/customize_java_packages_generated_by_xmlbeans.html" title="定制 xmlbeans 所生成的 package">定制 xmlbeans 所生成的 package</a></li><li>2010/07/16 -- <a href="http://blog.baturu.com/index.php/2010/07/16/wait_and_notifyall_in_java_multithreading.html" title="wait and notifyAll in Java multi-threading">wait and notifyAll in Java multi-threading</a></li><li>2010/07/13 -- <a href="http://blog.baturu.com/index.php/2010/07/13/5_things_you_didnt_know_about_java_util_concurrent.html" title="关于 java.util.concurrent 您不知道的 5 件事(转载)">关于 java.util.concurrent 您不知道的 5 件事(转载)</a></li><li>2010/05/07 -- <a href="http://blog.baturu.com/index.php/2010/05/07/executor_in_java_util_concurrent.html" title="java.util.concurrent 中的 Executor">java.util.concurrent 中的 Executor</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.baturu.com/index.php/2008/12/04/design-and-develop-webservice-with-jax-ws-20.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JAX-WS 开发 web service</title>
		<link>http://blog.baturu.com/index.php/2008/11/21/jax-ws-to-develop-a-webservice.html</link>
		<comments>http://blog.baturu.com/index.php/2008/11/21/jax-ws-to-develop-a-webservice.html#comments</comments>
		<pubDate>Fri, 21 Nov 2008 06:48:35 +0000</pubDate>
		<dc:creator>javafuns</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[Webservice]]></category>

		<guid isPermaLink="false">http://blog.baturu.com/?p=230</guid>
		<description><![CDATA[JAX-WS 代表 Java API for XML Web Services. JAX-WS 技术用于创建 web services 和 clients, 彼此之间使用 XML 通信. JAX-WS 允许开发者编写 message-oriented 和 RPC-oriented web services. 通过使用 JAX-WS, clients and web services 具有一个很大的优势: Java 编程语言的平台中立性. 另外, JAX-WS 是不受限制的: 一个 JAX-WS client 能够访问一个非运行于 Java 平台的 web service, 反之亦然. 这种灵活性是可能的, 因为 JAX-WS 使用 World Wide Web Consortium (W3C) 定义的技术: [...]]]></description>
			<content:encoded><![CDATA[<p>JAX-WS 代表 Java API for XML Web Services. JAX-WS 技术用于创建 web services 和 clients, 彼此之间使用 XML 通信. JAX-WS 允许开发者编写 message-oriented 和 RPC-oriented web services.</p>
<p>通过使用 JAX-WS, clients and web services 具有一个很大的优势: Java 编程语言的平台中立性. 另外, JAX-WS 是不受限制的: 一个 JAX-WS client 能够访问一个非运行于 Java 平台的 web service, 反之亦然. 这种灵活性是可能的, 因为 JAX-WS 使用 World Wide Web Consortium (W3C) 定义的技术: HTTP, SOAP, 和 Web Service Description Language (WSDL). WSDL 指定了一种 XML 格式用于描述一个由一组 endpoints 组成的 service.<br />
<strong>创建一个 web service 和 client 的基本步骤如下:</strong></p>
<p style="padding-left: 30px;">1. 编写实现类.<br />
2. 编译这个实现类.<br />
3. 使用 wsgen 生成必需的一些相关类或资源以发布服务.<br />
4. 将这些文件打包为一个 WAR.<br />
5. 发布该 WAR. The tie classes (用于与 clients 通信) 由应用服务器在发布时生成.<br />
6. 编写 client 类.<br />
7. 使用 wsimport 生成和编译 stub 文件.<br />
8. 编译这个 client 类.<br />
9. 运行该 client.</p>
<p><strong>详细步骤:</strong><br />
(你也可以定义一个 Java interface 作为 service endpoint interface &#8211; SEI, 尽管这不是必须的，因为 web service 实现类会暗中定义一个 SEI.<br />
你可能会通过在实现类中添加 endpointInterface 元素来指定一个明确的 SEI. 随后，你必须提供一个定义了公共方法且在该 endpoint 实现类中具有相应具体实现的 SEI.</p>
<p>JAX-WS Endpoint 的要求<br />
JAX-WS endpoints 必须遵从下列要求:<br />
• 实现类必须以 javax.jws.WebService or javax.jws.WebServiceProvider 注释进行标注.<br />
• 实现类可能会通过 @WebService 的 endpointInterface 明确引用一个 SEI, 但不是必须要求这样去做. 如果在 @WebService 中没有指定任何 endpointInterface, 将会为该实现类暗中定义一个 SEI.<br />
• 实现类的业务方法必须是 public, 且务必不可声明为 static or final.<br />
• 暴露给 web service clients 的业务方法必须用 javax.jws.WebMethod 进行标注.<br />
• 暴露给 web service clients 的业务方法必须具有与 JAXB 兼容的参数和返回类型.<br />
• 实现类务必不可声明为 final 且务必不可是 abstract.<br />
• 实现类必须有一个缺省的 public 构造方法.<br />
• 实现类务必不可定义 finalize 方法.<br />
• 实现类可能会在它的方法上使用 javax.annotation.PostConstruct or javax.annotation.PreDestroy 注释作为生命周期事件的回调.<br />
@PostConstruct 方法会在实现类开始响应客户端请求前被容器调用.<br />
@PreDestroy 方法会在 endpoint 被从 operation 中移除前被容器调用.</p>
<p><strong>一个简单的例子</strong></p>
<p><strong>a) 编写实现类：</strong></p>
<pre name="code" class="java">package helloservice.endpoint;
import javax.jws.WebService;

@WebService()
public class Hello {
    private String message = new String("Hello, ");

    public Hello() {}

    @WebMethod()
    public String sayHello(String name) {
        return message + name + ".";
    }
}</pre>
<p>@WebService() 表明这是一个 web service, @WebMethod() 表示这个方法是暴露给 clients 的.</p>
<p><strong>b) 编译这个实现类：</strong></p>
<p>wsgen -d build -s build -classpath build helloservice.endpoint.Hello</p>
<p>-d 指定生成的class文件的输出位置. -s 指定生成的源文件的输出位置. -classpath 指定了要编译文件的位置, 在本例中是 endpoint 实现类, helloservice.endpoint.Hello, 在build目录下.</p>
<p><strong>c) 打包并发布该服务：</strong></p>
<p>在发布时, 服务器和 JAX-WS 运行环境会生成 web 服务调用所必需的一些资源, 包括 WSDL 文件.</p>
<p>发布后, 访问 http://localhost:8080/helloservice/hello?wsdl 可看到生成的 WSDL 文件内容.</p>
<p><strong>d) JAX-WS Client：</strong></p>
<p>JAX-WS client 通过一个 stub 调用 web 服务, 这个 stub 是一个本地对象, 扮演远程服务的代理. Stub 在开发阶段使用 wsimport 工具创建, 该工具能够基于 WSDL 文件产生 JAX-WS portable artifacts.</p>
<p>步骤如下：</p>
<ol>
<li>使用 javax.xml.ws.WebServiceRef 注释声明一个指向一个 web service 的引用. WebServiceRef 使用 wsdlLocation element 指定已发布服务的 WSDL 文件的 URI.<br />
@WebServiceRef(wsdlLocation=&#8221;http://localhost:8080/helloservice/hello?wsdl&#8221;)<br />
static HelloService service;</li>
<li>通过调用该服务的 getHelloPort 获取该服务的一个 proxy, 也俗称为 port.<br />
Hello port = service.getHelloPort();<br />
该 port 实现了该服务所定义的 SEI.</li>
<li>调用该 port 的 sayHello 方法, 给该服务传递一个 name.<br />
String response = port.sayHello(name);</li>
</ol>
<p>完整代码：</p>
<pre name="code" class="java">package simpleclient;

import javax.xml.ws.WebServiceRef;
import helloservice.endpoint.HelloService;
import helloservice.endpoint.Hello;

public class HelloClient {

    @WebServiceRef(wsdlLocation = "http://localhost:8080/helloservice/hello?wsdl")
    static HelloService service;

    public static void main(String[] args) {
        try {
            HelloClient client = new HelloClient();
            client.doTest(args);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void doTest(String[] args) {
        try {
            System.out.println("Retrieving the port from the following service: " + service);
            Hello port = service.getHelloPort();
            System.out.println("Invoking the sayHello operation on the port.");
            String name;
            if (args.length &gt; 0) {
                name = args[0];
            } else {
                name = "No Name";
            }

            String response = port.sayHello(name);
            System.out.println(response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}</pre>
<p>以上是先从代码入手开发一个web service，如果你已有 WSDL，可以通过wsimport生成相应类来开发并发布一个web service。<br />
详细的介绍不妨看看《<a title="Design and Develop JAX-WS 2.0 Web Service" href="http://docs.google.com/Doc?id=agm3d6h3tjd7_29cdhh5mc4" target="_blank">设计与开发JAX-WS 2.0 Web 服务</a>》，这是一篇来自 IBM developerworks 上的文章，很值得一看。</p>
<p>另外有一篇SUN员工的介绍 JAX-WS 的文章《<a title="JAX-WS 2.0, an HelloWorld例子" href="http://blogs.sun.com/xiaojun/entry/jax_ws_2_0_an" target="_blank"><strong>JAX-WS 2.0, an HelloWorld例子</strong></a>》，也可以作为参考。</p>
<h3  class="related_post_title">Related Posts:</h3><ul class="related_post"><li>2008/12/04 -- <a href="http://blog.baturu.com/index.php/2008/12/04/design-and-develop-webservice-with-jax-ws-20.html" title="设计与开发 JAX-WS 2.0 Web 服务">设计与开发 JAX-WS 2.0 Web 服务</a></li><li>2010/08/15 -- <a href="http://blog.baturu.com/index.php/2010/08/15/customize_java_packages_generated_by_xmlbeans.html" title="定制 xmlbeans 所生成的 package">定制 xmlbeans 所生成的 package</a></li><li>2010/07/16 -- <a href="http://blog.baturu.com/index.php/2010/07/16/wait_and_notifyall_in_java_multithreading.html" title="wait and notifyAll in Java multi-threading">wait and notifyAll in Java multi-threading</a></li><li>2010/07/13 -- <a href="http://blog.baturu.com/index.php/2010/07/13/5_things_you_didnt_know_about_java_util_concurrent.html" title="关于 java.util.concurrent 您不知道的 5 件事(转载)">关于 java.util.concurrent 您不知道的 5 件事(转载)</a></li><li>2010/05/07 -- <a href="http://blog.baturu.com/index.php/2010/05/07/executor_in_java_util_concurrent.html" title="java.util.concurrent 中的 Executor">java.util.concurrent 中的 Executor</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.baturu.com/index.php/2008/11/21/jax-ws-to-develop-a-webservice.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Custody and Ownership Transfer API Set</title>
		<link>http://blog.baturu.com/index.php/2008/07/19/uddi-v302-uddi-programmers-apis-custody-and-ownership-transfer-api-set.html</link>
		<comments>http://blog.baturu.com/index.php/2008/07/19/uddi-v302-uddi-programmers-apis-custody-and-ownership-transfer-api-set.html#comments</comments>
		<pubDate>Sat, 19 Jul 2008 12:41:11 +0000</pubDate>
		<dc:creator>javafuns</dc:creator>
				<category><![CDATA[SOA]]></category>
		<category><![CDATA[SOAP]]></category>
		<category><![CDATA[UDDI]]></category>
		<category><![CDATA[Webservice]]></category>
		<category><![CDATA[WSDL]]></category>

		<guid isPermaLink="false">http://blog.baturu.com/?p=173</guid>
		<description><![CDATA[本节定义 UDDI Custody and Ownership Transfer API Set. 通过创建一个实体, 一个发布者可以拥有该实体的所有权, 称他为这个实体的所有者. 一个保管节点必须通过授权机制维护一个实体和它的发布者的所有权关系. 多节点注册中心的每个节点必须保证集成了实体保管功能. 同样, 一个节点务必不可允许改变一个实体, 除非这个节点已经保管了这个实体. Custody and Ownership Transfer API Set 使得一个注册中心的任意节点能够相互间从一个节点向另一个节点转移一个或多个 businessEntity or tModel 的保管关系, 也允许从一个发布者向另一个发布者转移这些数据的所有权. 一个 businessEntity 所包含的实体例如它的 businessService, bindingTemplate, 和 publisherAssertion 结构作为这个 businessEntity 保管关系转移的一部分进行转移. 从保管转移的视角来说, 参与这种转移的发布者总是不同的人, 尽管可能具有这种情况: 这些发布者都是同一个人. 这两个节点可能是不同的节点, 也可能是相同的节点; 两者发布者间的节点内(intra-node)转移简单退化为节点保管关系没有变化这种情况. 因而, 在节点内(规范上为inter-node, 注:这里应该是规范笔误)转移的情况下, 暗含的是所有权转移. 在节点内(intra-node)转移时, 这种转移使得两个发布者间进行所有权转移. 例如, 一个 UDDI 注册中心, [...]]]></description>
			<content:encoded><![CDATA[<p>本节定义 UDDI Custody and Ownership Transfer API Set. 通过创建一个实体, 一个发布者可以拥有该实体的所有权, 称他为这个实体的所有者. 一个保管节点必须通过授权机制维护一个实体和它的发布者的所有权关系. 多节点注册中心的每个节点必须保证集成了实体保管功能. 同样, 一个节点务必不可允许改变一个实体, 除非这个节点已经保管了这个实体.</p>
<p>Custody and Ownership Transfer API Set 使得一个注册中心的任意节点能够相互间从一个节点向另一个节点转移一个或多个 businessEntity or tModel 的保管关系, 也允许从一个发布者向另一个发布者转移这些数据的所有权. 一个 businessEntity 所包含的实体例如它的 businessService, bindingTemplate, 和 publisherAssertion 结构作为这个 businessEntity 保管关系转移的一部分进行转移.</p>
<p>从保管转移的视角来说, 参与这种转移的发布者总是不同的人, 尽管可能具有这种情况: 这些发布者都是同一个人. 这两个节点可能是不同的节点, 也可能是相同的节点; 两者发布者间的节点内(intra-node)转移简单退化为节点保管关系没有变化这种情况. 因而, 在节点内(规范上为inter-node, 注:这里应该是规范笔误)转移的情况下, 暗含的是所有权转移. 在节点内(intra-node)转移时, 这种转移使得两个发布者间进行所有权转移.</p>
<p>例如, 一个 UDDI 注册中心, UDDI-1, 可能允许每个节点(由节点1A, 1B and 1C组成)定义节点自己的注册, 认证, 授权策略. 在这种情况下, 一个&#8221;人(person)&#8221;, (P1) 会需要审视一下所有3个节点的策略, 决定注册到哪个节点上. P1 可能选择注册了多个节点. P1 注册了 node1A. Node1A 也指定了怎样验证 P1. 如果 P1 成功通过认证, 然后发布了一个 business entity (BE1), 这样 P1 成为 BE1 的 &#8220;owner&#8221;. Node1A 称之为 BE1 的 &#8220;保管人(custodian)&#8221;. P1 也可能注册到了 node1B. 如果成功通过认证并发布了一个 business entity (BE2), 这样 P1 成为 BE2 的 &#8220;owner&#8221;. Node1B 称之为 BE2 的 &#8220;保管人(custodian)&#8221;. 注册中心 UDDI-1 或者它的节点(node1A and node1B)不会意识到 P1 其实是同一个人.</p>
<p>另一个 UDDI 注册中心, UDDI-2, 可能需要它的每个节点(node2-1, node2-2 and node2-3)使用相同的注册, 认证和授权机制. 在这种情况下, 这些策略在所有节点中都是一样的. 它们的注册, 发布和所有权关系都保持相同. 如果 P1 想要注册到 UDDI-2 中的不同节点, 那就需要在这些不同的节点中区分这些注册关系, 因为在已经注册到了 node2-1 后又试图注册到 node2-2, 将会遭遇 &#8220;已经注册过(already registered)&#8221; 错误 (因为根据策略, 这些节点共享相同的注册, 认证和授权).</p>
<p><span id="more-173"></span></p>
<p><strong style="font-weight: bold;">Overview</strong></p>
<p>有许多关于发布者可能选择转移实体保管人或所有权关系的场景.</p>
<p><strong style="font-weight: bold; ">节点内所有权转移(Intra-Node Ownership Transfer)</strong></p>
<p>节点内所有权转移包括在同一 UDDI 节点内, 从一个发布者向另一个发布者转移实体所有权. 这类转移的使用场景包括如下:</p>
<p style="padding-left: 30px; ">· 商业实体或者组织合并: 多个组织需要整合到一个单一发布者进行管理.</p>
<p style="padding-left: 30px; ">· Domain key generators: 所有权转移的一个用处是由一个发布者向另一个发布者转移一个 derived key generator 所有权, 使得后者可以使用这个 domain 内的 keys 发布实体.</p>
<p>save_xx APIs 也可以用于在(由同一发布者所拥有的)双亲实体间移动实体. save_service API, 例如, 能够用于在一个 business entity 和另一个 business entity 间(使用save_service API)移动 services (和 binding templates). 使用这种方式改变双亲关系将使得两个 businessEntity 结构发生改变. 见以下使用场景:</p>
<p style="padding-left: 30px; ">· 剥夺: 一个组织需要重新分配一组服务的控制权给两个或多个发布者.</p>
<p style="padding-left: 30px; ">· 注册中心实体的合并: 某个商业实体有多个实体要合并到单一一个发布者名下.</p>
<p><strong style="font-weight: bold;">节点间保管关系转移(Inter-Node Custody Transfer)</strong></p>
<p>节点间保管关系转移包括跨越 UDDI 注册中心多个节点的一组实体的保管关系转移. 所有权转移会跟随着保管关系转移而发生. 除了以上描述的节点内的使用场景, 节点间保管关系转移还可能用于下面这些用例:</p>
<p style="padding-left: 30px; ">· 令人不满的服务水平: 某节点提供的功能和服务水平不够, 发布者希望将他们的数据转移到另一个节点.</p>
<p style="padding-left: 30px; ">· UDDI 节点可用性发生变化: 某节点不再提供 UDDI 服务, 所有发布者都需要迁移到注册中心的其它节点上.</p>
<p style="padding-left: 30px; ">· 组织合并, 剥夺或巩固: 组织结构变化可能导致需要更改负责管理注册中心各节点上实体的发布者.</p>
<p>对于节点内和节点间的这些使用场景, 本系列提供了一个机制便于在节点间转移 businessEntity 和 tModel 实体的保管关系, 不管是否实体是在单一一个节点内转移, 或者不管是否是在注册中心的多个节点间转移这种保管关系.</p>
<p><strong style="font-weight: bold;">保管关系转移时的特殊考虑</strong></p>
<p>当一个 businessEntity 被转移时, 所有相关 businessService and bindingTemplate elements 也被转移. 另外, 任何引用了这个 businessEntity element 的 businessKey 的 publisherAssertion elements 也会被转移.</p>
<p>注意, 在一次保管关系转移请求中, 并不会要求该放弃保管关系的发布者转移他的所有 UDDI 实体(也就是 businessEntity 和/或 tModel 实体), 也不会要求他将他的所有实体转移给同一接收发布者或者接收节点. UDDI 注册中心实体可以转移给任意数目的接收发布者或者接收节点.</p>
<p><strong style="font-weight: bold;">转移执行过程</strong></p>
<p>Custody and Ownership Transfer API 能够使在一个 registry 中的两个发布者 P1 and P2 和两个节点, N1 and N2, 相互配合, 将一个或多个现有 businessEntity 或 tModel, E1…En, 的保管权, 从 N1 转移到 N2, 同时也会将这些实体的所有权从 P1 转移给 P2. 相关的 businessService, bindingTemplate, and publisherAssertion 也将随它们的 businessEntities 而被转移. 从 Registry 角度来看, 这些发布者总是不同的, 尽管可能有这种情况: P1 和 P2 是同一个组织. 这两个节点可能是同一节点或者也可能不是; 在节点内从 P1 向 P2 转移所有权是一种退化情况, 节点保管关系没有改变.</p>
<p>Custody and Ownership Transfer API 分为两部分, 2个 client APIs 和 1 个节点间 API. client APIs 包括 get_transferToken 和 transfer_entities; 简而言之, 这构成了这个 API 集的 Ownership Transfer API 部分. 节点间 API 包括 transfer_ custody, 与 replication 联合使用, 组成了这个 API 集的 Custody Transfer API 部分.</p>
<p>保管权和所有权转移的总体流程如下:</p>
<p>Publisher P1 调用 N1 的 get_transferToken, 指定要转移的实体 E1…En 的 keys K1…Kn. 如果 P1 获得许可 (即, 如果 P1 具有 E1…En 所有权), N1 返回一个结构 T, 称作转移令牌, 代表了可以转移实体的授权, 包括所有与要转移的 businessEntity(owned by P1) 有关的天生所包含的那些孩子和 publisherAssertion. 转移令牌(transferToken) 结构包含一个不易阅读的只有产生它的节点才能理解的字符串, 一个过期时间, 和一个节点标识符.</p>
<p>P1 然后将 T 交给 P2 (通常是通过安全方式, 因为 T 是很重要的). 欲获得保管信息的发布者在他/她能够完成保管权的转移之前, 需要先获取接收该实体保管权的节点上的一个发布者帐号. P2 接着调用 N2 的 transfer_entities, 传递 K1…Kn 和 T. 如果 transfer_entities 调用成功, 实体 E1…En 和它们相关的数据结构 (businessService, bindingTemplate, and publisherAssertion) 将位于 N2 保管之下, 由 P2 持有(own). 如果操作失败, 不会对这些实体产生影响. transfer_entities 的实际转移处理步骤如下.</p>
<p>如果 N1 and N2 并非是不同节点(即同一节点), 从 P1 向 P2 转移所有权完全就是节点内部操作 – 操作是如何发生的取决于实现. 如果 N1 and N2 是不同的, 当在 N2 上处理 transfer_entities 请求时, 将遵循下面的协议.</p>
<p>Upon receipt of a transfer_entities request, N2 checks that K1…Kn are valid keys. There is the possibility that P1 might transfer more data than P2 can accept due to policy-based restrictions on the limit of entities allowed to be owned by P2 at N2. As is described below, replication is used to complete the custody transfer process. A question that arises is at the time of accepting the datum related to the transfer, could N2 throw a replication error because the data being transferred exceeds the limits of user P2? Such limits can not be enforced during replication because they are node-local policy decisions from the perspective of enforcement. Thus, it is therefore possible that as a result of a custody transfer a publisher may be caused to hold more data that he/she would have been able to publish. Should this situation occur, P2 MUST not be allowed to publish any additional data unless P2 first reduces the number of entries it owns to an allowable limit.</p>
<p>If all is well, N2 invokes the inter-node API transfer_custody on N1, presenting the keys of top-level entities to be transferred, K1…Kn, P2’s identity (using the publisher’s authorizedName), N2’s node identifier (as known in the Replication Configuration structure, see Section 7.5.2 Configuration of a UDDI Node – operator element), and T. The transferToken, T, implies permission to transfer the entire content of the entities it identifies, including all of the contained entities and related publisherAssertions, if any. N1 checks to see whether T is a valid transferToken that it issued and that T represents the authority to transfer E1…En. If the validation is successful, N1 prevents further changes to entities E1… En. N1 then updates the authorizedName and nodeID of the operationalInfo of E1…En and related entities so that they are shown to be in the custody of N2 and owned by P2. Finally, N1 responds to N2 which triggers N2 to respond to the transfer_entities caller. This completes the processing for the transfer_entities request.</p>
<p>In the case that the datum being transferred is a key generator tModel, N1 will disallow further generation of keys associated with this key partition at its node.</p>
<p>Following the issue of the empty message by N1 to the transfer_custody call, N1 will submit into the replication stream a changeRecordNewData providing in the operationalInfo, N2’s nodeID identifying it as the node where the datum is being transferred to, and the authorizedName of P2. The acknowledgmentRequested attribute of this change record MUST be set to &#8220;true&#8221;.</p>
<p>The last modified date timestamp in the operationalInfo must change to reflect the custody transfer.</p>
<p>Figure 2 depicts the flow of a custody transfer between P1 and P2.</p>
<p><a href="http://blog.baturu.com/wp-content/uploads/2008/07/custody-transfer.png"><img class="aligncenter size-full wp-image-174" title="custody-transfer" src="http://blog.baturu.com/wp-content/uploads/2008/07/custody-transfer.png" alt="" width="500" height="351" /></a></p>
<p>Figure 2 &#8211; Custody Transfer</p>
<p>Once N2 receives the changes via the replication stream it assumes custody of E1…En and assigns ownership of the entities and related entities owned by P1 to P2.</p>
<h3  class="related_post_title">Related Posts:</h3><ul class="related_post"><li>2009/07/19 -- <a href="http://blog.baturu.com/index.php/2009/07/19/smtp_transport_binding_for_soap.html" title="SMTP Transport Binding for SOAP">SMTP Transport Binding for SOAP</a></li><li>2009/07/07 -- <a href="http://blog.baturu.com/index.php/2009/07/07/which-style-of-wsdl-should-i-use-reship.html" title="Which style of WSDL should I use? (reship)">Which style of WSDL should I use? (reship)</a></li><li>2008/07/15 -- <a href="http://blog.baturu.com/index.php/2008/07/15/uddi-v302-uddi-programmers-apis-value-set-api-set.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Value Set API Set">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Value Set API Set</a></li><li>2008/07/13 -- <a href="http://blog.baturu.com/index.php/2008/07/13/uddi-v302-uddi-programmers-apis-security-policy-api-set.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Security Policy API Set">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Security Policy API Set</a></li><li>2008/07/07 -- <a href="http://blog.baturu.com/index.php/2008/07/07/uddi-v302-uddi-programmers-apis-publication-api-set-3.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Publication API Set(3)">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Publication API Set(3)</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.baturu.com/index.php/2008/07/19/uddi-v302-uddi-programmers-apis-custody-and-ownership-transfer-api-set.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Value Set API Set</title>
		<link>http://blog.baturu.com/index.php/2008/07/15/uddi-v302-uddi-programmers-apis-value-set-api-set.html</link>
		<comments>http://blog.baturu.com/index.php/2008/07/15/uddi-v302-uddi-programmers-apis-value-set-api-set.html#comments</comments>
		<pubDate>Tue, 15 Jul 2008 14:54:13 +0000</pubDate>
		<dc:creator>javafuns</dc:creator>
				<category><![CDATA[SOA]]></category>
		<category><![CDATA[SOAP]]></category>
		<category><![CDATA[UDDI]]></category>
		<category><![CDATA[Webservice]]></category>
		<category><![CDATA[WSDL]]></category>

		<guid isPermaLink="false">http://blog.baturu.com/?p=171</guid>
		<description><![CDATA[当在 save_xxx 操作中使用到 keyedReference 时, 它可能会被检查是否是有效的. 类似的, 在 save_xxx 操作中使用到一个 keyedReferenceGroup element 可能也要接受检查确定其是否有效. 检查针对那些被 UDDI 注册中心认为是 &#8220;checked&#8221; 的 tModels. UDDI 提供了让第三方注册 value set 的能力, 然后控制检验过程(由 UDDI 使用)去执行这种检查. UDDI 注册中心可能支持缓存这些外部 value sets. UDDI 注册中心也可能支持外部校验. 由节点和注册中心策略确定使用哪种校验方式去执行对外部值集引用的检查. 这一系列 APIs 能够供 UDDI 注册中心和节点用在它们的校验策略中. 想提供一个外部检验能力的第三方实体可能需要使用跟 UDDI 一样的方式去实现一个 Web service(举例来说, 使用 literal encoding SOAP 作为消息传递机制), 这个 Web service 只暴露一个方法 validate_values. validate_values [...]]]></description>
			<content:encoded><![CDATA[<p>当在 save_xxx 操作中使用到 keyedReference 时, 它可能会被检查是否是有效的. 类似的, 在 save_xxx 操作中使用到一个 keyedReferenceGroup element 可能也要接受检查确定其是否有效. 检查针对那些被 UDDI 注册中心认为是 &#8220;checked&#8221; 的 tModels.<br />
UDDI 提供了让第三方注册 value set 的能力, 然后控制检验过程(由 UDDI 使用)去执行这种检查. UDDI 注册中心可能支持缓存这些外部 value sets. UDDI 注册中心也可能支持外部校验. 由节点和注册中心策略确定使用哪种校验方式去执行对外部值集引用的检查. 这一系列 APIs 能够供 UDDI 注册中心和节点用在它们的校验策略中.<br />
想提供一个外部检验能力的第三方实体可能需要使用跟 UDDI 一样的方式去实现一个 Web service(举例来说, 使用 literal encoding SOAP 作为消息传递机制), 这个 Web service 只暴露一个方法 validate_values. validate_values 接口将在随后描述.<br />
在某些情况下, 一个节点可能希望消除或者减少对外部校验 Web service 的调用次数. 它能够通过缓存那些 允许缓存的外部值集 的有效值来达到这一目的. 一个节点有两种标准选项用于获得有效值的集合. 一个是周期性从那些实现了 get_allValidValues API Web service 的值集提供者那里获得有效值集合. 另一种获得有效值缓存的方式是累积每次从 validate_values 成功获得的有效值.</p>
<p><strong>Value Set 编程接口</strong></p>
<p>本系列的 APIs 提供了一种能力: UDDI registry 可能使用这种能力对值集的引用进行校验. 注册中心策略确定哪个外部值集是受支持的, 如何支持.<br />
公共可访问的用于支持外部值集校验的 APIs 如下:</p>
<p style="padding-left: 30px;">· validate_values: 由节点使用, 允许外部值集校验 Web service 的提供者评估 keyedReferences or keyedReferenceGroups 是否是有效的. 返回一个 dispositionReport 结构.<br />
· get_allValidValues: 由支持从可缓存检查型值集缓存有效值的节点使用, 用于获得有效值的集合. 返回一个空消息或者一个 dispositionReport 结构.</p>
<p>注册中心策略可能需要提供其中一种 Web service 的值集提供者通过特定方式为这个 service 发布 bindingTemplate, 为该值集发布 tModel, 这样才能够找到正确的 Web service. 当一个值集提供者提供了其中一种 Web service, 应该在任何该提供者想要提供该值集的注册中心中为该检查型值集发布一个 tModel, 为值集提供者为该检查型值集提供的 Web service 发布一个 bindingTemplate. 该 tModel 应该具有 uddi-org:types category system 的分类, 表明值集类型(categorization, identifier, relationship, categorizationGroup), 是检查型的(checked), 并且, 如果该值集提供者允许根据节点对有效值的缓存进行校验, 也应该标明是 cacheable 类别.<br />
为了让一个值集成为检查型的, 该 tModel 必须首先引用 uddi-org:types category system 使用 checked 值将其划为 checked 的.  检查这样的值集是由注册中心和节点策略决定的.<br />
如果一个值集 tModel 被划分为 checked, 那么在试图发布一个使用到这个 checked tModel 的 keyedReference 时, 节点必须或者执行必要的校验, 或者返回 E_unsupported.<br />
该 tModel 也应该具有一个到 get_allValidValues or validate_values Web service 的 bindingTemplate 的分类引用, 这需要使用 uddi-org:validatedBy category system.<br />
get_allValidValues or the validate_values Web service 的 bindingTemplate 应该在它 tModelInstanceDetails 中引用适当的值集 tModel, 和其它该服务所适用的所有的值集 tModels.</p>
<p><span id="more-171"></span></p>
<p><strong>validate_values：</strong></p>
<p>当发布者保存的数据使用 keyedReference or keyedReferenceGroup 而引用了某检查型值集, 支持外部校验的 UDDI 节点调用适当的外部 Web service 的 validate_values API 进行校验, 这个外部 Web service 有且只有一个 API. 为了讨论方便, keyedReference elements 引用的 identifier, category, and relationship type systems 统称为检查型值集(checked value sets). keyedReferenceGroup elements 引用的 category group systems 也类似地称为 checked category group systems.<br />
检查型值集的正常用途是验证特定值(检查 keyValue 属性的值)是否存在于值集中. 对于特定值集, 值集提供者可能依据所传递数据的上下文环境进一步限制对值的使用. 提供者可以通过提供一个校验 Web service 来执行这种上下文环境检查.<br />
checked category group systems 的校验算法也类似, 依据该 checked category group system 的校验算法检查 keyedReferenceGroup elements 内容是否构成了一个有效值集合. 这种校验经常是确认它所包含的 keyedReferences 的 tModelKey 集合都是允许参加这个 category group system(Frequently such validation ensures that the value sets identified in contained keyedReferences are allowed to participate in the category group system).</p>
<p><em><strong>参数：</strong></em></p>
<p>UDDI 节点在调用 validate_values 时必须传递一个或多个 businessEntity elements, 一个或多个 businessService elements, 一个或多个 bindingTemplate elements, 一个或多个 tModel elements, 或者一个或多个 publisherAssertion elements, 作为唯一参数传给这个 Web service. 这些 elements 就是在调用 save_business, save_service, save_binding, save_tModel, add_publisherAssertion, or set_publisherAssertions API 时所传递的 UDDI 数据.<br />
如果在同一保存操作中包含了多个同一类型的 elements, 它们可以一起传递给 validate_values.<br />
可选的 authInfo 参数包含一个 authentication token. 可以通过 get_authToken API 或其它途径获得一个 authentication token. 同时服务多个注册中心的 validate_values Web services 提供者和需要限制哪些用户可以使用该 Web service 的该 service 提供者可能需要 authInfo.</p>
<p><em><strong>行为：</strong></em></p>
<p>为检查型值集所提供的 Web service 对所有引用到它的 keyedReferences or keyedReferenceGroups 执行校验. 这可以包括只检查 keyValue 值对该(由 keyedReference tModelKey 值指定的)给定值集来说是良好的. 其它期望的校验也可以, 包括利用要保存实体中的信息进行上下文敏感的检查.<br />
要保存的实体可能包含多个到某(些)值集的引用. 当要保存的实体是一个 businessEntity, 它所包含的 businessService and bindingTemplate 实体可能自己也引用该值集中的值. 不管在被保存的实体中处于何位置, 所有到该(些)值集值的引用必须被校验.<br />
如果外部值集和节点都支持缓存有效值, 节点通过检查它的缓存已经知道该被引用值是有效的, 节点可以不调用 validate_values.<br />
一个 checked category group system 按照与一个 checked value set 相同的方式对待. keyedReferenceGroup 的 tModelKey 指向 checked category group system. 如果节点通过使用它的缓存可以确定包含于 keyedReferenceGroup 中的 keyedReference elements 的 tModelKey 属性都允许参加这个 category group system, 它可能不调用 validate_values 校验到该 cacheable checked category group system 的引用.</p>
<p><em><strong>返回值：</strong></em></p>
<p>如果在被保存实体中所有被引用值对该值集或者category group system(s)来说都是有效的, 正确的响应是一个空消息.</p>
<p><em><strong>错误警告：</strong></em></p>
<p>如果出现任何错误, 或者被调用 Web service 需要指出根据外部 Web service 提供者所选择的校验算法, 被保存的数据是无效的, 那么该 Web service 必须生成一个 SOAP Fault.<br />
当使用这种方式声明一个错误时, UDDI 节点必须拒绝等候作出更改的改动并将该校验 Web service 所返回的相同的 SOAP fault 数据返回给原始调用者. 错误代码指出以下某个错误原因, 错误文本清楚指出被拒绝的 keyedReference 或者 keyedReferenceGroup 数据和被拒绝的原因.</p>
<p style="padding-left: 30px;">· E_invalidValue: keyedReference 或 keyedReferenceGroup 里的 keyedReferences 中一个或多个 keyValues 校验失败. 只需要返回第一个错误.<br />
· E_valueNotAllowed: 值可能是有效的, 但上下文环境不允许.</p>
<p style="padding-left: 30px;">
<p><em><strong>get_allValidValues：</strong></em></p>
<p>支持外部值集的 UDDI node 经某外部值集提供者许可, 可能会调用该外部值集提供者提供的一个 get_allValidValues Web service 去缓存该值集的有效值. 外部值集提供者可能提供这个 get_allValidValues Web service, UDDI node 可能会使用它. 正常的用法是返回该值集有效值的一个完整集合. 如果值集提供者确认一次需要返回太多的值, 该有效值集合可能会分多次返回.<br />
当缓存应该被注册中心的节点重新获取时, 注册中心策略可能需要该提供了 get_allValidValues Web service 的值集提供者重新发布这个值集的 tModel.<br />
get_allValidValues 同样能够用于获得一个可缓存的 category group system 中的可参与该 category group system 的值集的 tModelKeys.</p>
<p><strong><em>参数：</em></strong></p>
<p style="padding-left: 30px;">· tModelKey: 这个必需的 uddiKey 值标识了某值集或 category group system 的 tModel 的特定实例, 这个 Web service 就是用于为该 tModel 获得所有有效值. 它唯一标识 category, identifier, or category group system.<br />
· chunkToken: 当第一次调用这个 API 时有太多数据, 这个可选元素可用于分几组来连续获取这些数据. 这种情况通常发生于在 validValuesList 结构中返回了一个 chunkToken 且值不为 &#8220;0&#8243; 的时候. 为了获取下一批次数据, 返回的 chunkToken 应该用作下一次调用该 API 的参数.<br />
· authInfo: 这个可选元素包含一个 authentication token. 可使用 get_authToken API 或其它方式获得 Authentication tokens. 服务于多个注册中心的 get_allValidValues Web services 的提供者和想要限制谁可以使用自己服务的提供者可能需要 authInfo.</p>
<p><em><strong>返回值：</strong></em></p>
<p>返回的 validValuesList 结构包含外部 category or identifier system 的有效值集合. 如果 Web service 提供者希望分批次提供提供数据的话, 该列表必须包含一个 chunkToken.</p>
<p>validValuesList 有：</p>
<ol>
<li>chunkToken 元素：可选</li>
<li>validValue 元素：0..∞</li>
</ol>
<p><em><strong>行为：</strong></em></p>
<p>成功的话, 这个被调用的 Web service 在 validValuesList 中返回有效值集合. 这个结构列出所传递 tModelKey 描述的值集或 category group system 中的每个有效值. 如果在一次响应中需要返回太多值(即, 消息大小超出了 UDDI 注册中心所允许的最大字节数), 或者值集提供者想要分多个批次提供这些值, 那么在 validValueList 中包含 chunkToken element 随后再次调用这个 API 便可得到剩下的有效值.</p>
<p><em><strong>Chunking of valid values：</strong></em></p>
<p>如果值集提供者认为在一组中返回的值太多, 那么该提供者应该为该结果集提供一个 chunkToken. chunkToken 是一个基于 token 的字符串, 当这些结果分多批次跨越多次响应时, 这个 token 用于为该特定调用者维护值的集合的状态. 提供者应该建立他们自己的策略用于确定 chunkToken 的内容和格式. 一个特定值集结果集的 chunkToken 应该被用于获取成批次的(subsequent)结果. 如果再没有结果集了, chunkToken 值将是 &#8220;0&#8243; 或者省略掉(absent) chunkToken.<br />
chunkToken 是为了用作短期内分批次获得结果的目的(A chunkToken is intended as a short-term aid in obtaining contiguous results across multiple API calls), 因此可能只在很短时间内保持有效. 值集提供者可以建立策略用于确定一个 chunkToken 可以保持多久有效.</p>
<p><em><strong>错误警告：</strong></em>如果发生错误, 必须在 SOAP Fault 中返回一个 dispositionReport</p>
<p style="padding-left: 30px;">· E_invalidKeyPassed: 所传递的 tModelKey 与任何已知的 tModels 的 uddiKey 都不匹配. 无效 key 的详细信息应该包含到 dispositionReport element 中.<br />
· E_noValuesAvailable: 没有任何有效值.<br />
· E_unsupported: 这个 Web service 不支持这个 API.<br />
· E_invalidValue: chunkToken 值或者是无效的或者已经过期了.</p>
<h3  class="related_post_title">Related Posts:</h3><ul class="related_post"><li>2009/07/19 -- <a href="http://blog.baturu.com/index.php/2009/07/19/smtp_transport_binding_for_soap.html" title="SMTP Transport Binding for SOAP">SMTP Transport Binding for SOAP</a></li><li>2009/07/07 -- <a href="http://blog.baturu.com/index.php/2009/07/07/which-style-of-wsdl-should-i-use-reship.html" title="Which style of WSDL should I use? (reship)">Which style of WSDL should I use? (reship)</a></li><li>2008/07/19 -- <a href="http://blog.baturu.com/index.php/2008/07/19/uddi-v302-uddi-programmers-apis-custody-and-ownership-transfer-api-set.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Custody and Ownership Transfer API Set">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Custody and Ownership Transfer API Set</a></li><li>2008/07/13 -- <a href="http://blog.baturu.com/index.php/2008/07/13/uddi-v302-uddi-programmers-apis-security-policy-api-set.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Security Policy API Set">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Security Policy API Set</a></li><li>2008/07/07 -- <a href="http://blog.baturu.com/index.php/2008/07/07/uddi-v302-uddi-programmers-apis-publication-api-set-3.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Publication API Set(3)">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Publication API Set(3)</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.baturu.com/index.php/2008/07/15/uddi-v302-uddi-programmers-apis-value-set-api-set.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Security Policy API Set</title>
		<link>http://blog.baturu.com/index.php/2008/07/13/uddi-v302-uddi-programmers-apis-security-policy-api-set.html</link>
		<comments>http://blog.baturu.com/index.php/2008/07/13/uddi-v302-uddi-programmers-apis-security-policy-api-set.html#comments</comments>
		<pubDate>Sun, 13 Jul 2008 12:01:04 +0000</pubDate>
		<dc:creator>javafuns</dc:creator>
				<category><![CDATA[SOA]]></category>
		<category><![CDATA[SOAP]]></category>
		<category><![CDATA[UDDI]]></category>
		<category><![CDATA[Webservice]]></category>
		<category><![CDATA[WSDL]]></category>

		<guid isPermaLink="false">http://blog.baturu.com/?p=170</guid>
		<description><![CDATA[security API 包括下面 APIs: · discard_authToken: 用于通知节点以前得到的某 authentication token 不再需要了, 如果在接收到这个消息之后还有使用它的, 应该认为它是无效的. · get_authToken: 用于从一个节点请求一个使用 authInfo element 样式的 authentication token. 在使用 Inquiry API Set, Publication API Set, Custody and Ownership Transfer API Set, 和 Subscription API Set 中的 API 时, authInfo element 可能是必需的. API 是否需要 authInfo elements 是由节点策略决定的. 如果一个 authInfo element 最后并没有被丢弃, 节点可能会选择使这个 authentication token [...]]]></description>
			<content:encoded><![CDATA[<p>security API 包括下面 APIs:</p>
<p style="padding-left: 30px;">· discard_authToken: 用于通知节点以前得到的某 authentication token 不再需要了, 如果在接收到这个消息之后还有使用它的, 应该认为它是无效的.<br />
· get_authToken: 用于从一个节点请求一个使用 authInfo element 样式的 authentication token. 在使用 Inquiry API Set, Publication API Set, Custody and Ownership Transfer API Set, 和 Subscription API Set 中的 API 时, authInfo element 可能是必需的.</p>
<p>API 是否需要 authInfo elements 是由节点策略决定的. 如果一个 authInfo element 最后并没有被丢弃, 节点可能会选择使这个 authentication token 过期, 这样可以让它不再有效. 如果一个过了期的 token 被传递给一个 API, 除了 discard_authToken 外, 将返回错误 E_authTokenExpired.<br />
如果一个 UDDI 节点不支持在 API set 中使用 authInfo element, 通常它也不支持 Security API set. 如果节点支持在该节点所提供的任何 API set 中使用 authInfo element, 它应该也支持 Security API set. 一个节点可能提供另一种可替代(security api的)机制用于获得 authInfo elements.</p>
<p><strong>discard_authToken：</strong></p>
<p><strong><em>参数：</em></strong></p>
<p style="padding-left: 30px;">· authInfo: 这个必需的参数包含一个 authentication token. Authentication tokens 可使用 get_authToken API 获得.</p>
<p><em><strong>行为：</strong></em></p>
<p>Discarding an expired authToken is processed and reported as a success condition.</p>
<p><em><strong>返回值：</strong></em></p>
<p>完全成功的话, 返回一个空消息(return null).</p>
<p><em><strong>错误警告：</strong></em></p>
<p>如果在处理这个 API 调用时发生错误, 将在 SOAP Fault 中返回一个 dispositionReport 结构给调用者.</p>
<p><strong>get_authToken：</strong></p>
<p>get_authToken API 用于获得一个 authentication token. 在使用 Inquiry API Set, Publication API Set, Custody and Ownership Transfer API Set, 和 Subscription API Set 中的 API 时, 一个 authToken element 可能是必需的.</p>
<p><em><strong>参数：</strong></em></p>
<p style="padding-left: 30px;">· userID 属性: 这个必需的属性是 UDDI 节点分配给一个已授权过用户的标识符. 节点应该提供一种方式供用户获得一个在给定节点有效的 userID and password 认证信息.<br />
· cred 属性: 这个必需属性是密码或者与该用户相关联的 credential.</p>
<p><em><strong>返回值：</strong></em></p>
<p>这个 API 调用完全成功后会返回一个 authToken 结构, 包含一个有效 authInfo element, 这个 authInfo element 就可以在接下来的请求中使用.<br />
authToken element 包含一个 authInfo element. authToken element 总是作为对 get_authToken 调用的同步响应而返回.</p>
<p><em><strong>错误警告：</strong></em>发生错误时, 必须返回一个 dispositionReport element.</p>
<p style="padding-left: 30px;">· E_unknownUser: UDDI node 不接受和认可请求所传递的 userID and/or cred 参数值为有效认证信息.</p>
<h3  class="related_post_title">Related Posts:</h3><ul class="related_post"><li>2009/07/19 -- <a href="http://blog.baturu.com/index.php/2009/07/19/smtp_transport_binding_for_soap.html" title="SMTP Transport Binding for SOAP">SMTP Transport Binding for SOAP</a></li><li>2009/07/07 -- <a href="http://blog.baturu.com/index.php/2009/07/07/which-style-of-wsdl-should-i-use-reship.html" title="Which style of WSDL should I use? (reship)">Which style of WSDL should I use? (reship)</a></li><li>2008/07/19 -- <a href="http://blog.baturu.com/index.php/2008/07/19/uddi-v302-uddi-programmers-apis-custody-and-ownership-transfer-api-set.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Custody and Ownership Transfer API Set">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Custody and Ownership Transfer API Set</a></li><li>2008/07/15 -- <a href="http://blog.baturu.com/index.php/2008/07/15/uddi-v302-uddi-programmers-apis-value-set-api-set.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Value Set API Set">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Value Set API Set</a></li><li>2008/07/07 -- <a href="http://blog.baturu.com/index.php/2008/07/07/uddi-v302-uddi-programmers-apis-publication-api-set-3.html" title="UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Publication API Set(3)">UDDI 规范 v3.0.2 &#8211; UDDI Programmers APIs 之 Publication API Set(3)</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://blog.baturu.com/index.php/2008/07/13/uddi-v302-uddi-programmers-apis-security-policy-api-set.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
