﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-我是北航MSE-随笔分类-Web Service</title><link>http://www.blogjava.net/hopeshared/category/10128.html</link><description>静下心来，一切变得美好</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 11:22:54 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 11:22:54 GMT</pubDate><ttl>60</ttl><item><title>读Axis2用户帮助文档</title><link>http://www.blogjava.net/hopeshared/archive/2006/10/23/76785.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Mon, 23 Oct 2006 08:46:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/10/23/76785.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/76785.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/10/23/76785.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/76785.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/76785.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 作者：李红霞时间：2006-10-19声明：本文可以算作Axis2用户手册的翻译，但是翻译后的文本是经过作者理解写出来的，可能有些偏差，欢迎讨论。本文属作者原创，允许转载，但请注明出处。						英文原文http://ws.apache.org/axis2/1_0/userguide.html														 															...&nbsp;&nbsp;<a href='http://www.blogjava.net/hopeshared/archive/2006/10/23/76785.html'>阅读全文</a><img src ="http://www.blogjava.net/hopeshared/aggbug/76785.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-10-23 16:46 <a href="http://www.blogjava.net/hopeshared/archive/2006/10/23/76785.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>服务设计的原则：服务模式与反模式（zz）</title><link>http://www.blogjava.net/hopeshared/archive/2006/09/27/72232.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Wed, 27 Sep 2006 03:04:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/09/27/72232.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/72232.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/09/27/72232.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/72232.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/72232.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 发布日期： 12/15/2005 | 更新日期： 12/15/2005						John Evdemon				Microsoft Corporation, Architecture Strategy 团队				适用于：																												•																						企业体系结构									...&nbsp;&nbsp;<a href='http://www.blogjava.net/hopeshared/archive/2006/09/27/72232.html'>阅读全文</a><img src ="http://www.blogjava.net/hopeshared/aggbug/72232.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-09-27 11:04 <a href="http://www.blogjava.net/hopeshared/archive/2006/09/27/72232.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Implementing REST Web Services: Best Practices and Guidelines</title><link>http://www.blogjava.net/hopeshared/archive/2006/08/31/66913.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Thu, 31 Aug 2006 09:26:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/08/31/66913.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/66913.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/08/31/66913.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/66913.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/66913.html</trackback:ping><description><![CDATA[
		<span class="secondary">by <a href="http://www.xml.com/pub/au/213">Hao He</a></span>
		<br />
		<span class="secondary">August 11, 2004<br /><br />Despite the lack of vendor support, <a href="http://www1.ics.uci.edu/%7Efielding/pubs/dissertation/rest_arch_style.htm">Representational State Transfer (REST)</a> web services have won the hearts of many working developers. For example, <a href="http://www.oreillynet.com/pub/wlg/3005">Amazon's web services</a> have both SOAP and REST interfaces, and 85% of the usage is on the REST interface. Compared with other styles of web services, REST is easy to implement and has many highly desirable architectural properties: scalability, performance, security, reliability, and extensibility. Those characteristics fit nicely with the modern business environment, which commands technical solutions just as adoptive and agile as the business itself. 
<p></p><p>A few short years ago, REST had a much lower profile than <a href="http://www.xml.com/pub/a/ws/2001/04/04/soap.html">XML-RPC</a>, which was much in fashion. Now XML-RPC seems to have less mindshare. People have made significant efforts to RESTize SOAP and WSDL. The question is no longer whether to REST, but instead it's become how to be the best REST?</p><p>The purpose of this article is to summarize some best practices and guidelines for implementing RESTful web services. I also propose a number of <a href="http://www.xml.com/pub/a/2004/06/23/standards.html">informal standards</a> in the hope that REST implementations can become more consistent and interoperable. </p><!-- sidebar begins --><!-- don't move sidebars --><!-- sidebar ends --><p>The following notations are used in this article: </p><ol><li>BP: best practice 
</li><li>G: general guideline 
</li><li>PS: proposed <a href="http://www.xml.com/pub/a/2004/06/23/standards.html">informal standard</a></li><li>TIP: implementation tip 
</li><li>AR: arguably RESTful -- may not be RESTful in the strict sense </li></ol><h3>Reprising REST</h3><p>Let's briefly reiterate the REST web services architecture. REST web services architecture conforms to the W3C's <a href="http://www.w3.org/TR/webarch/">Web Architecture</a>, and leverages the architectural principles of the Web, building its strength on the proven infrastructure of the Web. It utilizes the semantics of HTTP whenever possible and most of the <a href="http://www.w3.org/TR/webarch/">principles, constraints, and best practices published by the TAG</a> also apply.</p><p>The REST web services architecture is related to the <a href="http://webservices.xml.com/pub/a/ws/2003/09/30/soa.html">Service Oriented Architecture</a>. This limits the interface to HTTP with the four well-defined verbs: GET, POST, PUT, and DELETE. REST web services also tend to use XML as the main messaging format. </p><p>[<strong>G</strong>] Implementing REST correctly requires a resource-oriented view of the world instead of the object-oriented views many developers are familiar with.</p><h4>Resource</h4><p>One of the most important concepts of web architecture is a "resource." A resource is an abstract thing identified by a <a href="http://www.w3.org/Addressing/">URI</a>. A REST service is a resource. A service provider is an implementation of a service. </p><h4>URI Opacity [<strong>BP</strong>]</h4><p>The creator of a URI decides the encoding of the URI, and users should not derive metadata from the URI itself. URI opacity only applies to the path of a URI. The query string and fragment have special meaning that can be understood by users. There must be a shared vocabulary between a service and its consumers.</p><h4>Query String Extensibility [<strong>BP</strong>, <strong>AR</strong>]</h4><p>A service provider should ignore any query parameters it does not understand during processing. If it needs to consume other services, it should pass all ignored parameters along. This practice allows new functionality to be added without breaking existing services. </p><p>[<strong>TIP</strong>] <a href="http://www.w3.org/XML/Schema">XML Schema</a> provides a good framework for defining simple types, which can be used for validating query parameters.</p><h4>Deliver Correct Resource Representation [<strong>G</strong>]</h4><p>A resource may have more than one representation. There are four frequently used ways of delivering the correct resource representation to consumers:</p><ol><li>Server-driven negotiation. The service provider determines the right representation from prior knowledge of its clients or uses the information provided in HTTP headers like Accept, Accept-Charset, Accept-Encoding, Accept-Language, and User-Agent. The drawback of this approach is that the server may not have the best knowledge about what a client really wants. 
</li><li>Client-driven negotiation. A client initiates a request to a server. The server returns a list of available of representations. The client then selects the representation it wants and sends a second request to the server. The drawback is that a client needs to send two requests. 
</li><li>Proxy-driven negotiation. A client initiates a request to a server through a proxy. The proxy passes the request to the server and obtains a list of representations. The proxy selects one representation according to preferences set by the client and returns the representation back to the client. 
</li><li>URI-specified representation. A client specifies the representation it wants in the URI query string. </li></ol><h4>Server-Driven Negotiation [<strong>BP</strong>]</h4><ol><li>When delivering a representation to its client, a server MUST check the following HTTP headers: Accept, Accept-Charset, Accept-Encoding, Accept-Language, and User-Agent to ensure the representation it sends satisfies the user agent's capability. 
</li><li>When consuming a service, a client should set the value of the following HTTP headers: Accept, Accept-Charset, Accept-Encoding, Accept-Language, and User-Agent. It should be specific about the type of representation it wants and avoid "*/*", unless the intention is to retrieve a list of all possible representations. 
</li><li>A server may determine the type of representation to send from the profile information of the client. </li></ol><h4>URI-Specified Representation [<strong>PS</strong>, <strong>AR</strong>]</h4><p>A client can specify the representation using the following query string:</p><pre><code>mimeType={mime-type}</code></pre><p>A REST server should support this query.</p><h4>Different Views of a Resource [<strong>PS</strong>, <strong>AR</strong>]</h4><p>A resource may have different views, even if there is only one representation available. For example, a resource has an XML representation but different clients may only see different portion of the same XML. Another common example is that a client might want to obtain metadata of the current representation.</p><p>To obtain a different view, a client can set a "view" parameter in the URI query string. For example:</p><pre><code>
GET http://www.example.com/abc?view=meta</code></pre><p>where the value of the "view" parameter determines the actual view. Although the value of "view" is application specific in most cases, this guideline reserves the following words:</p><ol><li>"<code>meta</code>," for obtaining the metadata view of the resource or representation. 
</li><li>"<code>status</code>," for obtaining the status of a request/transaction resource. </li></ol><h3>Service</h3><p>A service represents a specialized business function. A service is safe if it does not incur any obligations from its invoking client, even if this service may cause a change of state on the server side. A service is obligated if the client is held responsible for the change of states on server side.</p><h4>Safe Service</h4><p>A safe service should be invoked by the GET method of HTTP. Parameters needed to invoke the service can be embedded in the query string of a URI. The main purpose of a safe service is to obtain a representation of a resource.</p><h4>Service Provider Responsibility [<strong>BP</strong>]</h4><p>If there is more than one representation available for a resource, the service should negotiate with the client as discussed above. When returning a representation, a service provider should set the HTTP headers that relate to caching policies for better performance.</p><p>A safe service is by its nature idempotent. A service provider should not break this constraint. Clients should expect to receive consistent representations. </p><h4>Obligated Services [<strong>BP</strong>]</h4><p>Obligated services should be implemented using POST. A request to an obligated service should be described by some kind of XML instance, which should be constrained by a schema. The schema should be written in W3C XML Schema or Relax NG. An obligated service should be made idempotent so that if a client is unsure about the state of its request, it can send it again. This allows low-cost error recovery. An obligated service usually has the simple semantic of "process this" and has two potential impacts: either the creation of new resources or the creation of a new representation of a resource.</p><h4>Asynchronous Services</h4><p>One often hears the criticism that HTTP is synchronous, while many services need to be asynchronous. It is actually quite easy to implement an asynchronous REST service. An asynchronous service needs to perform the following:</p><ol><li>Return a receipt immediately upon receiving a request. 
</li><li>Validate the request. 
</li><li>If the request if valid, the service must act on the request as soon as possible. It must report an error if the service cannot process the request after a period of time defined in the service contract. </li></ol><h4>Request Receipt</h4><p>An example receipt is shown below:</p><p><code>&lt;receipt xmlns="http://www.xml.org/2004/rest/receipt" requestUri = "http://www.example.com/xya343343" received = "2004-10-03T12:34:33+10:00"&gt;<br />  &lt;transaction uri="http://www.example.com/xyz2343" status = "http://www.example.com/xyz2343?view=status"/&gt;<br />&lt;/receipt&gt; </code></p><p>A receipt is a confirmation that the server has received a request from a client and promises to act on the request as soon as possible. The receipt element should include a received attribute, the value of which is the time the server received the request in WXS <code>dateTime</code> type format. The <code>requestUri</code> attribute is optional. A service may optionally create a request resource identified by the <code>requestUri</code>. The request resource has a representation, which is equivalent to the request content the server receives. A client may use this URI to inspect the actual request content as received by the server. Both client and server may use this URI for future reference. </p><p>However, this is application-specific. A request may initiate more than one transaction. Each transaction element must have a URI attribute which identifies this transaction. A server should also create a transaction resource identified by the URI value. The transaction element must have a status attribute whose value is a URI pointing to a status resource. The status resource must have an XML representation, which indicates the status of the transaction. </p><h4>Transaction</h4><p>A transaction represents an atomic unit of work done by a server. The goal of a transaction is to complete the work successfully or return to the original state if an error occurs. For example, a transaction in a purchase order service should either place the order successfully or not place the order at all, in which case the client incurs no obligation. </p><h4>Status URI [<strong>BP</strong>, <strong>AR</strong>]</h4><p>The status resource can be seen as a different view of its associated transaction resource. The status URI should only differ in the query string with an additional status parameter. For example: </p><p><code>Transaction URI: http://www.example.com/xyz2343 Transaction Status URI: http://www.example.com/xyz2343?view=status </code></p><h4>Transaction Lifecycle [<strong>G</strong>]</h4><p>A transaction request submitted to a service will experience the following lifecycle as defined in <a href="http://www.w3.org/TR/wslc/">Web Service Management: Service Life Cycle</a>:</p><ol><li>Start -- the transaction is created. This is triggered by the arrival of a request. 
</li><li>Received -- the transaction has been received. This status is reached when a request is persisted and the server is committed to fulfill the request. 
</li><li>Processing -- the transaction is being processed, that is, the server has committed resources to process the request. 
</li><li>Processed -- processing is successfully finished. This status is reached when all processing has completed without any errors. 
</li><li>Failed -- processing is terminated due to errors. The error is usually caused by invalid submission. A client may rectify its submission and resubmit. If the error is caused by system faults, logging messages should be included. An error can also be caused by internal server malfunction. 
</li><li>Final -- the request and its associated resources may be removed from the server. An implementation may choose not to remove those resources. This state is triggered when all results are persisted correctly. </li></ol><p>Note that it is implementation-dependent as to what operations must be performed on the request itself in order to transition it from one status to another. The state diagram of a request (taken from <a href="http://www.w3.org/TR/wslc/">Web Service Management: Service Life Cycle</a>) is shown below: </p><p></p><table cellspacing="0" cellpadding="0" width="500" align="center" border="0"><tbody><tr><td class="secondary"><img height="136" alt="The state diagram of a request (taken from Web Service Management: Service Life Cycle)" src="http://www.xml.com/2004/08/11/graphics/image004.png" width="500" border="0" /></td></tr></tbody></table><p>As an example of the status XML, when a request is just received: </p><p><code>&lt;status state="received" timestamp="2004-10-03T12:34:33+10:00" /&gt; </code></p><p>The XML contains a state attribute, which indicates the current state of the request. Other possible values of the state attribute are processing, processed, and failed. </p><p>When a request is processed, the status XML is (non-normative):</p><p><code>&lt;status state="processed" timestamp="2004-10-03T12:34:33+10:00" &gt;<br />  &lt;result uri="http://example.com/rest/1123/xyz" /&gt;<br />&lt;/status&gt; </code></p><p>This time, a result element is included and it points to a URL where the client can GET request results. </p><p>In case a request fails, the status XML is (non-normative):</p><pre><code>
&lt;status   state="failed" timestamp="2002-10-03T12:34:33+10:00" &gt;
  &lt;error code="3" &gt;
    &lt;message&gt;A bad request. &lt;/message&gt;
    &lt;exception&gt;line 3234&lt;/exception&gt;
  &lt;/error&gt;
&lt;/status&gt;</code></pre><p>A client application can display the message enclosed within the message tag. It should ignore all other information. If a client believes that the error was not caused by its fault, this XML may serve as a proof. All other information is for internal debugging purposes. </p><h4>Request Result [<strong>BP</strong>]</h4><p>A request result view should be regarded as a special view of a transaction. One may create a request resource and transaction resources whenever a request is received. The result should use XML markup that is as closely related to the original request markup as possible. </p><h4>Receiving and Sending XML [<strong>BP</strong>]</h4><p>When receiving and sending XML, one should follow the principle of "strict out and loose in." When sending XML, one must ensure it is validated against the relevant schema. When receiving an XML document, one should only validate the XML against the smallest set of schema that is really needed. Any software agent must not change XML it does not understand. </p><h3>An Implementation Architecture</h3><p></p><table cellspacing="0" cellpadding="0" width="500" align="center" border="0"><tbody><tr><td class="secondary"><img height="218" alt="An Implementation Architecture" src="http://www.xml.com/2004/08/11/graphics/restImpl.png" width="500" border="0" /></td></tr></tbody></table><p>The architecture represented above has a pipe-and-filter style, a classical and robust architectural style used as early as in 1944 by the famous physicist, Richard Feynman, to build the first atomic bomb in his computing team. A request is processed by a chain of filters and each filter is responsible for a well-defined unit of work. Those filters are further classified as two distinct groups: front-end and back-end. Front-end filters are responsible to handle common Web service tasks and they must be light weight. Before or at the end of front-end filters, a response is returned to the invoking client. </p><p>All front-end filters must be lightweight and must not cause serious resource drain on the host. A common filter is a bouncer filter, which checks the eligibility of the request using some simple techniques: </p><ol><li>IP filtering. Only requests from eligible IPs are allowed. 
</li><li>URL mapping. Only certain URL patterns are allowed. 
</li><li>Time-based filtering. A client can only send a certain number of requests per second. 
</li><li>Cookie-based filtering. A client must have a cookie to be able to access this service. 
</li><li>Duplication-detection filter. This filter checks the content of a request and determines whether it has received it before. A simple technique is based on the hash value of the received message. However, a more sophisticated technique involves normalizing the contents using an application-specific algorithm. </li></ol><p>A connector, whose purpose is to decouple the time dependency between front-end filters and back-end filters, connects front-end filters and back-end filters. If back-end processing is lightweight, the connector serves mainly as a delegator, which delegates requests to its corresponding back-end processors. If back-end processing is heavy, the connector is normally implemented as a queue. </p><p>Back-end filters are usually more application specific or heavy. They should not respond directly to requests but create or update resources. </p><p>This architecture is known to have many good properties, as observed by Feynman, whose team improved its productivity many times over. Most notably, the filters can be considered as a standard form of computing and new filters can be added or extended from existing ones easily. This architecture has good user-perceived performance because responses are returned as soon as possible once a request becomes fully processed by lightweight filters. This architecture also has good security and stability because security breakage and errors can only propagate a limited number of filters. However, it is important to note that one must not put a heavyweight filter in the front-end or the system may become vulnerable to denial-of-service attacks. </p><!-- sidebar begins --></span>
<img src ="http://www.blogjava.net/hopeshared/aggbug/66913.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-08-31 17:26 <a href="http://www.blogjava.net/hopeshared/archive/2006/08/31/66913.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>REST vs SOAP Web Services</title><link>http://www.blogjava.net/hopeshared/archive/2006/08/31/66911.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Thu, 31 Aug 2006 09:21:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/08/31/66911.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/66911.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/08/31/66911.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/66911.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/66911.html</trackback:ping><description><![CDATA[
		<p>I am seeing a lot of new web services are implemented using a <strong>REST</strong> style architecture these days rather than a SOAP one. Lets step back a second and explain what REST is.</p>
		<p>
				<strong>What is a REST Web Service</strong>
		</p>
		<p>The acronym REST stands for <em>Representational State Transfer</em>, this basically means that each unique URL is a representation of some object. You can get the contents of that object using an HTTP GET, to delete it, you then might use a POST, PUT, or DELETE to modify the object (in practice most of the services use a POST for this).</p>
		<p>
				<strong>Who's using REST?</strong>
		</p>
		<p>All of Yahoo's web services use REST, including Flickr, del.icio.us API uses it, pubsub, bloglines, technorati, and both eBay, and Amazon have web services for both REST and SOAP.</p>
		<p>
				<strong>Who's using SOAP?</strong>
		</p>
		<p>Google seams to be consistent in implementing their web services to use SOAP, with the exception of Blogger, which uses XML-RPC. You will find SOAP web services in lots of enterprise software as well.</p>
		<p>
				<strong>REST vs SOAP</strong>
		</p>
		<p>As you may have noticed the companies I mentioned that are using REST api's haven't been around for very long, and their apis came out this year mostly. So REST is definitely the trendy way to create a web service, if creating web services could ever be trendy (lets face it you use soap to wash, and you rest when your tired). The main advantages of REST web services are:</p>
		<ul>
				<li>Lightweight - not a lot of extra xml markup 
</li>
				<li>Human Readable Results 
</li>
				<li>Easy to build - no toolkits required </li>
		</ul>
		<p>SOAP also has some advantages:</p>
		<ul>
				<li>Easy to consume - sometimes 
</li>
				<li>Rigid - type checking, adheres to a contract 
</li>
				<li>Development tools </li>
		</ul>
		<p>For consuming web services, its sometimes a toss up between which is easier. For instance Google's AdWords web service is really hard to consume (in CF anyways), it uses SOAP headers, and a number of other things that make it kind of difficult. On the converse, Amazon's REST web service can sometimes be tricky to parse because it can be highly nested, and the result schema can vary quite a bit based on what you search for.</p>
		<p>Which ever architecture you choose make sure its easy for developers to access it, and well documented.<br /><br /><br /><br /><br />原文：<a href="http://www.petefreitag.com/item/431.cfm">http://www.petefreitag.com/item/431.cfm</a></p>
<img src ="http://www.blogjava.net/hopeshared/aggbug/66911.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-08-31 17:21 <a href="http://www.blogjava.net/hopeshared/archive/2006/08/31/66911.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Building Web Services the REST Way</title><link>http://www.blogjava.net/hopeshared/archive/2006/08/31/66907.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Thu, 31 Aug 2006 09:17:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/08/31/66907.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/66907.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/08/31/66907.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/66907.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/66907.html</trackback:ping><description><![CDATA[
		<h1>
				<font face="Verdana" size="4">Building Web Services the REST Way</font>
		</h1>
		<font face="Verdana" size="2">
				<b>Roger L. Costello</b>
		</font>
		<blockquote>
				<p>
						<font face="Verdana" size="2">I will first provide a brief introduction to REST and then describe how to build Web services in the REST style. </font>
				</p>
				<h2>
						<font face="Verdana" size="2">What is REST?</font>
				</h2>
				<font face="Verdana" size="2">REST is a term coined by Roy Fielding in his Ph.D. dissertation [1] to describe an <b>architecture style</b> of networked systems. REST is an acronym standing for Representational State Transfer. </font>
				<h2>
						<font face="Verdana" size="2">Why is it called Representational State Transfer?</font>
				</h2>
				<font face="Verdana" size="2">The Web is comprised of resources. A resource is any item of interest. For example, the Boeing Aircraft Corp may define a 747 resource. Clients may access that resource with this URL:</font>
				<p>
				</p>
				<form action="">
						<blockquote>
								<pre>http://www.boeing.com/aircraft/747
</pre>
						</blockquote>
				</form>
				<font face="Verdana" size="2">A <b>representation</b> of the resource is returned (e.g., Boeing747.html). The representation places the client application in a <b>state</b>. The result of the client traversing a hyperlink in Boeing747.html is another resource is accessed. The new representation places the client application into yet another state. Thus, the client application changes (<b>transfer</b>s) state with each resource representation --&gt; Representational State Transfer!</font>
				<p>
				</p>
				<font face="Verdana" size="2">Here is Roy Fielding's explanation of the meaning of Representational State Transfer:</font>
				<p>
				</p>
				<font face="Verdana" size="2">"Representational State Transfer is intended to evoke an image of how a well-designed Web application behaves: a network of web pages (a virtual state-machine), where the user progresses through an application by selecting links (state transitions), resulting in the next page (representing the next state of the application) being transferred to the user and rendered for their use." </font>
				<h2>
						<font face="Verdana" size="2">Motivation for REST</font>
				</h2>
				<font face="Verdana" size="2">The motivation for REST was to capture the characteristics of the Web which made the Web successful. Subsequently these characteristics are being used to guide the evolution of the Web. </font>
				<h2>
						<font face="Verdana" size="2">REST - An Architectural Style, Not a Standard</font>
				</h2>
				<font face="Verdana" size="2">REST is not a standard. You will not see the W3C putting out a REST specification. You will not see IBM or Microsoft or Sun selling a REST developer's toolkit. Why? Because REST is just an architectural style. You can't bottle up that style. You can only understand it, and design your Web services in that style. (Analogous to the client-server architectural style. There is no client-server standard.)</font>
				<p>
				</p>
				<font face="Verdana" size="2">While REST is not a standard, it does use standards: </font>
				<ul>
						<li>
								<font face="Verdana" size="2">HTTP</font>
						</li>
						<li>
								<font face="Verdana" size="2">URL</font>
						</li>
						<li>
								<font face="Verdana" size="2">XML/HTML/GIF/JPEG/etc (Resource Representations)</font>
						</li>
						<li>
								<font face="Verdana" size="2">text/xml, text/html, image/gif, image/jpeg, etc (MIME Types)</font>
						</li>
				</ul>
				<h2>
						<font face="Verdana" size="2">The Classic REST System</font>
				</h2>
				<font face="Verdana" size="2">The Web is a REST system! Many of those Web services that you have been using these many years - book-ordering services, search services, online dictionary services, etc - are REST-based Web services. Alas, you have been using REST, building REST services and you didn't even know it.</font>
				<p>
				</p>
				<font face="Verdana" size="2">REST is concerned with the "big picture" of the Web. It does not deal with implementation details (e.g., using Java servlets or CGI to implement a Web service). So let's look at an example of creating a Web service from the REST "big picture" perspective. </font>
				<h2>
						<font face="Verdana" size="2">Parts Depot Web Services</font>
				</h2>
				<font face="Verdana" size="2">Parts Depot, Inc (<b>fictitious company</b>) has deployed some web services to enable its customers to: </font>
				<ul>
						<li>
								<font face="Verdana" size="2">get a list of parts</font>
						</li>
						<li>
								<font face="Verdana" size="2">get detailed information about a particular part</font>
						</li>
						<li>
								<font face="Verdana" size="2">submit a Purchase Order (PO)</font>
						</li>
				</ul>
				<font face="Verdana" size="2">Let's consider how each of these services are implemented in a RESTful fashion. </font>
				<h3>
						<font face="Verdana" size="2">Get Parts List</font>
				</h3>
				<font face="Verdana" size="2">The web service makes available a URL to a parts list resource. For example, a client would use this URL to get the parts list:</font>
				<p>
				</p>
				<form action="">
						<blockquote>
								<pre>http://www.parts-depot.com/parts
</pre>
						</blockquote>
				</form>
				<font face="Verdana" size="2">Note that "how" the web service generates the parts list is completely transparent to the client. All the client knows is that if he/she submits the above URL then a document containing the list of parts is returned. Since the implementation is transparent to clients, Parts Depot is free to modify the underlying implementation of this resource without impacting clients. This is <b>loose coupling</b>.</font>
				<p>
						<font face="Verdana" size="2">Here's the document that the client receives:</font>
				</p>
				<p>
				</p>
				<form action="">
						<blockquote>
								<pre>&lt;?xml version="1.0"?&gt;
&lt;p:Parts xmlns:p="http://www.parts-depot.com" 
         xmlns:xlink="http://www.w3.org/1999/xlink"&gt;
      &lt;Part id="00345" xlink:href="http://www.parts-depot.com/parts/00345"/&gt;
      &lt;Part id="00346" xlink:href="http://www.parts-depot.com/parts/00346"/&gt;
      &lt;Part id="00347" xlink:href="http://www.parts-depot.com/parts/00347"/&gt;
      &lt;Part id="00348" xlink:href="http://www.parts-depot.com/parts/00348"/&gt;
&lt;/p:Parts&gt;
</pre>
						</blockquote>
				</form>
				<font face="Verdana" size="2">[Assume that through content negotiation the service determined that the client wants the representation as XML (for machine-to-machine processing).] Note that the parts list has links to get detailed info about each part. This is a key feature of REST. The client transfers from one state to the next by examining and choosing from among the alternative URLs in the response document. </font>
				<h3>
						<font face="Verdana" size="2">Get Detailed Part Data</font>
				</h3>
				<font face="Verdana" size="2">The web service makes available a URL to each part resource. Example, here's how a client requests part 00345:</font>
				<p>
				</p>
				<form action="">
						<blockquote>
								<pre>http://www.parts-depot.com/parts/00345
</pre>
						</blockquote>
				</form>
				<font face="Verdana" size="2">Here's the document that the client receives:</font>
				<p>
				</p>
				<form action="">
						<blockquote>
								<pre>&lt;?xml version="1.0"?&gt;
&lt;p:Part xmlns:p="http://www.parts-depot.com"   
        xmlns:xlink="http://www.w3.org/1999/xlink"&gt;
      &lt;Part-ID&gt;00345&lt;/Part-ID&gt;
      &lt;Name&gt;Widget-A&lt;/Name&gt;
      &lt;Description&gt;This part is used within the frap assembly&lt;/Description&gt;
      &lt;Specification xlink:href="http://www.parts-depot.com/parts/00345/specification"/&gt;
      &lt;UnitCost currency="USD"&gt;0.10&lt;/UnitCost&gt;
      &lt;Quantity&gt;10&lt;/Quantity&gt;
&lt;/p:Part&gt;
</pre>
						</blockquote>
				</form>
				<font face="Verdana" size="2">Again observe how this data is linked to still more data - the specification for this part may be found by traversing the hyperlink. Each response document allows the client to drill down to get more detailed information. </font>
				<h3>
						<font face="Verdana" size="2">Submit PO</font>
				</h3>
				<font face="Verdana" size="2">The web service makes available a URL to submit a PO. The client creates a PO instance document which conforms to the PO schema that Parts Depot has designed (and publicized in a WSDL document). The client submits PO.xml as the payload of an HTTP POST.</font>
		</blockquote>
		<p>
		</p>
		<blockquote>
				<font face="Verdana" size="2">The PO service responds to the HTTP POST with a URL to the submitted PO. Thus, the client can retrieve the PO any time thereafter (to update/edit it). The PO has become a piece of information which is shared between the client and the server. The shared information (PO) is given an address (URL) by the server and is exposed as a Web service. </font>
				<h2>
						<font face="Verdana" size="2">Logical URLs versus Physical URLs</font>
				</h2>
				<font face="Verdana" size="2">A resource is a conceptual entity. A representation is a concrete manifestation of the resource. This URL: </font>
				<form action="">
						<blockquote>
								<pre>http://www.parts-depot.com/parts/00345
</pre>
						</blockquote>
				</form>
				<font face="Verdana" size="2">is a logical URL, not a physical URL. Thus, there doesn't need to be, for example, a static HTML page for each part. In fact, if there were a million parts then a million static HTML pages would not be a very attractive design.</font>
				<p>
				</p>
				<font face="Verdana" size="2">[Implementation detail: Parts Depot could implement the service that gets detailed data about a particular part by employing a Java Servlet which parses the string after the host name, uses the part number to query the parts database, formulate the query results as XML, and then return the XML as the payload of the HTTP response.]</font>
				<p>
				</p>
				<font face="Verdana" size="2">As a matter of style URLs should not reveal the implementation technique used. You need to be free to change your implementation without impacting clients or having misleading URLs. </font>
				<h2>
						<font face="Verdana" size="2">REST Web Services Characteristics</font>
				</h2>
				<font face="Verdana" size="2">Here are the characteristics of REST: </font>
				<ul>
						<li>
								<font face="Verdana" size="2">Client-Server: a pull-based interaction style: consuming components pull representations.</font>
						</li>
						<li>
								<font face="Verdana" size="2">Stateless: each request from client to server must contain all the information necessary to understand the request, and cannot take advantage of any stored context on the server.</font>
						</li>
						<li>
								<font face="Verdana" size="2">Cache: to improve network efficiency responses must be capable of being labeled as cacheable or non-cacheable.</font>
						</li>
						<li>
								<font face="Verdana" size="2">Uniform interface: all resources are accessed with a generic interface (e.g., HTTP GET, POST, PUT, DELETE).</font>
						</li>
						<li>
								<font face="Verdana" size="2">Named resources - the system is comprised of resources which are named using a URL.</font>
						</li>
						<li>
								<font face="Verdana" size="2">Interconnected resource representations - the representations of the resources are interconnected using URLs, thereby enabling a client to progress from one state to another.</font>
						</li>
						<li>
								<font face="Verdana" size="2">Layered components - intermediaries, such as proxy servers, cache servers, gateways, etc, can be inserted between clients and resources to support performance, security, etc.</font>
						</li>
				</ul>
				<h2>
						<font face="Verdana" size="2">Principles of REST Web Service Design</font>
				</h2>
				<font face="Verdana" size="2">1. The key to creating Web Services in a REST network (i.e., the Web) is to identify all of the conceptual entities that you wish to expose as services. Above we saw some examples of resources: parts list, detailed part data, purchase order.</font>
				<p>
						<font face="Verdana" size="2">2. Create a URL to each resource. The resources should be nouns, not verbs. For example, do not use this:</font>
				</p>
				<p>
				</p>
				<blockquote>
						<form action="">
								<blockquote>
										<pre>http://www.parts-depot.com/parts/getPart?id=00345
</pre>
								</blockquote>
						</form>
						<font face="Verdana" size="2">Note the verb, getPart. Instead, use a noun:</font>
						<p>
						</p>
						<form action="">
								<blockquote>
										<pre>http://www.parts-depot.com/parts/00345
</pre>
								</blockquote>
						</form>
				</blockquote>
				<font face="Verdana" size="2">3. Categorize your resources according to whether clients can just receive a representation of the resource, or whether clients can modify (add to) the resource. For the former, make those resources accessible using an HTTP GET. For the later, make those resources accessible using HTTP POST, PUT, and/or DELETE.</font>
				<p>
				</p>
				<font face="Verdana" size="2">4. All resources accessible via HTTP GET should be side-effect free. That is, the resource should just return a representation of the resource. Invoking the resource should not result in modifying the resource.</font>
				<p>
				</p>
				<font face="Verdana" size="2">5. No man/woman is an island. Likewise, no representation should be an island. In other words, put hyperlinks within resource representations to enable clients to drill down for more information, and/or to obtain related information.</font>
				<p>
				</p>
				<font face="Verdana" size="2">6. Design to reveal data gradually. Don't reveal everything in a single response document. Provide hyperlinks to obtain more details.</font>
				<p>
				</p>
				<font face="Verdana" size="2">7. Specify the format of response data using a schema (DTD, W3C Schema, RelaxNG, or Schematron). For those services that require a POST or PUT to it, also provide a schema to specify the format of the response.</font>
				<p>
				</p>
				<font face="Verdana" size="2">8. Describe how your services are to be invoked using either a WSDL document, or simply an HTML document. </font>
				<h2>
						<font face="Verdana" size="2">Summary</font>
				</h2>
				<font face="Verdana" size="2">This article described REST as an architectural style. In fact, it's the architectural style of the Web. REST describes what makes the Web work well. Adhering to the REST principles will make your services work well in the context of the Web.</font>
				<p>
				</p>
				<font face="Verdana" size="2">In a future article I will write about the evolution of the Web using the REST principles. </font>
				<h2>
						<font face="Verdana" size="2">Acknowledgement</font>
				</h2>
				<font face="Verdana" size="2">Thanks to Robert Leftwich and Philip Eskelin for their very helpful comments in creating this document. </font>
				<h2>
						<font face="Verdana" size="2">References</font>
				</h2>
				<blockquote>
						<font face="Verdana" size="2">[1] <a href="http://www.ebuilt.com/fielding/pubs/dissertation/top.htm">http://www.ebuilt.com/fielding/pubs/dissertation/top.htm</a></font>
						<p>
								<br />原文：<a href="http://www.xfront.com/REST-Web-Services.html">http://www.xfront.com/REST-Web-Services.html</a></p>
				</blockquote>
		</blockquote>
<img src ="http://www.blogjava.net/hopeshared/aggbug/66907.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-08-31 17:17 <a href="http://www.blogjava.net/hopeshared/archive/2006/08/31/66907.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：使用Jena 处理 RSS 1.0</title><link>http://www.blogjava.net/hopeshared/archive/2006/07/20/59132.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Thu, 20 Jul 2006 02:36:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/07/20/59132.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/59132.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/07/20/59132.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/59132.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/59132.html</trackback:ping><description><![CDATA[作者：Brian McBride<br />发表时间：2000年9月2日<br />原文链接：<a href="http://www.hpl.hp.co.uk/people/bwm/rdf/jena/rssinjena.htm"> http://www.hpl.hp.co.uk/people/bwm/rdf/jena/rssinjena.htm</a><br />译者：<a href="mailto:unruly_wind@sina.com">dlee</a><br />翻译时间：2001年5月26日<br /><br />    <a href="http://purl.org/rss/1.0/">RSS 1.0</a> 是最近宣布的一个格式，顺从于 W3C 的 RDF (资源定义框架)，用来分发(distributing) 站点摘要 (site summary) 和企业联合 (syndication) 元数据。一个站点摘要文档的例子可以在规范中找到。Jena 是一套实验性的用来处理 RDF 的 Java API。这篇笔记描述了一个应用程序使用 Jena 来将一个站点摘要文档翻译成 HTML。整个程序的源代码作为 RenderToHTML 可以在 Jena 发布的例子包里得到。<br /><br />    这篇文章和例子代码基于 RSS 规范候选发布版本1 (Release Candidate 1 version)。<br />    这个应用程序以创建一个 RDF 模型开始，实际上在内存中是一个 RDF statement 的集合。然后解析站点摘要文档，使用一个 RDF 解析器，并加载 statement 到新创建的模型中。<br /><br />      Model model = new ModelMem();<br />      model.read("<a href="http://www.xml.com/xml/news.rss"> http://www.xml.com/xml/news.rss</a>");<br /><br />    在写出一个样板 HTML 头后，程序列出和处理在输入流中的每个 channel。在 RDF 术语中，channel 是具有一个 rdf:type 属性的 rss:channel 的资源。我们使用 Jena API 来列出具有一个有这个值的 rdf:type 属性的所有的资源。在下面的代码中，假设输出是一个接收 HTML 输出的 PrintWriter。<br /><br />      ResIterator channels =  model.listSubjectsWithProperty(RDF.type, RSS.channel);<br />      while (channels.hasNext()) {<br />          renderChannel(channels.next(), out);<br />      }<br /><br />    为了呈现 (render) 一个 channel，程序首先写出它的 title，description 和相关的 image 和 textinput 字段 (如果有的话)。getProperty 方法用来得到 channel 的 title，link 和 description 属性，随后这些可以被呈现为 HTML。<br /><br />      void renderChannel(Resource channel, PrintStream out) <br />             throws RDFException {<br />          String url = null;<br />          String title = null;<br />          String desc = null;<br /><br />          url = channel.getProperty(RSS.link).getString();<br />          title = channel.getProperty(RSS.title).getString();<br />          desc = channel.getProperty(RSS.description).getString(); <br /><br />    一个 channel 可以有一个相关联的 image 和 textinput，测试是否存在这些属性和是否需要调用合适的方法来呈现它们是很简单的。<br /><br />      if (channel.hasProperty(RSS.image)) {<br />          renderImage(channel.getProperty(RSS.image) .getResource(), out);<br />      }<br />      if (channel.hasProperty(RSS.textinput)) {<br />          renderImage(channel.getProperty(RSS.textinput) .getResource(), out);<br />      } <br /><br />    为了处理一个 image，同样的调用被用来确定 image 的属性。<br /><br />      String url = null;<br />      String title = null;<br /><br />      // does the image have a link?<br />      if (image.hasProperty(RSS.link)) {<br />          url = image.getProperty(RSS.link).getString();<br />      }<br /><br />      // does the image have a title?<br />      if (image.hasProperty(RSS.title)) {<br />          title = image.getProperty(RSS.title).getString();<br />      } image.getProperty(SSF.title).getString();<br /><br />    然后这个 image 可以被呈现成为 output stream。textinput 以 相似的方法处理。<br /><br />    channel 有一个 items 属性，它的值为一个 RDF sequence。因此使用 getProperty 方法得到这个 sequence 就很简单的了。然后迭代每一个元素以呈现它。<br /><br />      if (channel.hasProperty(RSS.items)) {<br />          Seq items = channel.getProperty(RSS.items).getSeq();<br />          for (int i=1; i&lt;= items.size(); i++) {<br />              renderItem(items.getResource(i), out);<br />          }<br />      }<br /><br />    以相同的模式呈现每一个 items。首先得到需要呈现的 items 的属性，然后写出 HTML。<br /><br />      void renderItem(Resource item, PrintWriter out) {<br />          String url = item.getProperty(RSS.link).getString();<br />          String title = item.getProperty(RSS.title).getString();<br />          String desc = item.getProperty(RSS.description) .getString();<br />          ...<br />      }<br /><br />    使用 Jena 来处理 RSS 1.0 流是简单和直接的。<br /><br />    Brian McBride<br />    HP实验室，2000年9月2日<br />    修改于2000年12月2日 <img src ="http://www.blogjava.net/hopeshared/aggbug/59132.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-07-20 10:36 <a href="http://www.blogjava.net/hopeshared/archive/2006/07/20/59132.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：jUDDI简单安装使用</title><link>http://www.blogjava.net/hopeshared/archive/2006/07/18/58755.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Tue, 18 Jul 2006 07:04:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/07/18/58755.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/58755.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/07/18/58755.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/58755.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/58755.html</trackback:ping><description><![CDATA[jUDDI，发音（Judy），是服务于WebServices 的UDDI的java实现开源包。 
<h2>1 安装</h2><h3>1.1 下载</h3>下载地址：http://ws.apache.org/juddi/releases.html <br /><br />目前的jUDDI的最新版本是0.9rc3（Release Candidate #3 for Version 0.9），不过在这个版本中有一些的bug。 <br /><br />juddi0.9版本发布应该是不会久，可以参考下面这段话，是Viens Stephen（juddi主要开发者之一）在mail list中说的：we've closed 40+ issues since January 1, 2005. We'll be releasing a 0.9rc4 as soon as Axis 1.2 final is released and then releasing a 0.9 final a few weeks after that. （March 22, 2005） 
<h3>1.2 数据库安装</h3>UDDI需要有一个地方来存储注册的数据，因此首先要选择一个关系数据库安装。JUDDI可以使用任何支持ANSI standard SQL关系数据库（ 例如MySQL, DB2, Sybase, JdataStore等）。本实例使用MySQL。 <br /><br />数据库安装完成后，在MySQL数据库中运行juddi-0.9rc3\\sql\\mysql\\create_database.sql， juddi-0.9rc3\\sql\\mysql\\insert_publishers.sql。数据库准备完成。 
<h3>1.3 安装juddi及配置</h3>首先将juddi-0.9rc3\\webapp下的juddi文件夹复制到Tomcat下的webapps中，并将 mysql-connector-java-3.1.7\\mysql-connector-java-3.1.7-bin.jar复制到Tomcat 5.0\\webapps\\juddi\\WEB-INF\\lib下。 <br /><br />下面就是连接数据库的配置，在Tomcat/conf/server.xml的Host element中加入： <br /><pre>&lt;Context path="/juddi" docBase="juddi" debug="5" reloadable="true" crossContext="true"&gt;<br />  &lt;Logger className="org.apache.catalina.logger.FileLogger" prefix="localhost_juddiDB_log" <br />  suffix=".txt" timestamp="true"/&gt;<br />  &lt;Resource name="jdbc/juddiDB" auth="Container" type="javax.sql.DataSource"/&gt;<br />  &lt;ResourceParams name="jdbc/juddiDB"&gt;<br />    &lt;parameter&gt;<br />      &lt;name&gt;factory&lt;/name&gt;<br />      &lt;value&gt;org.apache.commons.dbcp.BasicDataSourceFactory&lt;/value&gt;<br />    &lt;/parameter&gt;<br />    &lt;!-- Maximum number of dB connections in pool. Make sure you<br />         configure your mysqld max_connections large enough to handle<br />         all of your db connections. Set to 0 for no limit. --&gt;<br />    &lt;parameter&gt;&lt;name&gt;maxActive&lt;/name&gt;&lt;value&gt;100&lt;/value&gt;&lt;/parameter&gt;<br />    &lt;!-- Maximum number of idle dB connections to retain in pool.<br />         Set to 0 for no limit. --&gt;<br />    &lt;parameter&gt;&lt;name&gt;maxIdle&lt;/name&gt;&lt;value&gt;30&lt;/value&gt;&lt;/parameter&gt;<br />    &lt;parameter&gt;&lt;name&gt;maxWait&lt;/name&gt;&lt;value&gt;10000&lt;/value&gt;&lt;/parameter&gt;<br />    &lt;!-- MySQL dB username and password for dB connections 帐号密码根据数据库安装配置修改 --&gt;<br />    &lt;parameter&gt;&lt;name&gt;username&lt;/name&gt;&lt;value&gt;root&lt;/value&gt;&lt;/parameter&gt;<br />    &lt;parameter&gt;&lt;name&gt;password&lt;/name&gt;&lt;value&gt;****&lt;/value&gt;&lt;/parameter&gt;<br />    &lt;!-- Class name for mysql JDBC driver --&gt;<br />    &lt;parameter&gt;<br />      &lt;name&gt;driverClassName&lt;/name&gt;<br />      &lt;value&gt;com.mysql.jdbc.Driver&lt;/value&gt;<br />    &lt;/parameter&gt;<br />    &lt;!-- The JDBC connection url for connecting to your MySQL dB.<br />         The autoReconnect=true argument to the url makes sure that the<br />         mm.mysql JDBC Driver will automatically reconnect if mysqld closed the<br />         connection.  mysqld by default closes idle connections after 8 hours. <br />        数据库url连接配置<br />    --&gt;<br />    &lt;parameter&gt;<br />      &lt;name&gt;url&lt;/name&gt;<br />      &lt;value&gt;jdbc:mysql://host.domain.com:3306/juddi?autoReconnect=true&lt;/value&gt;<br />    &lt;/parameter&gt;<br />    &lt;parameter&gt;<br />           &lt;name&gt;validationQuery&lt;/name&gt;<br />           &lt;value&gt;select count(*) from PUBLISHER&lt;/value&gt;<br />    &lt;/parameter&gt;<br />  &lt;/ResourceParams&gt;<br />&lt;/Context&gt;<br /></pre><h3>1.4 本地安装检查</h3>访问http://127.0.0.1:8080/juddi/happyjuddi.jsp页面，此页面检查了jUDDI所必须的包和配置的正确性，并测试数据库连接是否成功。 如果没有红色文字，即本地安装成功，即可进行webservices的发布发现等服务。 
<h2>2 测试实例</h2><br /><br />以上安装成功的是UDDI的服务器端，而进行发布、查找服务的客户端的应用则要用jUDDI、UDDI4J等包来进行开发。我们可以直接使用jUDDI自 带的测试代码来进行客户端使用的学习。 
<h3>2.1 使用uddi4j测试</h3>使用uddi4j作为客户端进行测试。 <br /><br />代码位置：juddi-0.9rc3\\src\\uddi4j\\org\\apache\\juddi\\uddi4j <br /><br />新建立好一个工程并引入此代码，然后对代码进行必要的修改，主要是包名和配置。引入必要的包，比如：junit.jar、 uddi4j.jar、juddi.jar、soap.jar等（因为欧的代码库中有很多种代码，对应很多包，不知道其他哪些是必须的了：）。 <br /><br />接着是数据库的初始化，需要插入一个可以添加其他Publisher的Publisher,sql 语句： INSERT INTO PUBLISHER (PUBLISHER_ID,PUBLISHER_NAME,ENABLIED,ADMIN) VALUES ('juddi','juddi user','true','true'); <br /><br />调试代码后，运行TestAll测试，您可能会发现测试FAILURE很多，这些当中有些是测试代码的错误，也有可能是juddi-0.9rc3的缺陷（ juddi-0.9rc3不是正式发布版）。 <br /><br />以下列举一些本测试案例测试失败的可能出现的修改方法： 
<h3>2.1.1 加载配置文件时访问不到samples.prop</h3>我的解决办法是将建立一个新配置文件位置，在工程目录下的：conf\\samples.prop。 <br /><br />在Configurator.load（）方法中代码可以这样修改： <pre>    Properties config = new Properties();<br />    try {<br />        config.load(new java.io.FileInputStream("./conf/samples.prop"));<br />    }<br />    catch (Exception e) {<br />        System.out.println("Error loading samples property file\\n" + e);<br />    }<br /></pre>解决方法很多，您可以自己思索。 
<h3>2.1.2 TransportClassName配置错误</h3>如果错误提示中有这样的报告，即可能是此错误： <br />org.xml.sax.SAXParseException: Element or attribute do not match QName production: QName::=(NCName':')?NCName. <br /><br />在当前测试实例代码中的默认配置（samples.prop）中，TransportClassName定义成org.uddi4j.transport.ApacheSOAPTransport， 而我们使用的包是axis.jar，因此需要修改成相应的类，代码修改如下： <pre># -----------------------------------------------------------------------<br /><br /># Transport classname. Typically defined on commandline as<br /><br /># -Dorg.uddi4j.TransportClassName=xxx.<br /><br /># -----------------------------------------------------------------------<br /><br />#TransportClassName=org.uddi4j.transport.ApacheSOAPTransport<br /><br /> TransportClassName=org.uddi4j.transport.ApacheAxisTransport<br /><br /># TransportClassName=org.uddi4j.transport.HPSOAPTransport<br /></pre><h3>2.1.3 TestFindBusiness案例不通过</h3>TestFindBusiness中有大小写匹配测试，但是在juddi-0.9rc3中的大小写匹配（caseSensitiveMatch）有bug，因此可以将大小写匹配的测 试案例注释掉。 
<h3>2.1.4 PublisherManager的代码错误</h3>在测试Test_save_tModel的时候_testAuthTokenExpired()中，我们测试过期验证时，在错误匹配的时候，会出现测试失败，如果捕捉这个 匹配的结果，你会发现，出错的类型是E_authTokenRequired而不是期待的E_authTokenExpired。 <br /><br />这是因为在我们所获得的AuthToken是空的，在根源就是在PublisherManager. getExpiredAuthToken(String, String)方法中，代码： <pre>RegistryProxy proxy = new RegistryProxy();<br /></pre>proxy的实例的配置是空的。因此，我们修改这个方法变成： <pre>  /**<br /><br />   * changed by xio<br /><br />   * @param publisher String<br /><br />   * @param password String<br /><br />   * @param testprops Properties:增加的参数，传入基本配置<br /><br />   * @return String<br /><br />   */<br /><br />public static String getExpiredAuthToken(String publisher, String password,<br /><br />                                           Properties testprops) {<br /><br />    Properties props = new Properties();<br /><br />    props.setProperty(RegistryProxy.ADMIN_ENDPOINT_PROPERTY_NAME,<br /><br />                      testprops.getProperty("adminURL"));<br /><br />    props.setProperty(RegistryProxy.INQUIRY_ENDPOINT_PROPERTY_NAME,<br /><br />                      testprops.getProperty("inquiryURL"));<br /><br />    props.setProperty(RegistryProxy.PUBLISH_ENDPOINT_PROPERTY_NAME,<br /><br />                      testprops.getProperty("publishURL"));<br /><br /><br /><br />    RegistryProxy proxy = new RegistryProxy(props);<br /><br />    AuthToken token = null;<br /><br />    AuthInfo authInfo = null;<br /><br />    String ret = null;<br /><br />    try {<br /><br />      token = proxy.getAuthToken(publisher, password);<br /><br />      authInfo = token.getAuthInfo();<br /><br />      ret = authInfo.getValue();<br /><br />      System.out.println("getExpiredAuthToken:" + authInfo);<br /><br />      proxy.discardAuthToken(authInfo);<br /><br />    }<br /><br />    catch (Exception ex) {<br /><br />      ex.printStackTrace();<br /><br />    }<br /><br />    return ret;<br /><br />  }<br /></pre><h3>2.2 使用jUDDI测试</h3>在juddi-0.9rc3版本中自带的代码中没有客户端的使用实例，虽然附带了整个项目代码的测试代码，但是估计没什么人喜欢从这里抽取学 习客户端使用的学习。 <br /><br />当然，学习的实例还是有的，在cvs当前的工程代码中，有个samples的文件夹，这部分代码便是一个十分齐全的实例（有几个类没完成， 但不影响：）。 <br /><br />Cvs服务器数据：http://ws.apache.org/juddi/cvs.html <br /><br />Wincvs的使用请网上下载阅读。 <br /><br />其他：在进行代码学习的同时，建议阅读webservices相关资料文档。强烈建议阅读：理解 UDDI 注册中心的 WSDL 系列 (http://www-900.ibm.com/developerWorks/cn/webservices/ws-uwsdl/part1/) <br /><br />参考资料：<br /><a href="http://wiki.apache.org/ws/jUDDI_HOW-TOs"><font color="#000000">http://wiki.apache.org/ws/jUDDI_HOW-TOs</font></a><br /><a href="http://ws.apache.org/juddi/lists.html"><font color="#000000">http://ws.apache.org/juddi/lists.html</font></a><br /><br /><p align="left">原作者：xio@qq.com<br />来 源：http://xio.mblogger.cn<br /><br /><br /><br />原文地址：<a href="http://it.13520.org/ArticleView/2005-9-7/Article_View_121697.Htm">http://it.13520.org/ArticleView/2005-9-7/Article_View_121697.Htm</a></p><img src ="http://www.blogjava.net/hopeshared/aggbug/58755.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-07-18 15:04 <a href="http://www.blogjava.net/hopeshared/archive/2006/07/18/58755.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：解读UDDI和JAXR</title><link>http://www.blogjava.net/hopeshared/archive/2006/07/18/58698.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Tue, 18 Jul 2006 02:16:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/07/18/58698.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/58698.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/07/18/58698.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/58698.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/58698.html</trackback:ping><description><![CDATA[在过去的数年中，许多开发人员都使用了各种版本的J2EE，使服务器端软件编程的情形得到了很大的改观，现在，他们将再次挑战SOAP，在服务器端软件编程方面取得更大的进展。 <br />SOAP服务的支持者认为： <br />·企业级应用服务器是服务（或事务）的集合。 <br />·可以使用的服务应当很方便地列出来供用户浏览、搜索和访问。 <br />·象现在的基于组件的开发模式那样，将应用服务器设计为服务的集合将鼓励开发人员采用更好的设计模式。 <br />·这些事务能够被重新定位、负载平衡、替代等。 <br />而对SOAP持怀疑态度的人认为，SOAP是推广CORBA和COM的又一次尝试。他们指出，要简单地访问一个对象，需要完成太多的准备性工作，而且，UDDI带来的好处也被夸大了。 <br />那么，到底哪一种观点更合理呢？对于一些思想开放的人士而言，在决定是否采用SOAP服务前，他们一定希望了解其中的一些核心技术。 <br />解密UDDI <br />我们首先来看看UDDI代表什么？UDDI是Universal Description, Discovery and Integration（统一描述、发现和集成）的缩写。UDDI的意图是作为一个注册簿，就象黄页是一个地区企业的注册簿一样。象在黄页中那样，在UDDI注册簿中，企业将在不同的目录下注册它们自己或其服务。通过浏览一个UDDI注册簿，开发人员能够查找一种服务或一个公司，并发现如何调用该服务。 <br />除了黄页外，UDDI还使用了白页和绿页。白页是企业实体列表，绿页是调用一项服务所必需的文档。 <br />UDDI的定义非常全面，足以适应不同种类的服务。一个UDDI服务定义可能代表一个传真服务或电话服务。作为一种注册簿，UDDI一般使用数据库一类的软件来实现，在该数据库中，存在一个允许发布或查询服务的有关信息。 <br />UDDI数据模型 <br />UDDI数据模型包括下面的主要元素： <br />·businessEntity：表示一个实际的企业。 <br />·businessService：表示一个企业提供的服务。 <br />·bindingTemplate：如何调用服务的说明。 <br />·tModel&gt;: Good luck understanding this! (Just kidding, I will explain this later.) <br />为了加深对UDDI数据模型的理解，我们来看看这些数据元素的UML表示法。图1是这四种主要元素之间的关系图： <br /><img src="http://www.wyt2008.com/Article/UploadFiles/200603/200632611743220.gif" /><br />从上面的图中我们可以知道，一个businessEntity（一家公司）有一个能够告诉我们更多有关公司信息的描述性URL和联系人清单，此外，businessEntity还有一个商业服务清单。每种服务可能有多种调用方法，每种调用都由一个绑定模板描述。绑定模板详细地描述了如何访问一个服务，它受益于一系列描述用户如何访问这一服务的文档。绑定模板和其必要的文档之间的联系是通过所谓的tModel完成的。在上面的图中，这种联系被简单地描述为一个绑定模板有许多tModels。在进一步地解释tModels与绑定模板的关系前，我们必须先弄清楚tModels是什么。 <br />TModel是什么？ <br />我们可以把tModel想象成数据库库中的一个独立的表，其中包含下面的字段：名字、描述、URL、唯一的关健字。实际上，tModel就是包括有名字和描述，那么使用数据库表表示它是否是一种浪费呢？我们下面就会讨论这一问题： <br />下面是一个假想的tModel数据库表中的二个实体： <br />键 名字 描述 URL <br />1 Java-class 表示一个具备完全资格的java类的名字 http://www.javasoft.com/ <br />2 Jndi-home 表示一个JNDI名字 http://www.javasoft.com/ <br /><br />在将tModel比作数据库表方面，有几点值得注意。首先，tModel是一个独立的表，意味着它可以不依赖其他软件而存在；其次，tModel是查找表，提供了键与键的表示之间的转换关系。从这一点来看，tModel象词典那样，是一个引用表。在一些数据库中，这样的表也被称作是码集。 <br />因此，如果在上面的tModel中存在下面的记录： <br />com.mycompany.HelloWorld, 1 <br />com.mycompany.HelloWorldHome, 2 <br />就意味着字符串com.mycompany.HelloWorld是一个有完整资格的Java类；而字符串com.mycompany.HelloWorldHome是一个JNDI名。 <br /><br />因此在一定程度上，tModels中唯一的键与“名字空间”这个概念差不多。为了进一步地说明这个问题，我们来看一下下面的数字： <br />904-555-1212 <br />904-555-1213 <br />1-56592-391-x <br />你能够分清这些数字的意义吗？我们需要在一个环境或名字空间中来确认，904-555-1212是电话号码，904-555-1213是传真号，1-56592-391-x是一个ISBN号。 <br />因此在tModel数据库表中，我们将需要定义三个实体：一个是电话号码；一个是传真号码，一个是ISBN号码。 <br />下面我们以mycompany公司公布了一条号码为1-800-my-helpline的电话支持热线，并在UDDI中注册。那么，我们的数据模型为： <br />company name: mycompany <br />Service name: helpline <br />tModel: key=11 (representing telephoneline), name=telephone, <br />description=telephone stuff, url: <br />some at&amp;t url <br />binding: <br />accesspoint: 1-800-my-helpline <br />tModelInstanceInfo: 11 <br /><br />有了对tModel的基本理解后，我们就可以利用UML图表来研究绑定模板与tModels之间的关系了。我在上面曾经说过，这将使我们对绑定模板如何完成UDDI的“如何调用一项服务”的要求有一个直观的理解。 <br /><img src="http://www.wyt2008.com/Article/UploadFiles/200603/200632611743600.gif" /><br />在图2中，我们讨论了一个绑定模板与tModels之间的关系。从图表中我们可以看出，一个绑定模板可以指向一个由一个tModel确定的技术规格，技术规格有二部分组成： <br />·规格的类型。（例如电子邮件、传真、WSDL、SOAP等。） <br />·确定输入和输出的文档（在SOAP服务中，这些文档可以是XML输入/输出消息格式。） <br />既然我们已经对tModels有了一定程度的详细了解，就该再讨论UDDI中更复杂的东西了，也就是身份包和类别包。 <br />理解标识符包和类别包 <br />如果说从概念上理解tModels是理解UDDI需要跨越的第一道障碍，那么理解标识符包和类别包则是需要跨越的第二道障碍。下面的例子可以帮助我们理解这二个概念。 <br />例如，您的公司在美国开展业务需要有一个税号，如果还在另外的国家（例如墨西哥）开展业务，就需要有一个墨西哥的税号。为了能够在UDDI注册簿中获取您的公司的这些信息，在UDDI中应当包括下面的内容： <br />公司名字：mycompany <br />标识符： <br />美国税号：111111 <br />墨西哥税号：2223344 <br />其他国家税号： 333333 <br /><br />...其他的xml内容 <br />&lt;identifierBag&gt; <br />&lt;keyedReference tModelKey="US-tax-code" <br />keyName="taxnumber" keyValue="1111111"&gt; <br />&lt;keyedReference tModelKey="Mexico-tax-code" <br />keyName="taxnumber" keyValue="2223344"&gt; <br />&lt;keyedReference tModelKey="other-stuff" <br />keyName="taxnumber" keyValue="333333"&gt; <br />&lt;/identifiedBag&gt; <br />... 其他的xml内容 <br />现在明白tModels如何被用作名字空间了吧。为了进一步地深化对标识符包的理解，我们在下面的图中再次解释了标识符和类别包的概念： <br /><img src="http://www.wyt2008.com/Article/UploadFiles/200603/200632611743959.gif" /><br />从上面的图中我们能够看出，标识符包是一个在特定环境中的键/值对集合，这个环境从本质上说就是能够唯一地解析名字/值对儿的名字空间，它是由tModel确定的。类别包也是如此，二者之间唯一的区别就是类别包中由tModel确定的名字空间是一个预先确定好的类别。 <br />类别包 <br />我想将公司归类于饭店，其地理位置位于杰克逊维尔。 <br />公司名字：mycompany <br />适用类： <br />企业类型：饭店 <br />所在城市：杰克逊维尔 <br />&lt;categoryBag&gt; <br />&lt;keyedReference tModelKey="BusinessTypeClassification" <br />keyName="restaurant" keyValue=".."&gt; <br />&lt;keyedReference tModelKey="CityClassification" <br />keyName="JAX" keyValue=".."&gt; <br />&lt;/categoryBag&gt; <br />现在，我们已经搞清楚了tModels是如何用在标识符和类别包中的。从本质上说，tModels就是名字空间。 <br /><br />tModels也能被分类吗？ <br />我们已经明白了企业实体是如何利用使用了类别包的。另外，UDDI也允许tModels本身被分类。 <br />我们用分层次的文件系统进行说明。目录是用来对文件进行分类的，但目录还可以在父目录下再被分类。象硬盘上的目录那样，tModels也可以被分层次地进行组织。 <br />下面我们来讨论名字为getUniversalTime()的服务，该服务将返回当前全球任一地方的时间。二家存在竞争关系的公司可能会提供这一服务的不同实现。商业服务只限于在公司内部使用，公司之外的用户是不可使用的： <br />company1:getTime() <br />company1:getCurrentTime() <br />这二者的作用相同，为了表明它们实现的是同一个被称作getUniversalTime()的服务，我们可以定义如下所示的tModel： <br />tModel <br />name：: Get Universal Time <br />category: uddi-org:types, wsdl <br />[意味着这是一个由WSDL文档定义的服务] <br />上面的定义表明getUniversalTime()是一个WSDL服务，可以由任何公司实现。 <br />既然已经阐明了tModels和包之间的关系，我们下面可以看看一个tModel的UML表示： <br /><img src="http://www.wyt2008.com/Article/UploadFiles/200603/200632611743333.gif" /><br />从上面的图表中，我们可以看出tModel基本上就是一个名字和描述，另外，它也可以包含一个URL，以提供更进一步的详细资料。它可以由一个标识符包确定和由一个类别包进行分类。 <br />我们已经知道，一个tModel所属于的类别是由UDDI━━WSDL、SOAP等预先定义好的，下面是一个uddi-org:types名字空间中预先定义类别的清单： <br />tModel <br />identifier （唯一标识符） <br />namespace <br />categorization <br />specification <br />xmlSpec <br />soapSpec <br />wsdlSpec <br />protocol <br />transport <br />signatureComponent <br />如何开始在UDDI中创建一个服务？ <br />在开始定义服务的tModel时，要求我们为服务指定一个名字和上面所列出的服务类型中的一个。当然了，如果不喜欢上面的分类可以自己创建类别。 <br />我们可以针对上面定义的tModel开发一个商业服务。在商业服务定义中，我们需要指定一个指向定义了服务的输入/输出的WSDL文档的URL。 <br /><br />在UDDI中为什么需要tModels？ <br />在UDDI中使用tModels的目的如下： <br />·对商业实体进行标识和分类 <br />·对商业服务进行标识和分类 <br />·对tModels进行标识和分类 <br />·将商业服务绑定到它们抽象的tModel定义上 <br />UDDI名词的快速参考 <br />在看有关UDDI的资料时，如果看到很深奥的术语是一件很烦人的事儿，下面我们就把一些经常用到的与UDDI有关的概念搜集起来，通过比较帮助我们对UDDI概念的理解： <br />接口和实现 <br />服务绑定是一个容器，接口依赖于其实现；绑定元素详细说明了tModelInstaceInfo和instanceDetail， 我们将再通过一个例子加深对这一问题的例子。对于“获得统一时间”服务而言，细节将提供定义了输入、输出的实际的WSDL文档，绑定的访问点将提供实现服务的物理机器和端口。了解了这些，我们可以得出如下的结论： <br />·为一种服务定义的tModel是允许多家公司提供该服务的多个实现的界面。 <br />·服务绑定是具体的实现。 <br />名字空间 <br />Java、C++和XML中都有名字空间的概念，尽管其叫法可能不同，但它们都提供了使名字有意义的环境。在UDDI中，tModel象征着“名字”。当把这个名字作为目录使用时，你的本意是，“我属于这个名字”。从这个意义上说，tModel表示的是名字空间。 <br />技术指纹 <br />当一种服务被注册为tModel时，我们可以注册用来与该服务通讯的协议（例如WSDL、SOAP等）。因此根据所使用的协议不同，tModel有WSDL指纹或SOAP指纹。因此tModel被认为是技术性指纹，每种指纹与一种特定的协议有关。如果说一种tModel可以代表一个“技术性指纹”，我们也可以说tModel能够表示一种“协议”。 <br />分类 <br />分类与类别、名字空间类似，它提供了一种环境，只有在这种环境下，一些数字和名字才有意义。例如， <br />白页 <br />UDDI注册簿中的企业实体列表和根据名字搜索企业的能力。 <br />黄页 <br />黄页将企业实体按企业类别或其他适用的类别分类。 <br />绿页（技术规格） <br />绿页有助于我们理解服务的定义和访问服务的要求，serviceBindings和tModels也有助于这一目标的实现。 <br />JAXR <br />JAXR是在服务注册中使用的一种Java XML API。我们以前曾经讨论过，UDDI中的所有元素都用XML文档进行描述。从某种意义上说，嘦我们能够发送包含有服务描述的XML消息，UDDI注册簿就能够对它进行注册或更新。下面我们讨论在没有工具的情况下如何完成这一任务： <br />1、编写必要的服务描述XML文档。 <br />2、理解SOAP头部，以便能够将XML文件作为一个SOAP附件发送给UDDI注册簿。 <br />3、使用SOAP客户端Java API完成第二步中的任务。 <br />4、通过编程的方式处理SOAP消息。 <br />5、根据UDDI服务的描述，构造消息完成该UDDI服务的任务。 <br />6、对每个消息，完成第2、3步中的操作。 <br />如果使用JAXR，我们可以更好地完成这一任务。因为JAXR允许我们在发送XML消息时无需考虑SOAP头部，而且是一种严格的面向消息的协议。使用JAXR，上面的任务将简化为： <br />1、编写必要的服务描述XML文档。 <br />2、使用JAXM API发送和接收XML消息，JAXR隐藏了SOAP信息。 <br />3、根据UDDI服务构建消息完成该UDDI服务。（例如，向UDDI注册簿注册UDDI服务包含有4次信息交换过程。）这意味着我们仍然需要与XML内容打交道。 <br />使用这种方式，我们只需处理高层次的Java API即可，这些Java API能够产生必需的消息并通过JAXR传输它们。需要指出的一点是，JAXR也用来完成该任务。 <br />下面列出了JAXR的一些目标： <br />·支持业界标准的XML注册功能 <br />·支持成员机构和企业的注册 <br />·支持任意注册内容的存储和提交 <br />·支持XML、非XML注册内容的管理 <br />·支持注册内容间用户定义的结合 <br />·支持用户定义的注册内容的多级分类 <br />·支持基于定义的分类计划的注册内容查询 <br />·支持基于复杂查询的注册内容查询 <br />·支持基于关健词的注册内容查询 <br />·支持Web服务的共享 <br />·支持合作伙伴间商业过程的共享 <br />·支持合作伙伴间计划的共享 <br />·支持合作伙伴间商业文档的共享 <br />·支持合作伙伴间贸易伙伴协议的谈判 <br />·支持计划汇编 <br />·支持异类分布注册 <br />·支持参与各方发布/订阅XML消息 <br />JAXR将不仅仅支持UDDI，还会支持其他的类似注册服务标准（例如ebXML）。 <br /><br /><br />原文地址：<a href="http://www.wyt2008.com/Article/java/web/200603/Article_921.html">http://www.wyt2008.com/Article/java/web/200603/Article_921.html</a><img src ="http://www.blogjava.net/hopeshared/aggbug/58698.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-07-18 10:16 <a href="http://www.blogjava.net/hopeshared/archive/2006/07/18/58698.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：配置XFire</title><link>http://www.blogjava.net/hopeshared/archive/2006/06/04/50321.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Sun, 04 Jun 2006 11:53:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/06/04/50321.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/50321.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/06/04/50321.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/50321.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/50321.html</trackback:ping><description><![CDATA[原文地址：<a href="http://javaresearch.org/article/showarticle.jsp?column=5&amp;thread=50134">http://javaresearch.org/article/showarticle.jsp?column=5&amp;thread=50134</a><br /><br /><br />在进行所有的开发之前，自然是到<a href="http://xfire.codehaus.org/">http://xfire.codehaus.org</a>下载最新的xfire的发布版本，在写这篇文档的时候，xfire最新的版本是xfire-distribution-1.1-beta-1版，从官方网站下载到本地机器后，解压，目录结构如下：<br /><br />xfire-distribution-1.1-beta-1<br /><br />|____api (javadoc文档)<br /><br />|____sample (几个xfire例子)<br /><br />|____lib (xfire所需的jars)<br /><br />|____modules (xfire 模块)<br /><br />|____xfire-all-1.1-beta-1.jar<br /><br />|____几个授权和说明TXT文档<br /><br /> <br /><br />它所提供的例子需要Maven2编译执行，如果你还没有安装Maven，可以到apache网站下载安装。在你阅读的这篇教程的例子中，我将采用ant进行编译，毕竟Ant才是大家所常用的项目管理编译工具。<br /><br /> <br /><br />在你的tomcat的webapps建立一个web应用程序，例如xfire，目录结构如下：<br /><br />       xfire<br /><br />         |____WEB_INF<br /><br />                |____web.xml<br /><br />             |____classes<br /><br />             |____lib<br /><br /> <br /><br />将下载解压的xfire-distribution-1.1-beta-1\lib文件夹下的所有的jar放入的这个lib文件夹下(tomcat/webapps/xfire/WEB-INF/lib)、将xfire-distribution-1.1-beta-1\xfire-all-1.1-beta-1.jar放入到tomcat/webapps/xfire/WEB-INF/lib文件夹下。<br /><br />将xfire-distribution-1.1-beta-1\examples\book\src\webapp\WEB-INF下的web.xml文件复制到tomcat/webapps/xfire/WEB-INF文件夹下。<br /><br />Web.xml的内容如下：<br /><div class="codeStyle"><ol><li><i><font color="#339900">&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;</font></i></li><li></li><li><i><font color="#339900">&lt;!-- START SNIPPET: webxml --&gt;</font></i></li><li></li><li><i><font color="#339900">&lt;!DOCTYPE web-app</font></i></li><li></li><li><i><font color="#339900">    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"</font></i></li><li></li><li><i><font color="#339900">    "http://java.sun.com/dtd/web-app_2_3.dtd"&gt;</font></i></li><li></li><li><i><font color="#339900">   </font></i></li><li></li><li><i><font color="#339900">&lt;web-app&gt;</font></i></li><li></li><li><i><font color="#339900"></font></i></li><li></li><li><i><font color="#339900">  &lt;servlet&gt;</font></i></li><li></li><li><i><font color="#339900">    &lt;servlet-name&gt;XFireServlet&lt;/servlet-name&gt;</font></i></li><li></li><li><i><font color="#339900">    &lt;display-name&gt;XFire Servlet&lt;/display-name&gt;</font></i></li><li></li><li><i><font color="#339900">    &lt;servlet-class&gt;</font></i></li><li></li><li><i><font color="#339900">        org.codehaus.xfire.transport.http.XFireConfigurableServlet</font></i></li><li></li><li><i><font color="#339900">    &lt;/servlet-class&gt;</font></i></li><li></li><li><i><font color="#339900">  &lt;/servlet&gt;</font></i></li><li></li><li><i><font color="#339900"></font></i></li><li></li><li><i><font color="#339900">  &lt;servlet-mapping&gt;</font></i></li><li></li><li><i><font color="#339900">    &lt;servlet-name&gt;XFireServlet&lt;/servlet-name&gt;</font></i></li><li></li><li><i><font color="#339900">    &lt;url-pattern&gt;/servlet/XFireServlet/*&lt;/url-pattern&gt;</font></i></li><li></li><li><i><font color="#339900">  &lt;/servlet-mapping&gt;</font></i></li><li></li><li><i><font color="#339900"></font></i></li><li></li><li><i><font color="#339900">  &lt;servlet-mapping&gt;</font></i></li><li></li><li><i><font color="#339900">    &lt;servlet-name&gt;XFireServlet&lt;/servlet-name&gt;</font></i></li><li></li><li><i><font color="#339900">    &lt;url-pattern&gt;/services/*&lt;/url-pattern&gt;</font></i></li><li></li><li><i><font color="#339900">  &lt;/servlet-mapping&gt;</font></i></li><li></li><li><i><font color="#339900">&lt;/web-app&gt;</font></i></li></ol></div><br />启动tomcat,然后打开浏览器，在浏览器地址栏中输入http://localhost:8080/xfire/services/，如何能够正常显示页面，说明xfire就配置成功了。<br /><br /> <br />这样，我们的XFire就配置完成了。<br /><img src ="http://www.blogjava.net/hopeshared/aggbug/50321.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-06-04 19:53 <a href="http://www.blogjava.net/hopeshared/archive/2006/06/04/50321.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：WSIF应用(翻译的) </title><link>http://www.blogjava.net/hopeshared/archive/2006/05/15/46255.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Mon, 15 May 2006 09:31:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/05/15/46255.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/46255.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/05/15/46255.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/46255.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/46255.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Applying the Web services invocation framework 																										Calling services independent of protocols 																独立于协议的服务调用											...&nbsp;&nbsp;<a href='http://www.blogjava.net/hopeshared/archive/2006/05/15/46255.html'>阅读全文</a><img src ="http://www.blogjava.net/hopeshared/aggbug/46255.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-05-15 17:31 <a href="http://www.blogjava.net/hopeshared/archive/2006/05/15/46255.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：无 SOAP 的 Web 服务</title><link>http://www.blogjava.net/hopeshared/archive/2006/05/15/46251.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Mon, 15 May 2006 09:20:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/05/15/46251.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/46251.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/05/15/46251.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/46251.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/46251.html</trackback:ping><description><![CDATA[即使 SOAP 只是众多访问 Web 服务的可能的绑定之一，它已几乎成为 Web 服务的同义词。这意味着使用 Web 服务的应用程序通常通过绑到 SOAP 的特定实现的 API 来完成工作。本系列文章将描述一个更通用的、独立于 SOAP 的调用 Web 服务的方法，称之为“Web 服务调用框架”（Web Service Invocation Framework（WSIF））。它专门设计来直接调用用“Web 服务描述语言”（Web Services Description Language（WSDL））描述的 Web 服务，隐藏了底层访问协议（比如 SOAP）的复杂性。<br /><br /><p>Web 服务承诺为因特网分布式计算提供基于标准的平台，集中在简易性和灵活性。一种关键的 Web 服务技术是 WSDL，即“Web 服务描述语言”。使用 WSDL，开发者可以以抽象的形式描述 Web 服务，与用在其它分布式计算框架（比如 CORBA）的现有“接口描述语言”（Interface Description Language（IDL））类似。WSDL 也使 Web 服务开发者能够给服务指定具体的绑定。并且这些绑定描述怎样将抽象服务描述映射到特定访问协议。WSDL 的这部分是可扩展的，这就是说任何人都可以提出他们自己的绑定，使之可能通过某个定制的协议访问服务。</p><p>因此，从某种程度来说，使用 Web 服务是一种挑战。对于同样的服务可以有多个绑定。这些绑定中的一些可能适合于一些情形，其它可能适合于另外的情形。绑定本身可以代表抽象服务描述到用来访问服务的任意一种协议的映射。虽然有多种选择使用服务和允许绑定扩展是很有用的，但这给客户机以统一方式查看服务造成了困难。</p><p>我以当前客户机端 API 及其性能的讨论开始这篇文章。我将通过讨论来激发人们对 WSIF，即“Web 服务调用框架”的需要，然后继续进行 WSIF 的概述。</p><p><a name="1"></a><a name="h3919"><span class="atitle2">当前的调用风格及其缺点</span></a><br />用于 Web 服务的 SOAP 绑定是 WSDL 规范的一部分。在大多数编程语言中，该协议有可用的实现和工具，在许多情况下是免费的。这样，它使得开发者能以微乎其微的成本进行用于 Web 服务的独立于平台的开发。</p><p>因此，下述情况是不足为奇的：大多数开发者当想到使用 Web 服务时，在他们头脑中出现的是使用某个 SOAP 客户机 API 来装配一个 SOAP 消息并将它经由网络发送到服务端点。例如，使用 Apache SOAP，客户机将创建和植入一个 Call 对象。它封装了服务端点、要调用的 SOAP 操作的标识、必须发送的参数等等。而这是对 SOAP 而言，它仅限于将其用作调用 Web 服务的一般模型，这是因为下面的原因：</p><ul><li><b>Web 服务不仅仅是 SOAP 服务</b><br />将 Web 服务视为 SOAP 上提供的服务的同义词。这是对 Web 服务狭隘的见解。带有功能方面和访问协议 WSDL 描述的任何一段代码均可以被认为是 Web 服务。WSDL 规范为 Web 服务定义了 SOAP 绑定，但是原则上可能要添加绑定扩展，这样，例如，使用 RMI/IIOP 作为访问协议，EJB 就可以作为 Web 服务来提供。或者您甚至可以想象任意一个 Java 类可以被当作 Web 服务，以本机 Java 调用作为访问协议。就这个更广阔的 Web 服务定义来说，您需要用于服务调用的独立于绑定的机制。 
</li><li><b>将客户机代码绑到一个特殊的协议实现要受到限制</b><br />将客户机代码紧密地绑定到特殊的协议实现的客户机库造成了难以维护的代码。让我们假设您在客户机端有一个用 Apache SOAP v2.1 调用 Web 服务的应用程序。如果您想利用 v2.2 中出现的新的功能和错误修正，您将不得不更新所有的客户机代码，这是一项耗时的任务，将涉及到常见的令人头痛的迁移问题。类似的，如果您想从 Apache SOAP 移到一个不同的 SOAP 实现，这个过程并非无关紧要。所需要的是用于服务调用的独立于协议实现的机制。 
</li><li><b>将新的绑定融入到客户机代码是很困难的。</b><br />WSDL 允许有定义新的绑定的可扩展性元素。这使开发者能够定义绑定，这种绑定允许使用某种定制协议的代码作为 Web 服务。但是，事实上实现起来是很困难的。将不得不设计使用该协议的客户机 API 。应用程序本身可能正是使用 Web 服务的抽象接口，因此将必须编写一些工具来生成启用抽象层的存根。这些又一次是并非无关紧要的而且耗时的任务。所需要的是使绑定能够被更新或新的绑定能够容易地插入的服务调用机制。 
</li><li><b>可以以灵活的方式使用多绑定</b><br />例如，设想您已经成功地部署了一个应用程序，该应用程序使用提供多绑定的 Web 服务。为了使这个示例更具体，假设您有用于服务的 SOAP 绑定和允许您将本地服务实现（一个 Java 类）作为 Web 服务的本地 Java 绑定。显而易见，如果客户机部署在与服务本身相同的环境中，只能使用面向服务的本地 Java 绑定，并且如果情况确实如此，通过直接进行 Java 调用而不是使用 SOAP 绑定与服务进行通信将高效得多。Java 绑定作为一种快捷访问机制。接下来，想要利用多绑定可用性的客户机将必须具有一种能力 — 根据运行时信息对要用的实际绑定进行切换的能力。因此为了利用提供多绑定的 Web 服务，您需要一种服务调用机制，允许您在运行时在可用的服务绑定之间进行切换，而不需要生成或重编译存根。</li></ul><p><a name="2"></a><a name="h8285"><span class="atitle2">介绍 WSIF</span></a><br />“Web 服务调用框架”（WSIF）是为调用 Web 服务提供简单 API 的工具箱，而不管服务怎样提供或由哪里提供。它具有上面讨论中我确定的所有功能：</p><p></p><ul><li>有给任何 Web 服务提供独立于绑定访问的 API。 
</li><li>提供端口类型编译器来生成允许使用抽象服务接口的调用的存根。 
</li><li>允许无存根（完全动态）的 Web 服务调用。 
</li><li>可以在运行时将更新的绑定实现插入到 WSIF。 
</li><li>可以在运行时插入的新的绑定。 
</li><li>允许将绑定选择延后到运行时。</li></ul><p></p><p><a name="h9119"><span class="atitle3">分析 WSIF 的客户机 API</span></a><br />为了进行讨论，我将使用很常见的股票报价程序 — Web 服务的“Hello World”示例。请考虑下面<a href="http://www-900.ibm.com/developerWorks/cn/webservices/ws-wsif/part1/index.shtml#listing1">清单 1</a> 所示的使用 WSDL 的抽象服务描述。</p><p><a name="listing1"></a><b>清单 1：股票报价 Web 服务的 WSDL 描述</b></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #0000ff">&lt;?</span><span style="COLOR: #ff00ff">xml version="1.0" </span><span style="COLOR: #0000ff">?&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">definitions </span><span style="COLOR: #ff0000">targetNamespace</span><span style="COLOR: #0000ff">="http://www.ibm.com/namespace/wsif/samples/stockquote-interface"</span><span style="COLOR: #ff0000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />             xmlns:tns</span><span style="COLOR: #0000ff">="http://www.ibm.com/namespace/wsif/samples/stockquote-interface"</span><span style="COLOR: #ff0000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />             xmlns:xsd</span><span style="COLOR: #0000ff">="http://www.w3.org/1999/XMLSchema"</span><span style="COLOR: #ff0000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />             xmlns</span><span style="COLOR: #0000ff">="http://schemas.xmlsoap.org/wsdl/"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />  </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">message </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="GetQuoteInput"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">part </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="symbol"</span><span style="COLOR: #ff0000"> type</span><span style="COLOR: #0000ff">="xsd:string"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />  </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">message</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />  </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">message </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="GetQuoteOutput"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">part </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="quote"</span><span style="COLOR: #ff0000"> type</span><span style="COLOR: #0000ff">="xsd:float"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />  </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">message</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />  </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">portType </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="StockquotePT"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">operation </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="getQuote"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">input </span><span style="COLOR: #ff0000">message</span><span style="COLOR: #0000ff">="tns:GetQuoteInput"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">output </span><span style="COLOR: #ff0000">message</span><span style="COLOR: #0000ff">="tns:GetQuoteOutput"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">operation</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />  </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">portType</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">definitions</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div><p><br />足够简单：它描述了只带有由一个端口类型提供一个操作的服务。该操作等待一个字符串，被解释为股票的报价机符号，然后返回当前该股票报价，一个浮点值。为了实际使用该服务，您需要某个定义访问机制的绑定以及该绑定的服务端点。<a href="http://www-900.ibm.com/developerWorks/cn/webservices/ws-wsif/part1/index.shtml#listing2">清单 2</a> 展示了该服务的 SOAP 绑定：</p><p><a name="listing2"></a><b>清单 2：股票报价 Web 服务的 SOAP 绑定</b></p><p></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #0000ff">&lt;?</span><span style="COLOR: #ff00ff">xml version="1.0" </span><span style="COLOR: #0000ff">?&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">definitions </span><span style="COLOR: #ff0000">targetNamespace</span><span style="COLOR: #0000ff">="http://www.ibm.com/namespace/wsif/samples/stockquote"</span><span style="COLOR: #ff0000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />             xmlns:tns</span><span style="COLOR: #0000ff">="http://www.ibm.com/namespace/wsif/samples/stockquote"</span><span style="COLOR: #ff0000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />             xmlns:tns-int</span><span style="COLOR: #0000ff">="http://www.ibm.com/namespace/wsif/samples/stockquote-interface"</span><span style="COLOR: #ff0000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />             xmlns:xsd</span><span style="COLOR: #0000ff">="http://www.w3.org/1999/XMLSchema"</span><span style="COLOR: #ff0000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />             xmlns:soap</span><span style="COLOR: #0000ff">="http://schemas.xmlsoap.org/wsdl/soap/"</span><span style="COLOR: #ff0000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />             xmlns:java</span><span style="COLOR: #0000ff">="http://schemas.xmlsoap.org/wsdl/java/"</span><span style="COLOR: #ff0000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />             xmlns</span><span style="COLOR: #0000ff">="http://schemas.xmlsoap.org/wsdl/"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />  </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">import </span><span style="COLOR: #ff0000">namespace</span><span style="COLOR: #0000ff">="http://www.ibm.com/namespace/wsif/samples/stockquote-interface"</span><span style="COLOR: #ff0000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />          location</span><span style="COLOR: #0000ff">="stockquote-interface.wsdl"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />  </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">binding </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="SOAPBinding"</span><span style="COLOR: #ff0000"> type</span><span style="COLOR: #0000ff">="tns-int:StockquotePT"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">soap:binding </span><span style="COLOR: #ff0000">style</span><span style="COLOR: #0000ff">="rpc"</span><span style="COLOR: #ff0000"> transport</span><span style="COLOR: #0000ff">="http://schemas.xmlsoap.org/soap/http"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">operation </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="getQuote"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">soap:operation </span><span style="COLOR: #ff0000">soapAction</span><span style="COLOR: #0000ff">="http://example.com/GetTradePrice"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">input</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />        </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">soap:body </span><span style="COLOR: #ff0000">use</span><span style="COLOR: #0000ff">="encoded"</span><span style="COLOR: #ff0000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                   namespace</span><span style="COLOR: #0000ff">="urn:xmltoday-delayed-quotes"</span><span style="COLOR: #ff0000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                   encodingStyle</span><span style="COLOR: #0000ff">="http://schemas.xmlsoap.org/soap/encoding/"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">input</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">output</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />        </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">soap:body </span><span style="COLOR: #ff0000">use</span><span style="COLOR: #0000ff">="encoded"</span><span style="COLOR: #ff0000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                   namespace</span><span style="COLOR: #0000ff">="urn:xmltoday-delayed-quotes"</span><span style="COLOR: #ff0000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                   encodingStyle</span><span style="COLOR: #0000ff">="http://schemas.xmlsoap.org/soap/encoding/"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">output</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">operation</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />  </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">binding</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />  </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">service </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="StockquoteService"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">documentation</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">Stock quote service</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">documentation</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">port </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="SOAPPort"</span><span style="COLOR: #ff0000"> binding</span><span style="COLOR: #0000ff">="tns:SOAPBinding"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">soap:address </span><span style="COLOR: #ff0000">location</span><span style="COLOR: #0000ff">="http://localhost:8080/soap/servlet/rpcrouter"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">port</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />  </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">service</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">definitions</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div><p>这是一个标准的 SOAP 绑定，使用 RPC 风格和作为传输协议的 HTTP 与服务进行通信。在文档的 port 部分中，我定义了使用 SOAP 绑定可以访问服务的 URI。在<a href="http://www-900.ibm.com/developerWorks/cn/webservices/ws-wsif/part1/index.shtml#listing3">清单 3</a> 中，我将就通过 Apache SOAP 2.2 客户机端 API 和 WSIF 的客户机 API 使用该服务进行对比。</p><p><a name="listing3"></a><strong>清单 3：用于服务访问的 Apache SOAP API 与 WSIF API 对比<br /></strong></p><div align="left">Apache SOAP API</div><p></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Step 1: identify the service </span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000"> Call call </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Call(); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> call.setTargetObjectURI(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">urn:xmltoday-delayed-quotes</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Step 2: identify the operation </span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000"> call.setMethodName(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">getQuote</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> call.setEncodingStyleURI(encodingStyleURI); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Step 3: identify the parameters </span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000"> Vector params </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Vector(); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> params.addElement(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Parameter(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">symbol</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                          String.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">, symbol, </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">));<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> call.setParams(params); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Step 4: execute the operation </span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000"> Response resp </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> call.invoke(url, <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                   </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">http://example.com/GetTradePrice</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Step 5: extract the result or fault </span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(resp.generatedFault()) <br /><img id="Codehighlighter1_624_958_Open_Image" onclick="this.style.display='none'; Codehighlighter1_624_958_Open_Text.style.display='none'; Codehighlighter1_624_958_Closed_Image.style.display='inline'; Codehighlighter1_624_958_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_624_958_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_624_958_Closed_Text.style.display='none'; Codehighlighter1_624_958_Open_Image.style.display='inline'; Codehighlighter1_624_958_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /> </span><span id="Codehighlighter1_624_958_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_624_958_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />   Fault fault </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> resp.getFault(); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />   System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Ouch, the call failed: </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />   System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">  Fault Code   = </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">  <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                      fault.getFaultCode()); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />   System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">  Fault String = </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">  <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                      fault.getFaultString()); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />   </span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> SOAPException(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Execution failed </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> fault); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /> }</span></span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> <br /><img id="Codehighlighter1_969_1072_Open_Image" onclick="this.style.display='none'; Codehighlighter1_969_1072_Open_Text.style.display='none'; Codehighlighter1_969_1072_Closed_Image.style.display='inline'; Codehighlighter1_969_1072_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_969_1072_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_969_1072_Closed_Text.style.display='none'; Codehighlighter1_969_1072_Open_Image.style.display='inline'; Codehighlighter1_969_1072_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /> </span><span id="Codehighlighter1_969_1072_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/images/dot.gif" /></span><span id="Codehighlighter1_969_1072_Open_Text"><span style="COLOR: #000000">{ <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />   Parameter result </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> resp.getReturnValue(); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />   </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> ((Float) result.getValue()).floatValue(); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /> }</span></span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div><div align="left"><br />WSIF API</div><p></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Step 1: identify the service </span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000"> Definition def </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> WSIFUtils.readWSDL(</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">,wsdlLocation);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Step 2: identify the operation (choose an <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> appropriate service port) </span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000"> WSIFDynamicPortFactory portFactory </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />        </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">  WSIFDynamicPortFactory(def, </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">, </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Get default port </span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000"> WSIFPort port </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> portFactory.getPort(); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> The user can also explicitly select a port  <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> to use. <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> WSIFPort port =  <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">             portFactory.getPort("SOAPPort"); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Step 3: identify the parameters <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Prepare the input message </span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000"> WSIFMessage input </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> port.createInputMessage(); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> input.setPart(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">symbol</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,  <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />               </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> WSIFJavaPart(String.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">, symbol));<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Prepare a placeholder for the output value </span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000"> WSIFMessage output </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> port.createOutputMessage(); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Step 4: execute the operation </span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000"> port.executeRequestResponseOperation(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">getQuote</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                             input, output, </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Step 5: extract the result or fault </span><span style="COLOR: #008000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000"> WSIFPart part </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> output.getPart(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">quote</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> ((Float)part.getJavaValue()).floatValue();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div><p><br /></p><p>正如您可以看到的，WSIF 的 API 由以 WSDL 编写的抽象服务描述驱动；它完全从实际使用的绑定中分离出来。该调用 API 是面向 WSDL 的，并且使用它更自然，因为它使用 WSDL 术语引用消息部件（message part）、操作等等。当您阅读一个 WSDL 描述，出于直觉会想到选用支持所需端口类型的端口，然后通过提供必需抽象输入消息（由必要部件组成）调用操作（不用担心怎样将消息映射到特定的绑定协议）；WSIF API 就是这样设计的。</p><p>常用的 API，比如上面所示的 Apache SOAP API 采用了以特殊协议为中心的概念，比如在使用 SOAP 的情况下，目标 URI 和编码风格。这是不可避免的，因为 API 不是普遍适用于 WSDL，而是为特殊的协议设计。</p><p><a name="2"></a><a name="h17008"><span class="atitle2">两种使用 WSIF 的调用模型</span></a><br />WSIF 允许 Web 服务以两种方式调用。一种是无存根的动态调用，它要求直接使用 WSIF API；另一种是通过生成允许应用程序使用 Java 接口（直接对应于 WSDL 端口类型）和隐藏了 WSIF API 的存根的调用。</p><p><a name="h17446"><span class="atitle3">无存根（动态的）调用</span></a><br />访问 Web 服务所需的所有信息 — 抽象接口、绑定和服务端点可以通过 WSDL 得到。如果您仔细查看上面的客户机 API 示例，您将会注意到唯一由用户提供的信息是用于服务的 WSDL 文件位置和所需要的股票报价符号。很明显接下来是用 WSFL API 在运行时装入这个服务和进行该调用。</p><p>WSIF 分发包包含了演示怎样执行 WSDL 的任意一个操作的 DynamicInvoker。它以 WSDL 文件的 URI 和所需的操作参数作为命令行参数（在最初的实现中只接受简单的类型，如字符串），并且直接使用 WSIF API 完成工作。其用来调用股票报价服务的示例如<a href="http://www-900.ibm.com/developerWorks/cn/webservices/ws-wsif/part1/index.shtml#listing4">清单 4</a> 所示；您可以在包含 <a href="http://www.alphaworks.ibm.com/tech/wsif">WSIF 分发包</a>的文档中查找详细信息。</p><p>因为这类调用不会导致生成存根类，并且不需要单独的编译周期，所以它很方便。</p><p><a name="listing4"></a><b>清单 4：使用 DynamicInvoker 访问股票报价服务</b></p><p><a name="h19269"><span class="atitle3"><font color="#336699"></font></span></a></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">java clients.DynamicInvoker http://services.xmethods.net/soap/urn:<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    xmethods-delayed-quotes.wsdl getQuote IBM<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />Reading WSDL document from 'http://services.xmethods.net/soap/urn:<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    xmethods-delayed-quotes.wsdl'<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />Preparing WSIF dynamic invocation<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />Executing operation getQuote<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />Result:<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />Result=108.8<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />Done!<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div><p>使用存根的调用<br />在应用程序需要更抽象的服务视图和不希望处理 WSIF 客户机 API 的情况下，无存根调用不适用。WSIF 提供一个端口编译器，如果给定一个 WSDL，与所用到的复杂类型的 Java 等价物（以 JavaBean 的形式）一起，端口编译器将为每一个端口类型生成一个客户机存根。使用生成存根的应用程序可以利用抽象服务接口，并且这样与协议和 WSIF 客户机 API 分离。对于实际服务调用，这些存根使用缺省端口。通过由 WSIF 的端口类型编译器生成的存根使用股票报价服务的示例如<a href="http://www-900.ibm.com/developerWorks/cn/webservices/ws-wsif/part1/index.shtml#listing5">清单 5</a> 所示。</p><p><a name="listing5"></a><b>清单 5：使用生成存根的 WSIF 访问股票报价服务。</b></p><p></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">StockquotePT service </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> StockquotePTStub(WSIFUtils.readWSDL(</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">, wsdlLocation), <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />    </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">, </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">float</span><span style="COLOR: #000000"> quote </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> service.getQuote(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">IBM</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />System.err.println (</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">&gt;&gt; Received quote: </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">quote);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div><p>值得注意的是存根驻留在某些受管环境（如应用程序服务器）的情况，它们能够被定制；例如，可以改变负责返回恰当端口的工厂来定制端口选择算法，或者可以改变用于调用自身的实际端口。</p><p>在这篇文章中，我略述了对 WSIF 的需要，分析其通过高级 API 进行独立于绑定的服务访问的主要特征以及生成可定制的存根（通过其抽象接口使用服务）的端口类型编译器的可用性。直接通过 SOAP 客户机 API 和使用 WSIF API 进行服务访问之间的<a href="http://www-900.ibm.com/developerWorks/cn/webservices/ws-wsif/part1/index.shtml#listing3">对比</a>展示了 WSIF（由服务的 WSDL 描述驱动）怎样将 Web 服务调用的全部问题从以绑定为中心的观点转移到更抽象的级别。这是 WSIF 的设计原则之一，使服务绑定能被看作是根据特殊协议进行调用所需的代码片断，可以在任何时候插入它们。</p><p>在接下来的文章，我将分析 WSIF 的体系结构，看一看它怎样允许新的或更新的绑定实现被插入，它怎样使定制的类型系统用于 Web 服务以及怎样使运行时环境使用定制的探索性方法在多端口之间进行选择。</p><p><a name="resources"><span class="atitle2">参考资料</span></a></p><ul><li>请参加关于这篇文章的<a href="javascript:void%20forumWindow()"><font color="#336699">讨论论坛</font></a>。 
</li><li>请下载 <a href="http://www-900.ibm.com/developerWorks/cn/cgi-bin/click.cgi?url=http://www.alphaworks.ibm.com/tech/wsif"><font color="#336699">alphaworks 上的 WSIF 分发包</font></a>，并且试验比较简单的样本。它将给您一个由 WSIF 支持的不同调用风格的第一手示例以及它优于特定协议客户机 API 的优势。 
</li><li>重温 <a href="http://www.w3.org/TR/WSDL.html"><font color="#336699">WSDL 规范</font></a>，看一看允许哪一种扩展；如果用来为访问 Web 服务定义 SOAP 绑定，您也可以学习 WSDL 的扩展机制。 
</li><li>重温 <a href="http://www.w3.org/TR/SOAP"><font color="#336699">SOAP 规范</font></a>本身。 
</li><li>如果以前您没有对 Web 服务编过程，<a href="http://www-900.ibm.com/developerWorks/cn/cgi-bin/click.cgi?url=http://www.alphaworks.ibm.com/tech/webservicestoolkit"><font color="#336699">Web Services Toolkit</font></a> 是很好的起点。 
</li><li>请查看 <a href="http://www-900.ibm.com/developerWorks/cn/cgi-bin/click.cgi?url=http://oss.software.ibm.com/developerWorks/projects/wsdl4j"><font color="#336699">WSDL4J</font></a>，一个可扩展的 WSDL 分析框架，WSIF 在此基础上进行构建。</li></ul><p></p><p><a name="author1"><span class="atitle2">关于作者</span><br />Nirmal K. Mukhi 是 IBM 的 T J Watson Research Lab 的副研究员，自 2000 年 11 月，他一直在从事各种 Web 服务技术的研究。他还对 AI、创造性写作以及过时的计算机游戏感兴趣。您可以通过 <a href="mailto:nmukhi@us.ibm.com">nmukhi@us.ibm.com</a> 与 Nirmal 联系。</a></p><br /><br /><br />转载自：<a href="http://www.itepub.net/page/article/htmldata/2004_10/17/76/article_3575_1.html">http://www.itepub.net/page/article/htmldata/2004_10/17/76/article_3575_1.html</a><br /><img src ="http://www.blogjava.net/hopeshared/aggbug/46251.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-05-15 17:20 <a href="http://www.blogjava.net/hopeshared/archive/2006/05/15/46251.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：OWL本体设计模式(1)(2)(3)(4): N-元关系的表示; QCR的表示;避免使用oneOf；开放世界语义对本体构建的影响</title><link>http://www.blogjava.net/hopeshared/archive/2006/05/10/45368.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Wed, 10 May 2006 02:31:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/05/10/45368.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/45368.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/05/10/45368.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/45368.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/45368.html</trackback:ping><description><![CDATA[我们都知道，RDF只表示二元关系，但在实际应用中，多元关系非常常见，如：小红借给小明语文书，是个三元关系： borrow(小红，语文书，小明); 再如，小明的身高是170cm.也是个三元关系 length(小明，170, cm). 推广来说，n元关系如何在RDF和OWL中表示呢？
<p>我们假设三元组为(a,b,c). a,b.c 都是资源或Literal</p><p>1． 方法一<br />如果三元组中a是老大，即有个资源的地位是支配性的，如:小明的身高是170cm.<br />表示方法为 把老大提出来，再把三元关系分解为3个二元关系：<br />  R1(a, a’) ， R2（a’,b）,  R3（a’,c）  // R1(a, a’) 用RDF三元组表示为 （a , R1 , a’）<br />例如：小明的例子可以表示为<br />length(小明，length_obj_1);  //小明是老大, length_obj_1 是一个身高对象 <br /><i>value</i>(length_obj_1，170);     //值<br />unit(length_obj_1，cm);      //单位<br />2． 方法二<br />如果三元组中没有明显的老大，如: 小红借给小明语文书.<br />表示方法为提出一个对象，每个元素都和这个对象有关系：<br />R1(g, a) ， R2（g,b）,  R3（g, c）<br />例如：小红借书的例子可以表示为<br />rdf:type (borrow_obj_1,  BorrowRelation); // BorrowRelation 是一个表示借书关系的类<br />borrow_owner((borrow_obj_1,小红)； <br />borrow_agent((borrow_obj_1,小明)； //借书的人<br />borrow_book((borrow_obj_1, 语文书)；</p><p><br />3． 结论<br />1) n-元关系有2exp(n-2) 种表示方法： 二元关系一种表示法，三元关系有如上二种表示法，由数学归纳法得证。<br />2) 如果用RDF对复杂系统建模，有必要引入一个中间的抽象层，用以表示N元关系，还有named graph, context 等。如引入rdfe:relation(a,b,c,d,….)表示n元关系 <br />3) n-关系的表示对RDF数据的查询和存储优化很有价值，因为n-关系往往对应了数据库中的表。</p><p><br />注：大部分摘译自： <br /><a class="contentlink" href="http://www.w3.org/2001/sw/BestPractices/OEP/n-aryRelations-20040623/" target="_blank"><font color="#000050">http://www.w3.org/2001/sw/BestPractices/OEP/n-aryRelations-20040623/</font></a></p><p>更为详细的信息也参考它。<br /><br />原文地址：<a href="http://bbs.w3china.org/dispbbs.asp?boardID=2&amp;ID=8416">http://bbs.w3china.org/dispbbs.asp?boardID=2&amp;ID=8416</a></p><img src ="http://www.blogjava.net/hopeshared/aggbug/45368.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-05-10 10:31 <a href="http://www.blogjava.net/hopeshared/archive/2006/05/10/45368.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：Web Service 的异步调用</title><link>http://www.blogjava.net/hopeshared/archive/2006/05/07/44876.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Sun, 07 May 2006 08:28:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/05/07/44876.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/44876.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/05/07/44876.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/44876.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/44876.html</trackback:ping><description><![CDATA[
		<p> </p>在网络中为了保证数据的实时性，需要对数据进行异步操作。Java Web Service和J2EE中的异步操作通过java消息机制来完成，消息机制是非常完善的技术了。而Microsoft的Web Service的异步功能是怎样完成的呢？怎样才能达到java的境地呢？当然，Microsoft有自己的一套。
<p class="a14">众所周知，Web Service是靠SOAP协议进行数据传输的。而SOAP是基于XML技术之上的。SOAP协议是连接客户和服务器的桥梁。而SOAP协议本身没有异步功能，需要在客户端实现异步调用。我们以一个简单的Web Service的例子来说明这一点。</p><p class="a14">一、MathService.asmx</p><p class="a14">&lt;%@ WebService Language="C#" Class="MathService" %&gt;<br /></p><p class="a14">using System;</p><p class="a14">using System.Web.Services;</p><p class="a14"></p><p class="a14">[WebService]</p><p class="a14">public class MathService : WebService {</p><p class="a14"></p><p class="a14">[WebMethod]</p><p class="a14">public float Add(float a, float b)</p><p class="a14">{</p><p class="a14">return a + b;</p><p class="a14">}</p><p class="a14"></p><p class="a14"></p><p class="a14">[WebMethod]</p><p class="a14">public double Subtract(double a, double b)</p><p class="a14">{</p><p class="a14">return a - b;</p><p class="a14">}</p><p class="a14"></p><p class="a14">[WebMethod]</p><p class="a14">public float Multiply(float a, float b)</p><p class="a14">{</p><p class="a14">return a * b;</p><p class="a14">}</p><p class="a14"></p><p class="a14">[WebMethod]</p><p class="a14">public float Divide(float a, float b)</p><p class="a14">{</p><p class="a14">if (b==0) return -1;</p><p class="a14">return a / b;</p><p class="a14">}</p><p class="a14">}</p><p class="a14">这是个实现了加，减，乘，除的Web Service，任何客户端程序都可以调用它。下面我们用wsdl（微软公司提供）工具产生一个MathService.asmx 的客户代理程序：wsdl /n:MyMath　http://localhost/mathservice.asmx (假设MathService.asmx放在IIS服务器的根目录) ，产生一个MathService.cs代理程序，默认是SOAP协议。</p><p class="a14">二、MathService.cs:</p><p class="a14"></p><p class="a14">namespace MyMath{</p><p class="a14">using System.Diagnostics;</p><p class="a14">using System.Xml.Serialization;</p><p class="a14">using System;</p><p class="a14">using System.Web.Services.Protocols;</p><p class="a14">using System.ComponentModel;</p><p class="a14">using System.Web.Services;</p><p class="a14"></p><p class="a14"></p><p class="a14">[System.Diagnostics.DebuggerStepThroughAttribute()]</p><p class="a14">[System.ComponentModel.DesignerCategoryAttribute("code")]</p><p class="a14">[System.Web.Services.WebServiceBindingAttribute(Name="MathServiceSoap", Namespace="http://tempuri.org/")]</p><p class="a14">public class MathService : System.Web.Services.Protocols.SoapHttpClientProtocol {</p><p class="a14"></p><p class="a14">public MathService() {</p><p class="a14">this.Url = "http://localhost/mathservice.asmx";</p><p class="a14">}</p><p class="a14"></p><p class="a14">[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Add", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]</p><p class="a14">public System.Single Add(System.Single a, System.Single b) {</p><p class="a14">object[] results = this.Invoke("Add", new object[] {</p><p class="a14">a,</p><p class="a14">b});</p><p class="a14">return ((System.Single)(results[0]));</p><p class="a14">}</p><p class="a14"></p><p class="a14">public System.IAsyncResult BeginAdd(System.Single a, System.Single b, System.AsyncCallback callback, object asyncState) {</p><p class="a14">return this.BeginInvoke("Add", new object[] {</p><p class="a14">a,</p><p class="a14">b}, callback, asyncState);</p><p class="a14">}</p><p class="a14"></p><p class="a14">/// &lt;remarks/&gt;</p><p class="a14">public System.Single EndAdd(System.IAsyncResult asyncResult) {</p><p class="a14">object[] results = this.EndInvoke(asyncResult);</p><p class="a14">return ((System.Single)(results[0]));</p><p class="a14">}</p><p class="a14"></p><p class="a14">/// &lt;remarks/&gt;</p><p class="a14">[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Subtract", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]</p><p class="a14">public System.Double Subtract(System.Double a, System.Double b) {</p><p class="a14">object[] results = this.Invoke("Subtract", new object[] {</p><p class="a14">a,</p><p class="a14">b});</p><p class="a14">return ((System.Double)(results[0]));</p><p class="a14">}</p><p class="a14"></p><p class="a14">/// &lt;remarks/&gt;</p><p class="a14">public System.IAsyncResult BeginSubtract(System.Double a, System.Double b, System.AsyncCallback callback, object asyncState) {</p><p class="a14">return this.BeginInvoke("Subtract", new object[] {</p><p class="a14">a,</p><p class="a14">b}, callback, asyncState);</p><p class="a14">}</p><p class="a14"></p><p class="a14">/// &lt;remarks/&gt;</p><p class="a14">public System.Double EndSubtract(System.IAsyncResult asyncResult) {</p><p class="a14">object[] results = this.EndInvoke(asyncResult);</p><p class="a14">return ((System.Double)(results[0]));</p><p class="a14">}</p><p class="a14"></p><p class="a14">/// &lt;remarks/&gt;</p><p class="a14">[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Multiply", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]</p><p class="a14">public System.Single Multiply(System.Single a, System.Single b) {</p><p class="a14">object[] results = this.Invoke("Multiply", new object[] {</p><p class="a14">a,</p><p class="a14">b});</p><p class="a14">return ((System.Single)(results[0]));</p><p class="a14">}</p><p class="a14"></p><p class="a14">/// &lt;remarks/&gt;</p><p class="a14">public System.IAsyncResult BeginMultiply(System.Single a, System.Single b, System.AsyncCallback callback, object asyncState) {</p><p class="a14">return this.BeginInvoke("Multiply", new object[] {</p><p class="a14">a,</p><p class="a14">b}, callback, asyncState);</p><p class="a14">}</p><p class="a14"></p><p class="a14">/// &lt;remarks/&gt;</p><p class="a14">public System.Single EndMultiply(System.IAsyncResult asyncResult) {</p><p class="a14">object[] results = this.EndInvoke(asyncResult);</p><p class="a14">return ((System.Single)(results[0]));</p><p class="a14">}</p><p class="a14"></p><p class="a14">/// &lt;remarks/&gt;</p><p class="a14">[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Divide", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]</p><p class="a14">public System.Single Divide(System.Single a, System.Single b) {</p><p class="a14">object[] results = this.Invoke("Divide", new object[] {</p><p class="a14">a,</p><p class="a14">b});</p><p class="a14">return ((System.Single)(results[0]));</p><p class="a14">}</p><p class="a14"></p><p class="a14">/// &lt;remarks/&gt;</p><p class="a14">public System.IAsyncResult BeginDivide(System.Single a, System.Single b, System.AsyncCallback callback, object asyncState) {</p><p class="a14">return this.BeginInvoke("Divide", new object[] {</p><p class="a14">a,</p><p class="a14">b}, callback, asyncState);</p><p class="a14">}</p><p class="a14"></p><p class="a14">/// &lt;remarks/&gt;</p><p class="a14">public System.Single EndDivide(System.IAsyncResult asyncResult) {</p><p class="a14">object[] results = this.EndInvoke(asyncResult);</p><p class="a14">return ((System.Single)(results[0]));</p><p class="a14">}</p><p class="a14">}</p><p class="a14">}</p><p class="a14">之后我们用csc /t:library MathService.cs编译并产生一个MathService.dll.</p><p class="a14">现在我们可以写任何的客户程序去调用服务器上的MathService.asmx。</p><p class="a14">如：WinForm, C#,ASPX等。</p><p class="a14">下面我们写一个test.cs去测试异步调用：</p><p class="a14"></p><p class="a14">三、test.cs:</p><p class="a14">using System;</p><p class="a14"></p><p class="a14">public class test{</p><p class="a14">public static void Main(){</p><p class="a14">MyMath.MathService math = new MyMath.MathService();</p><p class="a14">IAsyncResult result1 = math.BeginAdd(10,20,null,null);</p><p class="a14">Object result=math.EndAdd(result1);</p><p class="a14">Console.WriteLine("result =========="+result);</p><p class="a14">}</p><p class="a14">}</p><p class="a14">我们看到它是先调用代理MathService.cs中的BeginAdd方法，然后状态信息保存在IasyncResult中，直到调用了EndAdd方法才返回调用的确切值。本例是远端调用MathService.asmx中的Add方法。</p><p class="a14">那Microsoft到底怎样实现客户端的异步呢？设计模式又是怎样的呢？</p><p class="a14">异步模式所提供的革新之一就是调用方确定特定调用是否应是异步的。　　对于被调用的对象，没有必要执行附加的编程来用于支持其客户端的异步行为；在该模式中异步委托提供此功能。公共语言运行库处理调用方和被调用的对象视图之间的差异。被调用的对象可以选择显式支持异步行为，这或者是因为它可以比一般结构更为有效地实现异步行为，或者是因为它想只支持其调用方的异步行为。但是，建议这种被调用的对象遵循公开异步操作的异步设计模式。</p><p class="a14">类型安全是异步模式的另一项革新。尤其对于异步委托，针对 .NET 框架和公共语言运行库的语言编译器可令映射到规则 Invoke 方法的开始和结束操作（例如，BeginInvoke 和 EndInvoke）的方法签名是类型安全的。这是十分重要的，因为编译器为异步委托将同步调用拆分成开始和结束操作，使其能够只传递有效参数。</p><p class="a14">在此模式中所蕴含的基本想法如下所示： </p><p class="a14">1．调用方确定特定调用是否应是异步的。 </p><p class="a14">2. 对于被调用的对象，没有必要由其客户端执行附加的编程来用于支持异步行为。公共语言运行库结构应该能够处理调用方和被调用的对象视图之间的差异。 </p><p class="a14">3. 被调用的对象可以选择显式支持异步行为，这或者是因为它可以比一般结构更为有效地实现异步行为，或者是因为它想只支持其调用方的异步行为。但是，建议这种被调用的对象遵循公开异步操作的异步设计模式。 </p><p class="a14">4. 编译器为 BeginInvoke 和 EndInvoke 以及异步委托生成类型安全方法签名。 </p><p class="a14">5. .NET 框架提供支持异步编程模型所需的服务。此类服务的部分列表示例是：</p><p class="a14">(1)同步基元，例如监视器和阅读器编写器锁定。</p><p class="a14">(2)线程和线程池。</p><p class="a14">(3)同步构造，例如支持等候对象的容器。</p><p class="a14">(4)向基础结构片（例如 IMessage 对象和线程池）公开。 </p><p class="a14">该模式将一个同步调用拆分成各构成部分：开始操作、结束操作和结果对象。考虑以下示例，在其中可能要用大量时间来完成 Factorize 方法。</p><p class="a14">public class PrimeFactorizer</p><p class="a14">{</p><p class="a14">public bool Factorize(int factorizableNum, ref int primefactor1, ref int primefactor2)</p><p class="a14">{</p><p class="a14">// Determine whether factorizableNum is prime.</p><p class="a14">// If is prime, return true. Otherwise, return false.</p><p class="a14">// If is prime, place factors in primefactor1 and primefactor2.</p><p class="a14">}</p><p class="a14">}</p><p class="a14">如果遵循异步模式，则类库编写器添加 BeginFactorize 和 EndFactorize方法，这两个方法将同步操作拆分成两个异步操作：</p><p class="a14">public class PrimeFactorizer</p><p class="a14">{</p><p class="a14">public bool Factorize(</p><p class="a14">　　　　int factorizableNum, </p><p class="a14">　　　　ref int primefactor1, </p><p class="a14">　　　　ref int primefactor2)</p><p class="a14">{</p><p class="a14">// Determine whether factorizableNum is prime.</p><p class="a14">// if is prime, return true; otherwise return false.</p><p class="a14">// if is prime palce factors in primefactor1 and primefactor2</p><p class="a14">}</p><p class="a14"></p><p class="a14">public IAsyncResult BeginFactorize(</p><p class="a14">　　　int factorizableNum, </p><p class="a14">　　　ref int primefactor1, </p><p class="a14">　　　ref int primefactor2, </p><p class="a14">　　　AsyncCallback callback, </p><p class="a14">　　　Object state)</p><p class="a14">{</p><p class="a14">　// Begin the factorizing asynchronously, and return a result object,</p><p class="a14">}</p><p class="a14"></p><p class="a14">public bool EndFactorize(</p><p class="a14">　　　ref int primefactor1, </p><p class="a14">　　　ref int primefactor2,</p><p class="a14">　　　IAsyncResult asyncResult</p><p class="a14">　)</p><p class="a14">{</p><p class="a14">// End (or complete) the factorizing, and </p><p class="a14">// return the results, </p><p class="a14">// and obtain the prime factors.</p><p class="a14">}</p><p class="a14">}</p><p class="a14">服务器将异步操作拆分成两个逻辑部分：采用来自客户端的输入并调用异步操作的部分，向客户端提供异步操作结果的部分。</p><p class="a14">除了异步操作所需的输入外，第一部分还采用在完成异步操作时后要被调用的 AsyncCallback 委托。第一部分返回一个可等待的对象，该对象实现客户端使用的 IAsyncResult 接口来确定异步操作的状态。</p><p class="a14">服务器还利用它返回到客户端的可等待的对象来维护与异步操作关联的任何状态。通过提供可等待的对象，客户端使用第二部分获取异步操作的结果。</p><p class="a14">可用于客户端来启动异步操作的选项有： </p><p class="a14">在开始异步调用时提供回调委托。 </p><p class="a14">　public class Driver1</p><p class="a14">　　　{</p><p class="a14">　　　　 public PrimeFactorizer primeFactorizer;</p><p class="a14"></p><p class="a14">　　　　 public void Results(IAsyncResult asyncResult)</p><p class="a14">　　　 {</p><p class="a14">　　　　　int primefactor1=0; </p><p class="a14">　　　　　 int primefactor2=0;</p><p class="a14"></p><p class="a14">　　　　　 bool prime = primeFactorizer.EndFactorize(</p><p class="a14">　　　　　　　　　ref primefactor1, </p><p class="a14">　　　　　　　　　ref primefactor2,</p><p class="a14">　　　　　　　　　asyncResult);</p><p class="a14">　　　　}</p><p class="a14"></p><p class="a14">　　　　 public void Work()</p><p class="a14">　　　　 {</p><p class="a14">　　　　　 int factorizableNum=1000589023, </p><p class="a14">　　　　　 int primefactor1=0; </p><p class="a14">　　　　　 int primefactor2=0;</p><p class="a14">　　　　　 Object state = new Object();</p><p class="a14"></p><p class="a14">　　　　　 primeFactorizer = new PrimeFactorizer();</p><p class="a14">　　　　　 AsyncCallback callback = new Callback(this.Results);</p><p class="a14">　　　　　 IAsyncResult asyncResult = 　　　　　　　　　　　　　　　　　　　　　primeFactorizer.BeginFactorize(</p><p class="a14">　　　　　　　factorizableNum, </p><p class="a14">　　　　　　　ref primefactor1, </p><p class="a14">　　　　　　　ref primefactor2, </p><p class="a14">　　　　　　　callback, </p><p class="a14">　　　　　　　state);</p><p class="a14">　　　　}　</p><p class="a14">｝</p><p class="a14"></p><p class="a14">在开始异步调用时不提供回调委托。</p><p class="a14">public class Driver2</p><p class="a14">{</p><p class="a14">public static void Work()</p><p class="a14">{</p><p class="a14">int factorizableNum=1000589023, </p><p class="a14">int primefactor1=0; </p><p class="a14">int primefactor2=0;</p><p class="a14">Object state = new Object();</p><p class="a14"></p><p class="a14">PrimeFactorizer primeFactorizer = new PrimeFactorizer();</p><p class="a14">AsyncCallback callback = new Callback(this.Results);</p><p class="a14">IAsyncResult asyncResult = primeFactorizer.BeginFactorize(</p><p class="a14">factorizableNum, </p><p class="a14">ref primefactor1, </p><p class="a14">ref primefactor2, </p><p class="a14">callback, </p><p class="a14">state);</p><p class="a14"></p><p class="a14">bool prime = primeFactorizer.EndFactorize(</p><p class="a14">ref primefactor1, </p><p class="a14">ref primefactor2,</p><p class="a14">asyncResult);</p><p class="a14">}</p><p class="a14">}</p><p class="a14">我们以.Net的一个例子来说明这一点：</p><p class="a14">AsyncDelegate2.cs</p><p class="a14">using System;</p><p class="a14">using System.Threading;</p><p class="a14">using System.Runtime.Remoting;</p><p class="a14">using System.Runtime.Remoting.Messaging;</p><p class="a14"></p><p class="a14">public class Wak</p><p class="a14">{</p><p class="a14">public int Pat(int i)</p><p class="a14">{</p><p class="a14">Console.WriteLine("Hash: {0} Wak Pat", Thread.CurrentThread.GetHashCode());</p><p class="a14">return i*2;</p><p class="a14">}</p><p class="a14">};</p><p class="a14">public delegate int WakPatDelegate(int i);// 异步调用的委派.</p><p class="a14">public class Simple </p><p class="a14">{</p><p class="a14">public static void SomeMethod(IAsyncResult ar)</p><p class="a14">{</p><p class="a14">// Obtain value from AsyncState object</p><p class="a14">int value = Convert.ToInt32(ar.AsyncState);</p><p class="a14"></p><p class="a14">// Obtain results via EndInvoke</p><p class="a14">int result = ((WakPatDelegate)((AsyncResult)ar).AsyncDelegate ).EndInvoke(ar);</p><p class="a14"></p><p class="a14">Console.WriteLine("Simple.SomeMethod (AsyncCallback): Result of {0} in Wak.Pak is {1} ",value, result);</p><p class="a14">}</p><p class="a14"></p><p class="a14">public static void Main(String[] args)</p><p class="a14">{</p><p class="a14">Console.WriteLine("Thread Simple Context Sample");</p><p class="a14">Console.WriteLine("");</p><p class="a14"></p><p class="a14">Console.WriteLine("Make an instance of a context-bound type Wak");</p><p class="a14">Wak oWak = new Wak();</p><p class="a14"></p><p class="a14">int value=0;</p><p class="a14">int result=0;</p><p class="a14"></p><p class="a14">Console.WriteLine("Make a sync call on the object");</p><p class="a14">value = 10;</p><p class="a14">result = oWak.Pat(value);</p><p class="a14">Console.WriteLine("Result of {0} in Wak.Pak is {1} ",value, result);</p><p class="a14"></p><p class="a14">Console.WriteLine("Make single Async call on Context-bound object");</p><p class="a14">WakPatDelegate wpD1 = new WakPatDelegate(oWak.Pat);</p><p class="a14">value = 20;</p><p class="a14">IAsyncResult ar1 = wpD1.BeginInvoke(value,null,null);</p><p class="a14"></p><p class="a14">ar1.AsyncWaitHandle.WaitOne();</p><p class="a14">result = wpD1.EndInvoke(ar1);</p><p class="a14">Console.WriteLine("Result of {0} in Wak.Pak is {1} ",value, result);</p><p class="a14"></p><p class="a14">Console.WriteLine("Make single Async call on Context-bound object - use AsyncCallback and StateObject");</p><p class="a14">WakPatDelegate wpD2 = new WakPatDelegate(oWak.Pat);</p><p class="a14">value = 30;</p><p class="a14">IAsyncResult ar2 = wpD2.BeginInvoke(</p><p class="a14">value,</p><p class="a14">new AsyncCallback(Simple.SomeMethod),</p><p class="a14">value</p><p class="a14">);</p><p class="a14">Console.WriteLine("Make multiple Async calls on Context-bound object");</p><p class="a14">int asyncCalls = 5;</p><p class="a14">IAsyncResult[] ars = new IAsyncResult[asyncCalls];</p><p class="a14">WaitHandle[] whs = new WaitHandle[asyncCalls];</p><p class="a14">int[] values = new int[asyncCalls];</p><p class="a14">WakPatDelegate wpD3 = new WakPatDelegate(oWak.Pat);</p><p class="a14"></p><p class="a14">for (int i=0; i &lt; asyncCalls; i++)</p><p class="a14">{</p><p class="a14">values[i] = i;</p><p class="a14">ars[i] = wpD3.BeginInvoke(values[i],null,null);</p><p class="a14">whs[i] = ars[i].AsyncWaitHandle;</p><p class="a14">}</p><p class="a14"></p><p class="a14">WaitHandle.WaitAll(whs,1000, false);</p><p class="a14"></p><p class="a14">for (int i=0; i &lt; asyncCalls; i++)</p><p class="a14">{</p><p class="a14">result = wpD3.EndInvoke(ars[i]);</p><p class="a14">Console.WriteLine("Result of {0} in Wak.Pak is {1} ",values[i], result);</p><p class="a14">}</p><p class="a14">Console.WriteLine("");</p><p class="a14">Console.WriteLine("Done");</p><p class="a14">}</p><p class="a14">}</p><p class="a14">　　　　</p><p class="a14">如果异步调用成功，将显示：</p><p class="a14">Thread Simple Context Sample</p><p class="a14"></p><p class="a14">Make an instance of a context-bound type Wak</p><p class="a14">Make a sync call on the object</p><p class="a14">Hash: 3 Wak Pat</p><p class="a14">Result of 10 in Wak.Pak is 20</p><p class="a14">Make single Async call on Context-bound object</p><p class="a14">Hash: 16 Wak Pat</p><p class="a14">Result of 20 in Wak.Pak is 40</p><p class="a14">Make single Async call on Context-bound object - use AsyncCallback and StateObje</p><p class="a14">ct</p><p class="a14">Hash: 16 Wak Pat</p><p class="a14">Make multiple Async calls on Context-bound object</p><p class="a14">Simple.SomeMethod (AsyncCallback): Result of 30 in Wak.Pak is 60</p><p class="a14">Hash: 16 Wak Pat</p><p class="a14">Hash: 16 Wak Pat</p><p class="a14">Hash: 16 Wak Pat</p><p class="a14">Hash: 16 Wak Pat</p><p class="a14">Hash: 16 Wak Pat</p><p class="a14">Result of 0 in Wak.Pak is 0　</p><p class="a14">Result of 1 in Wak.Pak is 2</p><p class="a14">Result of 2 in Wak.Pak is 4</p><p class="a14">Result of 3 in Wak.Pak is 6</p><p class="a14">Result of 4 in Wak.Pak is 8</p><p class="a14"></p><p class="a14">Done<br /><br />原文地址：<a href="http://www.ccw.com.cn/htm/center/prog/02_8_23_6.asp">http://www.ccw.com.cn/htm/center/prog/02_8_23_6.asp</a></p><img src ="http://www.blogjava.net/hopeshared/aggbug/44876.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-05-07 16:28 <a href="http://www.blogjava.net/hopeshared/archive/2006/05/07/44876.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：为异步 Web Services 创建支持回调的客户端</title><link>http://www.blogjava.net/hopeshared/archive/2006/05/07/44874.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Sun, 07 May 2006 08:19:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/05/07/44874.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/44874.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/05/07/44874.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/44874.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/44874.html</trackback:ping><description><![CDATA[　　Web services 是一种很有前途的技术，在面向服务的架构（ Service Oriented Architectures ， SOA ）中起着重要的作用。这种正在兴起的技术的一个关键方面就是提供了异步服务的能力。尽管现在的 web service 标准规范中包括了提供异步服务的内容，但客户端应用程序前景的细节还有一些混乱和模糊。 Web services 回调是实现这些异步服务的一个重要因素。这篇文章为创建带有回调操作的 Web services 的客户应用程序提供了实践指导。这篇文章中所有的代码段都来自于您可以下载的例子。这些例子包含了这些代码段的完整实现和使用指导。 
<p></p><p><strong>术语 </strong></p><p>　　在开始讨论支持回调的客户端之前，阐明相关术语是很重要的。下图就显示了客户端使用带有回调操作的 Web service 时所涉及到的主要实体。</p><p><img height="166" alt="Figure 1" src="http://dev2dev.bea.com.cn/images/webplat/images0506070301.jpg" width="258" /><br />图 1. 调用 Web service 的客户端 </p><p>　　上图描述了客户端对 Web service 的调用。 Web service 能够在一段时间后通过对客户端的回调做出响应 。因此，包含回调操作的 Web service 客户端的特别之处在于，客户端本身必须提供一个端点。我们调用这一回调端点 ，并将这个端点定义为由 URI 确定的唯一地址， SOAP 请求消息将发送到这个 URI 。 </p><p>　　将 SOAP 消息发送到Web service 端点 之后，客户端本身开始与 Web service 进行交互。由客户端发送给 Web service 的相关请求消息及其相关响应消息构成了客户端初始化操作 。如前所述，客户能够处理 Web service 发送到回调端点的请求消息。相关的请求和响应消息一起被称为一个回调 操作。 </p><p>　　理解这些术语之后，让我们走近一步考察 Web service 回调的概念，以及它与会话式 Web services 和异步 Web service 调用之间的关系。 </p><p><strong>异步、回调和会话</strong></p><p>　　异步 Web service 调用的概念有时容易与 Web services 回调和会话式 Web services 相混淆。虽然这三个概念很相关，但却不同。 </p><p>　　异步 Web services 调用 是指在不阻塞接收服务器发来的相应响应消息的情况下，客户端能够发送 SOAP 消息请求 。 BEA WebLogic Platform 8.1 web services 上进行异步 Web service 调用的过程已经详细地 <a href="http://e-docs.bea.com/wls/docs81/webserv/client.html#1069326" target="_blank">记录在软件文档中了 </a>，因此在本文中不作进一步的讨论。 </p><p>　　Web services 回调 是指 Web services 提供者向客户端发回 SOAP 消息的情况。 <a href="http://www.w3.org/tr/wsdl" target="_blank">Web Services Description Language (WSDL) specifications </a>将这种操作定义为一种“请求 / 响应”。支持回调操作的 Web services 客户端本身必须有一个 Web services 端点，这样 Web service 就可以利用这个 Web services 端点在任意时间发送回调请求，也就是说，可以是异步的。注意，这跟我们上面讨论的异步调用 没有关联。 </p><p>　　如果一系列可在两个端点之间来回传送的消息可以被唯一会话 ID 追踪，而这个 ID 又由特定的操作来标识消息流的始末，这种 Web services 就是 会话式 的。提供回调的 Web services 也定义为会话式的。这是因为正常情况下如果 Web services 能够对客户端进行回调访问，它就必须有它自己的回调端点信息。这种情况只有客户端做出了初始调用以后才会发生。因此，至少由客户启动的初始化操作和由 Web services 做出的回调操作是相互关联的，并且由唯一的会话 ID 跟踪。如果不是这样，客户端就无法分辨与不同初始调用相关联的回调操作。 </p><p>　　我们现在将考虑这些问题并创建支持回调的客户端，就像我们刚才所看到的，这些客户端构成了请求 - 响应和会话式 Web services 的基础。</p><p><strong>创建支持回调的客户端 </strong></p><p>　　正如前面讨论的，支持回调的 Web services 客户端需要提供一个能够异步接收和处理回调操作消息的回调端点。为避免必须提供回调端点这类复杂的事情，一种叫做 <a href="http://e-docs.bea.com/workshop/docs81/doc/en/workshop/guide/progmodel/conUsingPollingAsAnAlternativeToCallbacks.html" target="_blank">polling </a>（轮询）的技术可以作为替代技术。然而这种技术要求客户端周期性地调用服务端以校验回调事件。如果这种事件很少发生，那么调用的开销就太大了。如果客户端提供一个回调端点并直接处理回调操作，这种开销就可以避免。 </p><p>　　我们还应该注意到，尽管可以通过用 JMS 上的 Web services （如果提供了这种连接）创建支持回调的客户端，但这种方法有一些限制，其中一个重要的限制就是客户端要被迫采用与 Web services 提供者相同的 JMS 实现。因此我们将集中于经过 HTTP 传输来完成我们的任务。有两个领域需要创建这样的客户端：创建适当的客户端启动 SOAP 消息，以及处理回调操作。 </p><p>　　当客户端启动有回调的 Web service 操作时，它需要以某种方式包含回调端点的 URI ，使其在请求消息中监听。 <a href="http://www.w3.org/tr/2005/wd-ws-addr-core-20050215/" target="_blank">Web Services Addressing </a>和 <a href="http://dev2dev.bea.com/technologies/webservices/SOAPConversation.jsp" target="_blank">SOAP Conversation Protocol </a>规范都定义了 SOAP 头部元素，允许您实现这一目标。从理论上说，用于规定回调端点的规范并不重要。但是大多数 Web services 容器（包括 BEA WebLogic Server 8.1 ）都还没有包含 Web services Addressing 规范的实现形式。当前， BEA WebLogic Workshop 8.1 的 Web services 支持 SOAP Conversation Protocol 规范，我们将在例子客户端中使用。 </p><p>　　根据 SOAP Conversation Protocol ， SOAP 头部在会话的不同阶段是不同的。对于会话中的第一个客户端启动（开始）操作，我们需要通过 callbackLocation 头部元素 提供有回调端点的 Web service 。所有操作（包括第一个操作）也将需要唯一的 ID ，这个 ID 在整个会话过程中都用在我们的 SOAP 消息里。这可通过 conversationID 元素 来完成。下面是一个启动支持回调会话的 SOAP 请求消息的例子：</p><pre class="code">&lt;soapenv:Envelope soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/" 
    xmlns:env="http://schemas.xmlsoap.org/soap/envelop/" 
    xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"&gt;
  &lt;soapenv:Header&gt;
    &lt;con:StartHeader soapenv:actor="http://schemas.xmlsoap.org/soap/actor/next" 
     soapenv:mustUnderstand="0" 
     xmlns:con="http://www.openuri.org/2002/04/soap/conversation/"&gt;
    <b>  &lt;con:conversationID&gt;[123456]:192.168.1.100:8181&lt;/con:conversationID&gt;
         &lt;con:callbackLocation&gt;
          http://192.168.1.100:8181/StockNotificationCallback
         &lt;/con:callbackLocation&gt;
    </b>  &lt;/con:StartHeader&gt;
 &lt;/soapenv:Header&gt;
  &lt;soapenv:Body&gt;
    &lt;n1:registerForThresholdNotif xmlns:n1="http://www.openuri.org/"&gt;
      &lt;n1:stockTicker&gt;CCC&lt;/n1:stockTicker&gt;
      &lt;n1:threshold&gt;10&lt;/n1:threshold&gt;
    &lt;/n1:registerForThresholdNotif&gt;
  &lt;/soapenv:Body&gt;
&lt;/soapenv:Envelope&gt;
</pre><p>　　现有的大多数 Java Web service 工具包（例如 BEA WebLogic 的 clientgen 、 Apache Axis 和 JWSDP ）都允许您创建一个代理库，客户端程序可以容易地用它来调用 Web services 操作。但是，这些框架中没有一种支持回调操作，主要问题是它们的代理不生成所需的头部。在能提供这种支持以前，通过扩展它们对回调操作的支持来利用这些框架（例如复杂类 XML 映射），这种益处还是很需要的。一种用来达到这种效果的技术就是应用 <a href="http://e-docs.bea.com/wls/docs81/webserv/interceptors.html" target="_blank">SOAP 消息处理程序 </a>。 </p><p>　　上面提到的所有 Web services 工具包都能支持 SOAP 消息处理程序。消息处理程序是一种 Java 类，它实现了 javax.xml.rpc.handler.GenericHandler 界面，并且还包含一种称为先送出（或后接收） SOAP 消息的方法。这里介绍我们客户端中的消息处理程序，它能够找出一个特定会话的当前阶段，并据此扩展带有所需头部的请求消息。 </p><p>　　注意到这一点是很重要的，客户端 SOAP 消息处理程序必须能确定消息属于会话的哪个阶段，以便创建合适的头部元素。生成会话 ID 也是客户端处理程序要完成的一个任务。 </p><p>　　一旦 Web services 端点收到扩展的请求消息，它就会将请求消息发送到由开始消息的 callbackLocation 元素规定的回调端点。在大多数情况下，客户端过程自身就需要提供这个端点，并且恰当地处理回调消息。如果客户端在 Web services 的容器中运行，这项工作就可以通过把有回调操作的 Web services 部署在同一个容器内来完成。然而，如果客户端不是正在容器中运行，这项工作就要靠在一个嵌入在客户端过程本身的轻量级容器中执行回调端点来完成。这使我们能够调用客户端生成的操作，并且处理同一过程上下文中的传入回调操作。注意在回调端点背后（和在客户端中）的过程实体要求不仅能够分配对适当域的代码操作，而且还能处理 XML 映射。 </p><p>　　当然，客户端也可以选择简单地设置恰当的 callbackLocation 头部元素来规定一个在容器中的回调端点，而这个容器与访问过程相分离。 </p><p>　　正如我们已经看到的，为带回调操作的 Web services 创建客户端并不是毫无意义的，它包含了复杂元素，比如处理 SOAP 消息、管理会话（包括阶段和 ID ）、参数映射以及操作分配。当 Web service 通过 BEA WebLogic Workshop Service Control 访问时，这些复杂性就都不存在了，它会自动为用户执行所有操作。 </p><p><strong>使用服务控件创建支持回调的客户端</strong></p><p>　　通过 WebLogic Workshop Service Control 访问 Web services 在 <a href="http://e-docs.bea.com/workshop/docs81/doc/en/core/index.html">软件文档 </a>中已经做了详细描述。如果客户端实体能够使用控件（也就是 Java Process Definition 业务流程或其他控件； Page Flows 不能使用控件回调），这个解决方案就是最简单的使用支持回调的 Web services 的方案了。采用这种方法，所有涉及访问支持回调的 Web service 的复杂性就都迎刃而解了。</p><p><strong>股票通知服务例子 </strong></p><p>　　本文的例子包括一个股票通知（ Stock Notification ）的会话式 Web service 和一个能阐明概念的示例客户端。 Web service 提供的操作允许客户端注册股票接收机并设置一个相关的阈值价格。然后服务端就监视股票，只要股票价格超过了阈值价格就通过一个回调（ onThresholdPassed() ）通知客户端。 </p><p><img height="138" alt="Figure 2" src="http://dev2dev.bea.com.cn/images/webplat/images506070302.jpg" width="341" /><br />图 2. 本图说明了这个例子的配置 </p><p>　　很显然，轮询技术不是创建客户端的最佳解决方案：股票价格有可能经常超过阈值价格也可能极少超过阈值价格。轮询间隔短就会造成很多不必要的访问，而另一方面，轮询间隔长又可能导致股票价格超过阈值价格很长时间后客户端才被告知。 </p><p>　　客户端应用程序中回调端点的实现应该是一种更好的解决方案。让我们首先来看一下例子客户端是如何将操作传递给 StockNotification Web service 的。我们已经采用两种不同的技术实现了客户端。第一种技术使用 WebLogic Workshop 生成的代理库，并由 StockNotificationClient 类的 makeCallUsingBEAProxy() 方法来实现： </p><pre class="code">public void makeCallUsingBEAProxy() {
    try {
      // Get the proxy instance so that we can start calling the web service operations
      StockNotificationSoap sns = null;
      StockNotification_Impl snsi = new StockNotification_Impl();
      sns = snsi.getStockNotificationSoap();

      // Register our conversational handler so that it can properly set our
      // our conversation headers with a callback location
      QName portName = new QName("http://www.openuri.org/",
                                 "StockNotificationSoap");
      HandlerRegistry registry = snsi.getHandlerRegistry();
      List handlerList = new ArrayList();
      handlerList.add(new HandlerInfo(<b>ClientConversationHandler.class</b>, null, null));
      registry.setHandlerChain(portName, handlerList);

      // Register, call some methods, then sleep a bit so that our callback
      // location can receive some notifications and finally finish the conversation.
      sns.registerForThresholdNotif("AAAAA", "100");
      sns.addToRegistration("BBBBB", "5");
      StockList stocks = sns.getAllRegisteredStocks();

      ...

      sns.endAllNotifications();
    }
    catch (Exception e) {
      throw new RuntimeException(e);
    }
}
</pre><p>　　正如从上述代码段中看到的，我们可以使用 clientgen 生成的类。与没有回调的 Web service 调用相比，这段代码唯一强调的就是，在方法一开始就实例化和注册了客户端 SOAP 消息处理程序。这个处理程序截取了发出的 SOAP 消息，并加上必要的会话头部。每当客户端过程发出 SOAP 请求消息时，消息处理程序的 handleRequest() 方法就被调用，它利用了一个包含了输出 SOAP 请求信息的 MessageContext 对象。下面是例子客户端消息处理程序的代码段： </p><pre class="code">package weblogic.webservice.core.handler;

...

public class ClientConversationHandler
    extends GenericHandler {

public boolean handleRequest(MessageContext ctx) {  
  ...
  if (phase.equals("START")) {
    headerElement
              = (SOAPHeaderElement) header
              .addChildElement("StartHeader",
                               "con",
                               "http://www.openuri.org/2002/04/soap/conversation/");

    headerElement.addChildElement("con:callbackLocation")
              .addTextNode(CALLBACK_URI);
  }
  else if (phase.equals("CONTINUE") || phase.equals("FINISH")) {
    headerElement
              = (SOAPHeaderElement) header
              .addChildElement("ContinueHeader",
                               "con",
                               "http://www.openuri.org/2002/04/soap/conversation/");
  }

  headerElement.addChildElement("con:conversationID").addTextNode(convID);
  ...
}
}
</pre><p>　　BEA clientgen 工具生成的代理库已经用了一个缺省的客户端 SOAP 消息处理程序，可创建会话式 StartHeader 头部元素。不幸的是，目前的 clientgen 输出不支持回调操作，因此缺省的处理程序不会创建所需的 callbackLocation 次级元素。所以我们必须保证自己的消息处理程序重写缺省的会话式处理程序，以便管理创建 callbackLocation 头部的额外任务。我们通过确保处理程序在一个与缺省处理程序相同的程序包中创建来做到这一点，这个程序包就是 weblogic.webservice.core.handler ，并且它还有具体的相同类名称 ClientConversationHandler 。注意，这种技术涉及到重写现有会话消息处理程序，但它并不能保证是向前兼容的。这个例子展示了消息处理程序如何用于创建回调头部，以及这种概念如何应用于任何其他支持 SOAP 消息处理程序的 Web services 框架中。 </p><p>　　有一种使用 SOAP 消息处理程序和代理类的可选技术，它使用 JAXM API 直接创建 SOAP 请求消息，并把它们送往 Web service 。这是我们例子客户端采用的第二种技术，它在 StockNotificationClient 类的 makeCallsUsingJAXM() 和 callMethodFromFile() 方法中实现： </p><pre class="code">public void makeCallsUsingJAXM() {
      callMethodFromFile("C:\\registerForNotifSOAP.xml");
      ...
      callMethodFromFile("C:\\endAllNotifSOAP.xml");
}

private void callMethodFromFile(String fileName) {

    try {
      // Create a SOAP connection object
      SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance();
      SOAPConnection conn = scf.createConnection();

      // Create the SOAP request message from the specified file
      MessageFactory mf = MessageFactory.newInstance();
      SOAPMessage msg = mf.createMessage();
      SOAPPart sp = msg.getSOAPPart();

      // Read the file content into a string and replace the conversation ID with
      // the current one.
      String fileContent = readFileIntoString(fileName);
      fileContent = fileContent.replaceFirst(CONV_ID_HOLDER,
                                             ConvIDGenerator.getInstance().
                                             getConversationID());

      StreamSource prepMsg = new StreamSource(new StringBufferInputStream(
          fileContent));
      sp.setContent(prepMsg);
      msg.saveChanges();

      // Make the actual call
      conn.call(msg, TARGET_SERVICE_URI);
      conn.close();
    }
    catch (Exception ex) {
      throw new RuntimeException(ex);
    }
}   
</pre><p>　　callMethodFromFile() 方法从指定的文件读取 SOAP 消息，用客户端的当前会话 ID 取代消息会话 ID ，最后生成实际调用。当使用 JAXM 方法时， Java 到 XML 的映射操作参数和返回值必须由客户端来完成。通过使用从文件中预先生成的 SOAP 消息（它已经包含了所需的参数值），我们已经避免了这一任务。尽管从概念上来说这种方法很好，但对于比较复杂的客户端端来说，这不是一种可行的解决方案。这些客户端必须从头开始通过编程方式使用 JAXM 来创建消息。 </p><p>　　既然我们已经回顾了客户端在生成 Web services 操作中的作用，下面让我们转向客户端的回调端点的实现方式和对来自 Web services 回调消息的处理。因为回调端点需要能够处理输入的 HTTP 请求， servlet 就是一种合适的选择。进一步说，我们非常需要一个 servlet ，它能够从输入的 HTTP 请求中提取 SOAP 消息，并以一种容易使用的方式提供给我们。 javax.xml.messaging 程序包里的 ReqRespListener 接口和 JAXMServlet 类提供给我们这个功能。只要安排合理，应用了这种接口和类的 servlet 将把所有的目标 HTTP post 请求自动转换成 SOAPMessage 实例，并通过 onMessage() 方法传递给我们。下面的代码显示了 onMessage() 方法如何帮助例子客户端实现这些功能。 </p><pre class="code">public class CallBackHandlerServlet
    extends JAXMServlet
    implements ReqRespListener {


  public SOAPMessage onMessage(SOAPMessage message) {
    try {
      // We have just received a SOAP message at the callback
      // endpoint. In this example we will just assume that
      // the message received is in fact the onThresholdPassed
      // callback request. However, a servlet handling
      // multiple callbacks cannot make this assumption and
      // should process the SOAP message to see what callback
      // it relates to and do as appropriate for each.
      String stockTicker = extractOnThresholdPassedArgument(message);

	System.out.println("[DEV2DEV CALLBACK EXAMPLE]: Received treshold notification 
	                                for: " + stockTicker);

      // Now we have to create a proper response to the callback
      // request. Returning this response as part of the onMessage()
      // method will ensure that the SOAP response gets back to the server.
      SOAPMessage response = createThresholdPassedResponse();

      return response;
    }
    catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
  ...
}
</pre><p>　　一旦回调请求消息被 onMessage() 方法所接收，客户端就从股票接收机中提取参数，将它输出到标准设备上，并生成一条相应的响应消息，它还会通过 servlet 返回到 Web service 。使用带有多个回调操作的 Web services 客户端也需要把传入的请求分发给客户端代码的合适部分，这个过程是基于相应的回调操作的。 </p><p>　　尽管 servlet 包含了合适代码来处理来自 Web services 的传入 onThresholdPassed() 回调消息，但它需要在监听回调 URI 的 servlet 容器中部署完成，这样才能完成回调端点的实现。 <a href="http://jetty.mortbay.org/jetty/index.html" target="_blank">Jetty </a>开源项目有一个轻量级 servlet 容器，它可以嵌入在我们的客户端中。将 CallBackHandlerServlet servlet 部署在一个嵌入式 Jetty 容器中，允许我们将回调端点驻留在客户端 Java 进程中。 StockNotificationCallbackProcessor 类是一种客户端使用的公共类，它用于启动 Jetty 服务器和部署CallBackHandlerServlet servlet ： </p><pre class="code">public class StockNotificationCallbackProcessor {

  public static final String CALLBACK_SERVER_PORT = ":8181";
  public static final String CALLBACK_SERVLET_CLASS = 
       "asynchwsconsumer.CallBackHandlerServlet";
  public static final String CALLBACK_SERVLET_NAME = "CallBackHandlerServlet";

  private HttpServer server;

  public StockNotificationCallbackProcessor() {}

  public void startListening() {

    try {
      // Configure the server so that we listen on the callback URI
      server = new Server();
      server.addListener(CALLBACK_SERVER_PORT);
      ServletHttpContext context = (ServletHttpContext) server.getContext("/");
      context.addServlet(CALLBACK_SERVLET_NAME, "/*",
                         CALLBACK_SERVLET_CLASS);

      // Start the http server
      server.start();
    }
    catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  public void stopListening() {
    try {
      server.stop();
    }
    catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
}
</pre><p>　　startListening() 方法把 CallBackHandlerServlet 部署在端口 8181 上并配置嵌入式 servlet 容器，这样所有 HTTP 请求都将指向这个端口。这种方法还启动了嵌入式 servlet 容器。 </p><p>　　现在我们已经考察了 Web service 操作的创建和回调操作的处理，下面我们来看看例子客户端的 main() 方法是如何使用这些元素的： </p><pre class="code">public static void main(String[] args) {

    StockNotificationClient snClient = new StockNotificationClient();

    snClient.snCallbackProcessor.startListening();

    snClient.makeCallUsingBEAProxy();

    ConvIDGenerator.getInstance().resetConversationID();

    snClient.makeCallsUsingJAXM();

    snClient.snCallbackProcessor.stopListening();
}
</pre><p>　　正如您所看到的，这种方法开始于建立一个回调端点（正如前面所看到的，它包括启动嵌入式 servlet 容器和部署回调过程）。该方法接着使用 BEA clientgen 代理来调用股票通知的 Web service 。这样，这种与 Web services 的交互就通过调用 endAllNotifications() 端操作来完成会话，客户端需要改变会话 ID 以启动新会话。客户端使用 ConvIDGenerator 单一类来管理会话 ID ，而 ConvIDGenerator 类又使用 java.rmi.dgc.VMID 类来创建合适的格式化唯一会话 ID 。 </p><p>　　一旦会话 ID 发生了变化，客户端就会用 JAXM 再一次调用股票通知 Web services 。最后，客户端终止嵌入式 servlet 容器，这个过程就结束了。 </p><p>　　我们现在已经完成了对例子客户端的分析，该例子客户端可作为本文的一部分下载。当您运行客户端和股票通知 Web services 的时候，客户端和 Web service 都将把消息显示在标准输出设备上，用以描述会话的不同阶段，包括对回调操作的处理。 </p><p><strong>结束语 </strong></p><p>　　本文展示了为包含回调操作的 Web services 创建独立客户端过程的步骤。这种客户端需要管理 Web services 调用的会话方面，并提供一个端点用于 Web service 进行回调操作。 </p><p><strong>下载</strong></p><p><a href="http://ftpna2.bea.com/pub/downloads/callbackexample.zip" target="_blank">CallbackExample.zip </a>(1.7Mb) ——这个文件包括了本文讲述的完整实例应用程序。</p><p><strong>参考资料</strong></p><ul><li><a href="http://e-docs.bea.com/wls/docs81/webserv/client.html" target="_blank">Invoking Web Services from Client Applications and WebLogic Server </a></li><li><a href="http://e-docs.bea.com/workshop/docs81/doc/en/workshop/guide/progmodel/conUsingPollingAsAnAlternativeToCallbacks.html" target="_blank">Using Polling as an Alternative to Callbacks </a></li><li><a href="http://www.w3.org/tr/wsdl" target="_blank">Web Services Description Language Specification </a></li><li><a href="http://jetty.mortbay.org/jetty/index.html" target="_blank">Jetty Java HTTP Servlet Server </a></li><li><a href="http://e-docs.bea.com/workshop/docs81/doc/en/workshop/guide/controls/service/navServiceControl.html" target="_blank">Workshop Web Service Control </a></li><li><a href="http://e-docs.bea.com/wls/docs81/webserv/interceptors.html" target="_blank">Creating SOAP Message Handlers to Intercept the SOAP Message </a></li><li><a href="http://dev2dev.bea.com/technologies/webservices/SOAPConversation.jsp" target="_blank">SOAP Conversation Protocol </a></li><li><a href="http://www.w3.org/tr/2005/wd-ws-addr-core-20050215/" target="_blank">Web Services Addressing </a></li></ul><p><strong>原文出处</strong></p><p><a href="http://dev2dev.bea.com/pub/a/%202005/03/c%20allback_clients.html" target="_blank">http://dev2dev.bea.com/pub/a/ 2005/03/c allback_clients.html</a><!--文章其他信息--></p><img src ="http://www.blogjava.net/hopeshared/aggbug/44874.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-05-07 16:19 <a href="http://www.blogjava.net/hopeshared/archive/2006/05/07/44874.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：关于Apache Axis2的Web service消息</title><link>http://www.blogjava.net/hopeshared/archive/2006/05/07/44869.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Sun, 07 May 2006 08:05:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/05/07/44869.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/44869.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/05/07/44869.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/44869.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/44869.html</trackback:ping><description><![CDATA[
		<h4>摘要:</h4>到目前为止，web service交互作用是独立同步的，同时本质上是应答式的。不过，很显然同步应答类型在基于消息的应用中只是一个很小的子集。消息在耦合松散系统中是非常重要的，因此这种限制很关键。Web service规范，例如WS-addressing和WSDL，已经融入了消息的概念并且为包含一个相当大范围的消息应用奠定了基础。Apache Axis2 架构既不基于任一个消息交换模式，也不基于同步/异步行为。这篇文章解释了消息概念和Axis2在几种众所周知的消息场合中怎样被扩展使用。 <br /><br /><center><b><span style="FONT-SIZE: 20px">关于Apache Axis2的Web service消息</span></b></center><br /><center>作者：Srinath Perera, Ajith Ranabahu</center><br /><center>07/27/2005 </center><br /><center>翻译：<a href="http://www.matrix.org.cn/user.shtlm?username=doomsday" target="_new">doomsday</a></center><br /><span style="COLOR: purple">版权声明</span>：可以任意转载，转载时请务必以超链接形式标明文章原始出处和作者信息及本声明<br />英文原文地址:<br /><a href="http://www.onjava.com/pub/a/onjava/2005/07/27/axis2.html" target="_new">http://www.onjava.com/pub/a/onjava/2005/07/27/axis2.html</a><br />中文地址:<br /><a href="http://www.matrix.org.cn/resource/article/43/43723_Apache_Axis2.html" target="_new">http://www.matrix.org.cn/resource/article/43/43723_Apache_Axis2.html</a><br />关键词： Apache Axis2 Web service<br /><br />   <br />     到目前为止，web service交互作用是独立同步的，同时本质上是应答式的。不过，很显然同步应答类型在基于消息的应用中只是一个很小的子集。消息在耦合松散系统中是非常重要的，因此这种限制很关键。Web service规范，例如WS-addressing和WSDL，已经融入了消息的概念并且为包含一个相当大范围的消息应用奠定了基础。Apache Axis2 架构既不基于任一个消息交换模式，也不基于同步/异步行为。这篇文章解释了消息概念和Axis2在几种众所周知的消息场合中怎样被扩展使用。<br /><br /><b><span style="FONT-SIZE: 16px">消息的简单介绍</span></b><br /><br />    贯穿计算历史，分布式运算是其中的一个很大的挑战：当资源是分布式时，进程间的通信变得相当困难，研究人员仍然在寻找更好的解决方案。有趣的是，几乎所有关于分布式计算机计算能力问题的解决方案来源于两种概念基础： 远程过程调用(RPC) 和消息传递。<br /><br />    毫无疑问，使用RPC在开发人员中是非常流行的技术，部分原因是是本地过程调用与它的类似之处。本地过程调用在程序员中很有人气，所以在分布式系统中使用RPC是很自然的选择，而另一方面，消息传递不是非常流行，当它被提起时很少有开发人员关注它。不过，在某些场合使用消息相比RPC系统有更好的优势。<br /><br />RPC和消息框架的基本差异如下所示：<br /><br />●消息完全不懂客户端和服务器，因为一个消息框架（通常所说的面向消息的中间件，或message-oriented middleware，即MOM）集中于传递消息，所有接收和散发消息的节点身份平等，术语称之为对等体。RPC始终有服务请求者 (AKA client) 和服务提供者 (AKA server)的概念。 <br />●消息对于一个特定范畴是时间独立的。没有任何对等体希望实时接收消息－－当对等体可用时MOM关注于传递一个消息到相应的对等体，然而，RPC在失去一方时立即失效。<br />●消息可被复制并且轻易的传递到众多对待体。RPC本质上是一种一对一的交流方式，而消息更灵活，并且毫不费力地传递同一消息的拷贝到多种对等体。<br /><br /><b><span style="FONT-SIZE: 16px">Web service消息</span></b><br /><br />    Web service是在XML消息的基础上定义的，下面3个因素描述了一个给定的Web service的消息交互。<br /><br />●消息交换模式<br />●同步和异步客户端API<br />●单向和双向传送行为<br /><br />    从最抽象的角度来讲，，web service消息传递建立在发送和接收消息基础上，一个给定的消息被一方发出，并且被另一方接收。消息可能相互关联，识别这些相互关联的消息群中的最常见的应用场合是非常重要的，这些消息群被定义为消息交换模式(message exchange patterns)，简称MEPs.<br /><br />    过渡时期下在两种相关消息间的一个服务请求者的行为在客户端API定义了消息同步/异步行为。同步场合下，客户端请求将会阻塞，在相关消息到达目的地后前一直等待，在非阻塞场合下，客户端请求不会阻塞，当相关消息到达时，它与之前的消息相互联系。<br /><br />    传送分类为单向或双向，基于单方或双方行为。类似SMTP和JMS传送即是单向传送的，不会阻塞，另一方面，类似HTTP和TCP即是双向传送，相关消息可能在回路中返回，实际上，在Web service消息中，双向传送可能被用作单向传送，但是在这些场合下，它们可被有效的处理为单向方式。<br /><br /><b><span style="FONT-SIZE: 16px">消息交换模式</span></b><br /><br />    根据W3C建议，消息交互模式就是一个为交流双方构建消息交换的一个模板，一个MEP将相关消息确定为一组。MEPs根据服务请求者和服务提供者来定义，需要注意，为了清晰，MEPs以服务提供者的消息特性来命名。为方便理解，所有的命名都可以用request代替in, 用response代替out。<br /><br />例如，我们看看两个有名的MEPS<br /><br />1.In-only/"发后不理:" 服务请求者发送消息给服务提供者但是不关心任何后继相关消息<br />2.In-out/"应答式:" 服务请求者发送消息给服务提供者并希望返回结果<br /><br />    MEPS概念仍在扩展中，模式的数目是没有限制的，所以Web service中间件应用强制使用几种选定的MEPs，"发后不理"和 "应答式" 是被明确使用的，其它大多数的模式可由这两种组合使用。<br /><br /><b><span style="FONT-SIZE: 16px">客户端API同步/异步行为</span></b><br /><br />    同步/异步（或阻塞/非阻塞）行为是基于在web service请求的线程，同步服务将会阻塞，等待相关消息到达。另一方面，异步请求仅仅返回，等待相关消息被后台另一个不同线程执行。<br /><br />    这两种途径有典型的用例。考虑一下银行事务，其需要一定数量的消息来来回传递。银行事务本质是连续的，当结果到达时后执行下一步骤，因此同步等待结果很有意义。另一方面，设想一个航班预约程序，其需要搜集多种数据来源，根据这些结果再匹配。这个案例中，异步行为发挥作用，因为程序可以提交所有结果并且当数据到达时工作。考虑到网络响应，异步方式获得较好的结果。<br /><br />    同步请求很简单：请求在相关消息到达前等待，并且可以像本地过程调用一样被编码。但是异步消息的相互关系就比较复杂，客户端必须处理这种复杂性。尽管如此，通过一些额外工作来处理这种复杂情况仍是必要的。<br /><br /><b><span style="FONT-SIZE: 16px">传输层的行为</span></b><br /><br />    传输层的行为是个关键因素，决定了Web service消息的发生，传输根据依据其行为分类为单向和双向。<br />    单向传送减少web service消息的复杂性，因为相关消息必须来源于各自的通道。另一方面，如果传送是双向的，消息有机会选择使用单向还是双向，例如，传输是HTTP时，相关消息来自HTTP连接的返回路径，或者这么讲web service提供者可以写HTTP 200来指出没有来自同一连接的响应，在这种案例下回应经由独立的HTTP连接发送。<br /><br /><b><span style="FONT-SIZE: 16px">Web service寻址角色</span></b><br /><br />    webs ervice寻址框架（也被称为WS-addressing）是为了在同一web service交互活动中交换不同信息部分，下面的5个因素定义了交互活动：<br /><br />    1.消息交换模式<br />    2.可被访问的服务传送<br />    3.相关消息传送<br />    4.传送的行为<br />    5.客户端API的同步/异步行为<br /><br />    服务提供者申明了头两个，客户端定义了其余因素，客户端级别的同步/异步行为对服务提供者是完全透明的，客户端使用WS-addressing来解释web service消息。<br /><br />    在其它大多数结构中，WS-addressing定义了四种标题：To, ReplyTo, RelatesTo, FaultTo以及一个被称为匿名地址的特定地址，当一个服务提供者接收到SOAP消息时，它会查找在to地址上的目标服务并且调用服务。如果有结果，即被发送到ReplyTo地址，错误被发送到FaultTo地址，如果以上任一个的标题没有指定或具有匿名值，结果通过双向传送返回路径返回（因为匿名决定双向传送返回路径）。<br /><br />    传送和WS-addressing一起定义了查找相关消息的机制，消息是相关缘于它们共享了相同的传送通道，也可能因为它们都共享把它们互相链接的公共信息。web service RelateTo标题正好提供了这种关系。<br /><br />下面的表显示的明确定义的消息交互活动的寻址标题的不同值<br /><img onmouseover="javascript:imgShowTip(this);" style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="" src="http://www.matrix.org.cn/resource/upload/content/2005_09_06_112234_lxYNHabcLo.gif" onload="javascript:imgLoad(this);" border="0" resized="0" /><br /><br /><br /><b><span style="FONT-SIZE: 16px">Axis2客户端API概念</span></b><br /><br />    Axis2客户端API处理了In-Only和In-OutMEPs，所有的消息结合在下面的章节讨论。MEPs的空间是无限的，因此，Axis2强制提供了支持任意消息交换模式的核心，并且提供了两种常被使用的模式In-Only和In-Out的API，有两种方法实现更多的复杂模式：组合In-Only和In-Out来完成希望的模式，或者对希望的模式写新的扩展。因为Axis2为任意MEP提供核心级别的支持，实现是显而易见的。In-Only和In-OutMEPS被InOnlyMEPClient和InOutMEPClient类支持，下两节即做具体描述。<br /><br /><b>In-Only MEP 支持: InOnlyMEPClient</b><br /><br />    InOnlyMEPClient类对发送不理消息提供了支持，所有的传送类型作为单向传送对待，InOnlyMEPClient和InOutMEPClient真正的差别是寻址参数起先没有锁定，并且寻址参数随后被Axis2控制。作为可被控制的寻址参数，InOnlyMEPClient可被用作消息API，并且在此基础上构建更复杂的消息交互。<br /><br /><b>In-Out MEP 支持: InOutMEPClient</b><br /><br />    InOutMEPClient和继承了InOutMEPClient的调用类为应答式消息提供了支持，Axis2关注完整的操作，除了To地址外的所有的寻址属性都在Axis2的控制下<br /><br />    用户可以配置InOutMEPClient 来表现不同，利用以下的四个参数。<br /><br />1.发送者传输<br />2.监听者传输<br />3.是用单独监听<br />4.使用阻塞<br /><br /><img onmouseover="javascript:imgShowTip(this);" style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="" src="http://www.matrix.org.cn/resource/upload/content/2005_09_06_112338_dZGrdHMMOS.gif" onload="javascript:imgLoad(this);" border="0" resized="0" /><br /><br />    客户端API当前提供了针对HTTP和SMTP传输的支持，下面的表格显示了这些参数可能的组合以及它们怎样结合来提供不同特效。<br /><br /><b><span style="FONT-SIZE: 16px">举例</span></b><br /><br />    下面的代码实例显示了怎样使用Apache Axis2做几个定义明确的交互作用,用户可以在客户端API简单的转换属性从而转换不同的交互作用，客户端Axis2 API仅仅支持XML级别的消息和代表大块XML的OME元素。<br /><br /><b>调用单向消息</b><br /><br />    单向MEP简单之处在于在仅有一个消息来回传送时它能表现正确的单向，这些消息被异步对待并且传送是单向的。<br /><br /><b>应答式消息</b><br /><br />    可以表现四种方式的应答式消息<br /><br />    1.双向In-Out 同步<br />    2.双向In-Out 异步<br />    3.单向In-Out 同步<br />    4.单向In-Out 异步<br /><br />    下面的代码实例说明这些案例怎样被Axis2寻址，注意客户端API的四种属性怎样被使用。<br /><br />    1.In-Out同步，HTTP作为双向传输方式<br /><br /><pre class="overflow">OMElement payload = .... <br />Call call = new Call();<br />call.setTo(<br />        new EndpointReference(AddressingConstants.WSA_TO,<br />                "HTTP://...));<br />call.setTransportInfo(Constants.TRANSPORT_HTTP, <br />       Constants.TRANSPORT_HTTP, false);<br />OMElement result =<br />        (OMElement) call.invokeBlocking(<br />        operationName.getLocalPart(), payload);</pre><br /><br />    这里，SOAP消息经由同一个HTTP连接传播，地址属性没有指定，所以它们在服务器方缺省为匿名，客户端API将被锁定直到回复消息到达。<br /><br />    2.In-Out异步，HTTP使用HTTP作为双向传送<br /><br /><pre class="overflow">//this is the payload goes on the body of SOAP message <br />OMElement payload = .... <br />Call call = new Call();<br />call.setTo(<br />        new EndpointReference(AddressingConstants.WSA_TO,<br />                "HTTP://...));<br />call.setTransportInfo(Constants.TRANSPORT_HTTP,<br />              Constants.TRANSPORT_HTTP, false);<br /><br />Callback callback = new Callback() {<br />    public void onComplete(AsyncResult result) {<br />        //what user can do to result<br />    }<br />    public void reportError(Exception e) {<br />       //on error<br />    }<br />};<br />call.invokeNonBlocking(operationName.getLocalPart(),<br />       payload, callback);</pre><br /><br />    和前面相同，SOAP消息经由同一个HTTP连接传输并且不需要寻址，一旦回复消息到达客户端API不会阻塞并且回调将被执行。<br /><br />    3.In-Out, 异步HTTP 作为单向传输<br /><br /><pre class="overflow">OMElement payload = .... <br />Call call = new Call();<br />call.setTo(<br />        new EndpointReference(AddressingConstants.WSA_TO,<br />                "HTTP://...));<br />call.setTransportInfo(Constants.TRANSPORT_HTTP,<br />    Constants.TRANSPORT_HTTP, true);<br />Callback callback = new Callback() {<br />        public void onComplete(AsyncResult result) {<br />        ....<br />        }<br /><br />        public void reportError(Exception e) {<br />        ...<br />        }<br />};<br />call.engageModule(new Qname("addressing"));<br />call.invokeNonBlocking(operationName.getLocalPart(), method, callback);</pre><br /><br />    在这个案例中，SOAP消息通过两个HTTP连接传输，寻址是强制的，ReplyTo标题出现指示服务器端经由单独的通道发送回应。客户端没有阻塞，当回应消息到达时，唤起回调。<br /><br />4.In-Out, 同步 HTTP 作为单向传送<br /><br /><pre class="overflow">OMElement payload = .... <br />Call call = new Call();<br />call.setTo(<br />new EndpointReference(AddressingConstants.WSA_TO,<br />        "HTTP://...));<br />call.setTransportInfo(Constants.TRANSPORT_HTTP,<br />    Constants.TRANSPORT_HTTP, true);<br />OMElement result =<br />        (OMElement) call.invokeBlocking(<br />           operationName.getLocalPart(), payload);</pre><br /><br />    在这种场合下使用"In-Out,异步HTTP作为单向传送"类型，在结果到达第二种连接时唤起阻塞，执行并返回结果。<br /><br /><b><span style="FONT-SIZE: 16px">总结</span></b><br /><br />    总而言之，web wervice消息行为建立在三种因素上：消息交互模式，客户端同步异步模式和传送行为。Asis2建立核心在不一定要任何MEP类型，不过为MEPs的广泛支持：单向和应答提供了客户端API支持，这篇文章解释Axis2消息支持概念和客户端API的使用。<br /><br /><b>资源</b><br />  <br />●<a href="http://ws.apache.org/axis2/" target="_new">Apache Axis2的官方站点</a><br />●W3C讨论稿, <a href="http://www.w3.org/TR/2004/WD-wsdl20-patterns-20040326/" target="_new">"WSDL Version 2.0 Part 2: Message Exchange Patterns" </a><br />●<a href="http://www.neward.net/ted/weblog/index.jsp?date=20030409" target="_new">"Why Messaging? The Mountain of Worthless Information," </a>Ted Neward的博客, 星期三，2003年5月9日<br />●<a href="http://dev2dev.bea.com/pub/a/2005/01/ws_addressing_intro.html" target="_new">"Introduction to WS-Addressing,"</a>  作者Beth Linker, dev2dev, 2005年1月31日 <br />●<a href="http://www.pacificspirit.com/blog/2005/05/05/async" target="_new">"Async," </a>Dave Orchard的博客, 2005年5月5日 <br />●<a href="http://www-128.ibm.com/developerworks/library/ws-asynch2/" target="_new">"Programming Patterns to Build Asynchronous Web Services,"</a>  Holt Adams, IBM开发者文集, 2002年6月1日<br /><br />Srinath Perera是Apache Axis2的主要架构师<br />Ajith Ranabahu是Apache Axis2项目的成员并且在基于Web service的项目里工作了3年<br /><br /><br /><img src ="http://www.blogjava.net/hopeshared/aggbug/44869.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-05-07 16:05 <a href="http://www.blogjava.net/hopeshared/archive/2006/05/07/44869.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：深入学习Web Service系列之异步开发模式</title><link>http://www.blogjava.net/hopeshared/archive/2006/05/07/44866.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Sun, 07 May 2006 07:28:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/05/07/44866.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/44866.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/05/07/44866.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/44866.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/44866.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 深入学习Web Service系列之				异步开发模式																																		——《深入学习				Web Service				系列》之一								Terrylee				，				2005				年				12				月				4				日				...&nbsp;&nbsp;<a href='http://www.blogjava.net/hopeshared/archive/2006/05/07/44866.html'>阅读全文</a><img src ="http://www.blogjava.net/hopeshared/aggbug/44866.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-05-07 15:28 <a href="http://www.blogjava.net/hopeshared/archive/2006/05/07/44866.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：何时采用异步 Web 方法</title><link>http://www.blogjava.net/hopeshared/archive/2006/05/07/44864.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Sun, 07 May 2006 07:22:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/05/07/44864.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/44864.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/05/07/44864.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/44864.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/44864.html</trackback:ping><description><![CDATA[在确定是否适合在您的应用程序中采用异步 Web 方法时，有几个问题需要考虑。首先，调用的 BeginXXX 函数必须返回一个 IAsyncResult 接口。IAsyncResult 是从多个异步 I/O 操作返回的，这些操作包括访问数据流、进行 Microsoft&amp;reg; Windows&amp;reg; 套接字调用、执行文件 I/O、与其他硬件设备交互、调用异步方法，当然也包括调用其他 Web 服务。您可以从这些异步操作中得到 IAsyncResult，以便从 BeginXXX 函数返回它。您也可以创建自己的类以实现 IAsyncResult 接口，但随后可能需要以某种方式包装前面提到的某个 I/O 操作。 <br /><br />对于前面提到的大多数异步操作，使用异步 Web 方法包装后端异步调用很有意义，可以使 Web 服务代码更有效。但使用委托进行异步方法调用时除外。委托会导致异步方法调用占用进程线程池中的某个线程。不幸的是，ASMX 处理程序为进入的请求提供服务时同样要使用这些线程。所以与对硬件或网络资源执行真正 I/O 操作的调用不同，使用委托的异步方法调用在执行时仍将占用其中一个进程线程。您也可以占用原来的线程，同步运行您的 Web 方法。 <br /><br />下面的示例显示了一个调用后端 Web 服务的异步 Web 方法。它已经使用 WebMethod 属性标识了 BeginGetAge 和 EndGetAge 方法，以便异步运行。此异步 Web 方法的代码调用名为 UserInfoQuery 的后端 Web 方法，以获得它需要返回的信息。对 UserInfoQuery 的调用被异步执行，并被传递到 AsyncCallback 函数，后者被传递到 BeginGetAge 方法。这将导致当后端请求完成时，调用内部回调函数。然后，回调函数将调用 EndGetAge 方法以完成请求。此示例中的代码比前面示例中的代码简单得多，并且还具有另外一个优点，即没有在与为中间层 Web 方法请求提供服务的相同线程池中启动后端处理。 <br /><br />[WebService] <br /><br />public class GetMyInfo : System.Web.Services.WebService <br />{ <br /><br />[WebMethod] <br />public IAsyncResult BeginGetAge(AsyncCallback cb, Object state) <br />{ <br /><br />// 调用异步 Web 服务调用。 <br />localhost.UserInfoQuery proxy <br />= new localhost.UserInfoQuery(); <br />return proxy.BeginGetUserInfo("用户名", <br />cb, <br />proxy); <br />} <br /><br />[WebMethod] <br />public int EndGetAge(IAsyncResult res) <br />{ <br />localhost.UserInfoQuery proxy <br />= (localhost.UserInfoQuery)res.AsyncState; <br />int age = proxy.EndGetUserInfo(res).age; <br />// 在此对 Web 服务的结果进行其他 <br />// 处理。 <br />return age; <br />} <br />} <br /><br />发生在 Web 方法中的最常见的 I/O 操作类型之一是对 SQL 数据库的调用。不幸的是，目前 Microsoft&amp;reg; ADO.NET 尚未定义一个完好的异步调用机制；而只是将 SQL 调用包装到异步委托调用中对提高效率没有什么帮助。虽然有时可以选择缓存结果，但是也应当考虑使用 Microsoft SQL Server 2000 Web Services Toolkit（英文）将您的数据库发布为 Web 服务。这样您就可以利用 .NET Framework 中的支持，异步调用 Web 服务以查询或更新数据库。 <br /><br />通过 Web 服务调用访问 SQL 时，需要注意众多的后端资源。如果您使用了 TCP 套接字与 Unix 计算机通信，或者通过专用的数据库驱动程序访问其他一些可用的 SQL 平台，甚至具有使用 DCOM 访问的资源，您都可以考虑使用众多的 Web 服务工具包将这些资源发布为 Web 服务。 <br /><br />使用这种方法的优点之一是您可以利用客户端 Web 服务结构的优势，例如使用 .NET Framework 的异步 Web 服务调用。这样您将免费获得异步调用能力，而您的客户端访问机制会与异步 Web 方法高效率地配合工作。 <br /><br />使用异步 Web 方法聚合数据 <br /><br />现在，许多 Web 服务都访问后端的多个资源并为前端的 Web 服务聚合信息。尽管调用多个后端资源会增加异步 Web 方法模型的复杂性，但最终还是能够显著提高效率。 <br /><br />假设您的 Web 方法调用两个后端 Web 服务：服务 A 和服务 B。从您的 BeginXXX 函数，您可以异步调用服务 A 和服务 B。您应该向每个异步调用传递自己的回调函数。在从服务 A 和服务 B 接收到结果后，为触发 Web 方法的完成，您提供的回调函数将验证所有的请求都已完成，在返回的数据上进行所有的处理，然后调用传递到 BeginXXX 函数的回调函数。这将触发对 EndXXX 函数的调用，此函数的返回将导致异步 Web 方法的完成。 <br /><br />小结 <br /><br />异步 Web 方法在 <a title="" href="http://ewebapp.cnblogs.com/category/35086.html">ASP.NET</a> Web 服务中提供了一个有效的机制，可以调用后端服务，而不会导致占用却不利用进程线程池中的宝贵线程。通过结合对后端资源的异步请求，服务器可以使用自己的 Web 方法使同时处理的请求数目达到最大。您应该考虑使用此方法开发高性能的 Web 服务应用程序。 <br /><br /><br />原文地址：<a href="http://ewebapp.cnblogs.com/articles/237372.html">http://ewebapp.cnblogs.com/articles/237372.html</a><img src ="http://www.blogjava.net/hopeshared/aggbug/44864.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-05-07 15:22 <a href="http://www.blogjava.net/hopeshared/archive/2006/05/07/44864.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：简单的异步 Web 方法 </title><link>http://www.blogjava.net/hopeshared/archive/2006/05/07/44863.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Sun, 07 May 2006 07:18:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/05/07/44863.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/44863.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/05/07/44863.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/44863.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/44863.html</trackback:ping><description><![CDATA[为举例说明异步 Web 方法，我从一个名为 LengthyProcedure 的简单同步 Web 方法开始，其代码如下所示。然后我们再看一看如何异步完成相同的任务。LengthyProcedure 只占用给定的毫秒数。 <br /><br />[WebService] <br /><br />public class SyncWebService : System.Web.Services.WebService <br />{ <br /><br />[WebMethod] <br />public string LengthyProcedure(int milliseconds) <br />{ <br />System.Threading.Thread.Sleep(milliseconds); <br />return "成功"; <br />} <br />} <br /><br />现在我们将 LengthyProcedure 转换为异步 Web 方法。我们必须创建如前所述的 BeginLengthyProcedure 函数和 EndLengthyProcedure 函数。请记住，我们的 BeginLengthyProcedure 调用需要返回一个 IAsyncResult 接口。这里，我打算使用一个委托以及该委托上的 BeginInvoke 方法，让我们的 BeginLengthyProcedure 调用进行异步方法调用。传递到 BeginLengthyProcedure 的回调函数将被传递到委托上的 BeginInvoke 方法，从 BeginInvoke 返回的 IAsyncResult 将被 BeginLengthyProcedure 方法返回。 <br /><br />当委托完成时，将调用 EndLengthyProcedure 方法。我们将调用委托上的 EndInvoke 方法，以传入 IAsyncResult，并将其作为 EndLengthyProcedure 调用的输入。返回的字符串将是从该 Web 方法返回的字符串。下面是其代码： <br /><br />[WebService] <br /><br />public class AsyncWebService : System.Web.Services.WebService <br />{ <br />public delegate string LengthyProcedureAsyncStub( <br />int milliseconds); <br /><br />public string LengthyProcedure(int milliseconds) <br />{ <br />System.Threading.Thread.Sleep(milliseconds); <br />return "成功"; <br />} <br /><br />public class MyState <br />{ <br />public object previousState; <br />public LengthyProcedureAsyncStub asyncStub; <br />} <br /><br />[ System.Web.Services.WebMethod ] <br /><br />public IAsyncResult BeginLengthyProcedure(int milliseconds, <br />AsyncCallback cb, object s) <br />{ <br />LengthyProcedureAsyncStub stub <br />= new LengthyProcedureAsyncStub(LengthyProcedure); <br />MyState ms = new MyState(); <br />ms.previousState = s; <br />ms.asyncStub = stub; <br />return stub.BeginInvoke(milliseconds, cb, ms); <br />} <br /><br />[ System.Web.Services.WebMethod ] <br />public string EndLengthyProcedure(IAsyncResult call) <br />{ <br />MyState ms = (MyState)call.AsyncState; <br />return ms.asyncStub.EndInvoke(call); <br />} <br />} <br /><!-- 页面内容结束 --><br /><br />原文地址：<a href="http://ewebapp.cnblogs.com/articles/237375.html">http://ewebapp.cnblogs.com/articles/237375.html</a><img src ="http://www.blogjava.net/hopeshared/aggbug/44863.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-05-07 15:18 <a href="http://www.blogjava.net/hopeshared/archive/2006/05/07/44863.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：几种调用WebService的方法</title><link>http://www.blogjava.net/hopeshared/archive/2006/05/07/44860.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Sun, 07 May 2006 07:12:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/05/07/44860.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/44860.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/05/07/44860.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/44860.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/44860.html</trackback:ping><description><![CDATA[1． 在JavaScript中调用WebService <br /><br />&lt;script language="javascript"&gt; <br />function PostRequestData(URL,data){ <br />var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); <br />xmlhttp.Open("POST",URL, false); <br />xmlhttp.SetRequestHeader ("Content-Type","text/xml; charset=utf-8"); <br />xmlhttp.SetRequestHeader ("SOAPAction","http://tempuri.org/myService/test/isNumner"); <br /><br />try { <br />xmlhttp.Send(data); <br />var result = xmlhttp.status; <br />} <br />catch(ex) { <br />return("0" + ex.description + "|" + ex.number); <br />} <br />if(result==200) { <br />return("1" + xmlhttp.responseText); <br />} <br />xmlhttp = null; <br />} <br /><br />function loadit(value){ <br />var url = ''http://localhost/myService/test.asmx''; <br />var data ; <br />var r; <br /><br />data = ''&lt;?xml version="1.0" encoding="utf-8"?&gt;''; <br />data = data + ''&lt;soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"&gt;''; <br />data = data + ''&lt;soap:Body&gt;''; <br />data = data + ''&lt;isNumner xmlns="http://tempuri.org/myService/test"&gt;''; <br />data = data + ''&lt;str&gt;''+value+''&lt;/str&gt;''; <br />data = data + ''&lt;/isNumner&gt;''; <br />data = data + ''&lt;/soap:Body&gt;''; <br />data = data + ''&lt;/soap:Envelope&gt;''; <br /><br />r=PostRequestData(url,data); <br />document.write(r); <br />} <br />loadit(''5''); <br />&lt;/script&gt; <br /><br /><br />还可以使用微软的htc组件来实现，可以到这里下载: <br /><br />http://msdn.microsoft.com/workshop/author/webservice/webservice.htc <br /><br />&lt;script language="javascript"&gt; <br />function timer(){ <br />service.useService("http://localhost/myService/test.asmx?WSDL","test"); <br />service.test.callService(callback,"isNumner",''gdh''); <br />} <br /><br />function callback(res){ <br />if (!res.error) <br />time.innerText=res.value; <br />} <br />&lt;/script&gt; <br /><br />&lt;div id="service" style="behavior:url(webservice.htc)"&gt;&lt;/div&gt; <br />&lt;span id="time"&gt;&lt;/span&gt; <br /><br />2. 在Asp中 <br /><br />&lt;%@LANGUAGE="VBSCRIPT" CODEPAGE="936"%&gt; <br />&lt;% <br />Dim strxml <br />Dim str <br /><br />''定义soap消息 <br /><br />strxml = "&lt;?xml version=''1.0'' encoding=''tf-8''?&gt;" <br />strxml = strxml &amp; "&lt;soap:Envelope xmlns:xsi=''http://www.w3.org/2001/XMLSchema-instance'' xmlns:xsd=''http://www.w3.org/2001/XMLSchema'' xmlns:soap=''http://schemas.xmlsoap.org/soap/envelope/''&gt;" <br />strxml = strxml &amp; "&lt;soap:Body&gt; " <br />strxml = strxml &amp; "&lt;isNumner xmlns=''http://tempuri.org/myService/test''&gt;" <br />strxml = strxml &amp; "&lt;str&gt;4&lt;/str&gt;" <br />strxml = strxml &amp; "&lt;/isNumner&gt;" <br />strxml = strxml &amp; "&lt;/soap:Body&gt;" <br />strxml = strxml &amp; "&lt;/soap:Envelope&gt;" <br /><br />''定义一个XML的文档对象，将手写的或者接受的XML内容转换成XML对象 <br /><br />''set x = createobject("Microsoft.DOMDocument") <br /><br />''初始化XML对象 <br /><br />''将手写的SOAP字符串转换为XML对象 <br /><br />'' x.loadXML strxml <br /><br />''初始化http对象 <br /><br />Set h = createobject( "Microsoft.XMLHTTP") <br /><br />''向指定的URL发送Post消息 <br /><br />h.open "POST", "http://localhost/myService/test.asmx", False <br />h.setRequestHeader "Content-Type", "text/xml" <br />h.setRequestHeader "SOAPAction", "http://tempuri.org/myService/test/isNumner" <br />h.send (strxml) <br />While h.readyState &lt;&gt; 4 <br />Wend <br /><br />''显示返回的XML信息 <br /><br />str = h.responseText <br /><br />''将返回的XML信息解析并且显示返回值 <br /><br />''Set x = createobject("MSXML2.DOMDocument") <br />'' x.loadXML str <br />''str = x.childNodes(1).Text <br />response.write(str) <br />%&gt; <br /><br />3．在.net中 <br /><br />在.net中调用WebService就方便多了，没有必要自己写soap消息了，以上都是用XMLHTTP来发送WebService请求的，在.net只要添加了web引用，会自动为你创建一个代理类。然后使用代理类就像用自己定义的类一样方便。 <br /><br /><br />原文地址：<a href="http://ewebapp.cnblogs.com/articles/237386.html">http://ewebapp.cnblogs.com/articles/237386.html</a><img src ="http://www.blogjava.net/hopeshared/aggbug/44860.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-05-07 15:12 <a href="http://www.blogjava.net/hopeshared/archive/2006/05/07/44860.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转载：使用ActiveBPEL编排、控制Web Services</title><link>http://www.blogjava.net/hopeshared/archive/2006/04/25/42974.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Tue, 25 Apr 2006 03:26:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/04/25/42974.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/42974.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/04/25/42974.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/42974.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/42974.html</trackback:ping><description><![CDATA[
		<a class="fwhere">【2005-11-29 16:04】</a>
		<a class="fwhere">【Daniel Rubio】</a>
		<a class="fwhere">【TechTarget】</a>
		<br />
		<br />
		<a class="f1">  
<div class="guanggao"><span id="contentAdv"></span></div><p>　　在SOA的上下文中设计<a class="bluekey" href="http://www.yesky.com/key/3819/543819.html" target="_blank">WebServices</a>必须处理好一系列问题，包括可重用性和灵活性等。然而，一旦最初的设计是让独立的服务一起以集成的方式出现就会导致另一些需求的出现，其中大多数可以被业务过程执行语言(Business Process Execution Language ，BPEL)来处理。</p><p>　　BPEL是由IBM、Microsoft和BEA在2003年共同发明的。但从诞生尹始，BPEL就得到了Web <a class="bluekey" href="http://www.yesky.com/key/2009/542009.html" target="_blank">services</a>标准的引导。现在，在OASIS的资助下已经升到了2.0版本，有超过35家公司正在参与规划未来标准的方向，它将成为处理Web services编排的标准。</p><p>　　但如何通过BPEL来进行Web services编排呢?一些其它公司把它称为Web services工作流，意思是已经使用基础的Web services协议栈SOAP/WSDL/UDDI。让我们来谈这个问题之前先假设你被派去迁移一个信用卡应用系统并使用到Web services。</p><p>　　由于自身的特性，我们的信用卡应用程序必须与第三方系统交互，并且在同样的过程中有成百的调用。她们基于同样的Web services，这样可以满足不同系统用户的要求。</p><p>　　BPEL就是用来构建这些Web services决策链或工作流的。但是，在更深入探讨它的具体使用之前，你应该认识到一个重要事情或者说必备条件，即BPEL背后的价值:可重用性。</p><p>　　为了尽可能多的构建基于Web services的业务过程并用BPEL把它们粘合到一起，必须使每个独立的服务都达到精确的平衡。使用粗粒度的Web services比使用BPEL创建不同决策链的整体目标更重要，因为它们可能是完整的业务过程。同样的，细粒度的服务不利于重用和构建BPEL工作流。</p><p>　　这个过程本质上与面向对象的设计很类似，即一个对象需要完成足够的工作来证明它的存在才能不被认为是上层调用对象。你应该用同样的方式考虑Web service。Web service 的可重用性是SOA的一个主要原则，这自不必说，而在使用BPEL的时候这一点体现的更加明显。</p><p>　　作为核心，BPEL用XML语法来表达Web service交互，而像声明变量、流控、事务和错误处理等其它事情你可以让另一种语言来负责编排协作。</p><p>　　因为这样也隐含着Web servcies基本的SOAP/WSDL/UDDI方法，因此BPEL要求其自身环境能够执行这些命令，我们称之为BPEL引擎。</p><p>　　现在，BPEL引擎存在着不同的成熟度和复杂性。当SOA领域的一些厂商用其它核心产品例如ESB来紧密集成他们的BPEL引擎时，其他人则在同样的领域创建单独的产品。</p><p>　　为了牢固掌握BPEL，我们通过最中立和不侵权的方法，即一个叫做ActiveBPEL的开源Java BPEL引擎来看看下面的BPEL示例。</p><p>　　ActiveBPEL是一个单独的BPEL引擎，可以在任何Java/J2EE<a class="bluekey" href="http://www.yesky.com/key/2002/592002.html" target="_blank">应用服务</a>器下以Web应用(WAR文件)的形式运转。由于ActiveBPEL属于开源产品，所以它与事实上的Java/J2EE开源Tomcat、Apache's Web services框架Axis以及流行的构建工具<a class="bluekey" href="http://www.yesky.com/key/337/595337.html" target="_blank">Ant</a>紧密的结合在一起。</p><p>　　这些特点使ActiveBPEL成为开发BPEL功能的优秀产品，因为它基于已经被熟知并已获得应用的技术。如果你的机器上还没有这些包，可以下载它们并按照基本安装命令进行安装。我们不会谈论配置问题，因为本文的目的是让你能更快的使用BPEL。</p><p>　　让我们从高层审视ActiveBPEL编排的过程。你的银行系统需要执行一个信用卡应用过程，并根据一系列详细的决策链返回一个简单的"yes" or a "no"。这些决策链需要拿到贷款数额、某个律师的信用历史或支出地点，所有这一切都是通过调用单独的Web services来完成的。</p><p>　　根据市场条件或银行政策，这个业务过程将很可能改变信用卡应用的验证方式。用上层Web services返回结果是相当不灵活的方法，因为它使得每次修改Web services之后都要继续修改业务逻辑。另一方面，让BPEL过程来编排应用逻辑会给我们带来两大好处。</p><p>　　BPEL的XML语法授予我们一种指令级别，通过它可以改变应用的工作流而不必在现场业务逻辑之后再修改。这为我们以后在更复杂的工作流情况下重用某套核心Web services提供了方便。</p><p>　　假设我们已经为我们的核心Web servcies完成了最后的设计。我们有两个Web services，它们组成了一个approver和一个assessor。初始分析显示这两个服务都能很容易地被其他信用演进过程重用。因此，现在来看BPEL的伪代码并看看为创建BPEL-XML语法我们需要做什么。</p><p><font style="BACKGROUND-COLOR: #dddddd" face="Verdana">if (creditapplication &lt; <a class="bluekey" href="http://www.yesky.com/key/1081/571081.html" target="_blank">$1</a>0,000) {<br />        if (assessor returns "lowrisk")<br />                return "yes"<br />        else<br />                return approver response<br />}<br />else<br />        return approver response<br /><br /></font></p><p>　　首先是检查信用卡应用的数额。如果它的量超过$10,000，我们就把输入的数据转交给approver Web service以获得一个响应。反之，如果数量在$10,000以下，我们就先调用assessor Web service，让它返回一个回答，如果响应是"lowrisk"，那么应用程序立即被证实。否则我们就需要进一步调用approver Web service。</p><p>　　这是一个很直接的业务过程，很明显的展示了BPEL的强大，达到了为我们的核心Web services编排不同调用场景的目的。现在，让我们来看看实际的BPEL-XML语法。</p><p><font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;?xml version="1.0" encoding="UTF-8"?&gt; <br />&lt;process name="loanApprovalProcess" suppressJoinFailure="yes" <br />targetNamespace="http://acme.com/loanprocessing" <br />xmlns="http://schemas.xmlsoap.org/ws/2003/03/business-process/" <br />xmlns:apns="http://tempuri.org/services/loanapprover"<br />xmlns:asns="http://tempuri.org/services/loanassessor" <br />xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/" <br />xmlns:lns="http://loans.org/wsdl/loan-approval" xmlns:loandef="http://tempuri.org/services/loandefinitions"<br /> xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt; <br />   &lt;partnerLinks&gt;<br />      &lt;partnerLink myRole="approver" name="customer" partnerLinkType="lns:loanApprovalLinkType"/&gt;<br />      &lt;partnerLink name="approver" partnerLinkType="lns:loanApprovalLinkType" partnerRole="approver"/&gt;<br />      &lt;partnerLink name="assessor" partnerLinkType="lns:riskAssessmentLinkType" partnerRole="assessor"/&gt;<br />   &lt;/partnerLinks&gt;<br />   &lt;variables&gt;<br />      &lt;variable messageType="loandef:creditInformationMessage" name="request"/&gt;<br />      &lt;variable messageType="asns:riskAssessmentMessage" name="riskAssessment"/&gt;<br />      &lt;variable messageType="apns:approvalMessage" name="approvalInfo"/&gt;<br />      &lt;variable messageType="loandef:loanRequestErrorMessage" name="error"/&gt;<br />   &lt;/variables&gt;<br />   &lt;faultHandlers&gt;<br />      &lt;catch faultName="apns:loanProcessFault" faultVariable="error"&gt;<br />         &lt;reply faultName="apns:loanProcessFault" operation="approve" partnerLink="customer" <br />       portType="apns:loanApprovalPT" variable="error"/&gt;<br />      &lt;/catch&gt;<br />   &lt;/faultHandlers&gt;<br />   &lt;flow&gt;<br />      &lt;links&gt;<br />         &lt;link name="receive-to-approval"/&gt; <br />         &lt;link name="receive-to-assess"/&gt;<br />         &lt;link name="approval-to-reply"/&gt;<br />         &lt;link name="assess-to-setMessage"/&gt;<br />        &lt;link name="assess-to-approval"/&gt;<br />          &lt;link name="setMessage-to-reply"/&gt;<br />      &lt;/links&gt;<br />      &lt;receive createInstance="yes" name="receive1" operation="approve" partnerLink="customer" <br />      portType="apns:loanApprovalPT" variable="request"&gt;<br />         &lt;source linkName="receive-to-approval" transitionCondition="bpws:getVariableData('request', <br />         'amount')&gt;=10000"/&gt;<br />         &lt;source linkName="receive-to-assess" transitionCondition="bpws:getVariableData('request', <br />         'amount')&lt;10000"/&gt;<br />      &lt;/receive&gt;<br />      &lt;invoke inputVariable="request" name="invokeapprover" operation="approve" <br />      outputVariable="approvalInfo" partnerLink="approver" <br />     portType="apns:loanApprovalPT"&gt;<br />         &lt;target linkName="receive-to-approval"/&gt;<br />         &lt;target linkName="assess-to-approval"/&gt;<br />         &lt;source linkName="approval-to-reply"/&gt;<br />      &lt;/invoke&gt;<br />      &lt;invoke inputVariable="request" name="invokeAssessor" operation="check" outputVariable="riskAssessment"<br />     partnerLink="assessor" <br />     portType="asns:riskAssessmentPT"&gt;<br />         &lt;target linkName="receive-to-assess"/&gt;<br />         &lt;source linkName="assess-to-setMessage" transitionCondition=<br />         "bpws:getVariableData('riskAssessment', 'risk')='low'"/&gt;<br />         &lt;source linkName="assess-to-approval" transitionCondition="bpws:getVariableData<br />        ('riskAssessment', 'risk')!='low'"/&gt;<br />      &lt;/invoke&gt;<br />      &lt;reply name="reply" operation="approve" partnerLink="customer" portType="apns:loanApprovalPT" <br />      variable="approvalInfo"&gt;<br />         &lt;target linkName="approval-to-reply"/&gt;<br />         &lt;target linkName="setMessage-to-reply"/&gt;<br />      &lt;/reply&gt;<br />      &lt;assign name="assign"&gt;<br />         &lt;target linkName="assess-to-setMessage"/&gt;<br />         &lt;source linkName="setMessage-to-reply"/&gt;<br />         &lt;copy&gt;<br />            &lt;from expression="'approved'"/&gt;<br />            &lt;to part="accept" variable="approvalInfo"/&gt;<br />         &lt;/copy&gt;<br />      &lt;/assign&gt;<br />   &lt;/flow&gt;<br />&lt;/process&gt;</font></p><p>　　注意BPEL的元素有&lt;partnerLink&gt;, &lt;variable&gt;, &lt;faultHandler&gt;, &lt;flow&gt;, &gt;target&gt;等等。继续讲解BPEL语法的含义超出了本问的范围，但如果你跟进的话你就能发现在伪代码中有同样的模式。还要注意到，很多BPEL过程是使用特殊的编辑器创建的，这样可以避免手写XML时的错误。</p><p>　　在看过实际的BPEL过程后，你大概会问这跟实际的Web servcies的UPI或WSDL描述符有什么关系。在ActiveBPEL中，它需要你定义一个过程部署描述符(Process Deployment Descriptor)文件来告诉BPEL引擎你的过程。下面就是这个PDD文件。</p><p><font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;process location="bpel/loanapproval.bpel" name="bpelns:loanApprovalProcess" <br />xmlns="http://www.active-endpoints.com/schemas/deploy/pdd.xsd" <br />xmlns:bpelns="http://acme.com/loanprocessing" <br />xmlns:wsa="http://schemas.xmlsoap.org/ws/2003/03/addressing"&gt;<br />  &lt;!-- Partner Link for inbound request from customer --&gt;<br />  &lt;partnerLinks&gt;<br />    &lt;partnerLink name="customer"&gt;<br />      &lt;myRole allowedRoles="" binding="RPC" service="ApproveLoan"/&gt;<br />    &lt;/partnerLink&gt;<br />    &lt;!-- Partner Link for outbound request to delegate approver --&gt;<br />    &lt;partnerLink name="approver"&gt;<br />      &lt;partnerRole endpointReference="static"&gt;<br /> &lt;wsa:EndpointReference xmlns:approver="http://tempuri.org/services/loanapprover"&gt;<br />   &lt;wsa:Address&gt;approver:anyURI&lt;/wsa:Address&gt;<br />   &lt;wsa:ServiceName PortName="SOAPPort"&gt;approver:LoanApprover&lt;/wsa:ServiceName&gt;<br /> &lt;/wsa:EndpointReference&gt;<br />      &lt;/partnerRole&gt;<br />    &lt;/partnerLink&gt;<br />    &lt;!-- Partner Link for outbound request to risk assessment process --&gt;<br />    &lt;partnerLink name="assessor"&gt;<br />      &lt;partnerRole endpointReference="static"&gt;<br /> &lt;wsa:EndpointReference xmlns:assessor="http://tempuri.org/services/loanassessor"&gt;<br />   &lt;wsa:Address&gt;assessor:anyURI&lt;/wsa:Address&gt;<br />   &lt;wsa:ServiceName PortName="SOAPPort"&gt;assessor:LoanAssessor&lt;/wsa:ServiceName&gt;<br /> &lt;/wsa:EndpointReference&gt;<br />      &lt;/partnerRole&gt;<br />    &lt;/partnerLink&gt;<br />  &lt;/partnerLinks&gt;<br />  &lt;wsdlReferences&gt;<br />    &lt;wsdl location="project:/wsdl/loandefinitions.wsdl" <br />    namespace="http://tempuri.org/services/loandefinitions"/&gt;<br />    &lt;wsdl location="project:/wsdl/loanapproval.wsdl" <br />    namespace="http://loans.org/wsdl/loan-approval"/&gt;<br />    &lt;wsdl location="project:/wsdl/loanapprover.wsdl" <br />    namespace="http://tempuri.org/services/loanapprover"/&gt;<br />    &lt;wsdl location="project:/wsdl/loanassessor.wsdl" <br />   namespace="http://tempuri.org/services/loanassessor"/&gt;<br />  &lt;/wsdlReferences&gt;<br />&lt;/process&gt;</font></p><p>　　注意这个描述符是如何与刚才的BPEL过程协作的。它声明了&lt;process location="bpel/loanapproval.bpel"&gt;来为每个&lt;partnerLink&gt;定义物理地址，并声明了多个WSDL描述符。</p><p>　　重要的是，这个文件与我们的Web services一起绑定到BPEL过程。通过上面的讲解，你应该能意识到Web services WSDL文件组成了任何BPEL过程的主体。</p><p>　　前面的因为WSDL定义了一个Web service的方法、消息和特征。而一个BPEL过程则通过它的引擎使得丰富的使用信息被包含在这些标准Web services文件中，以此来编排需要的业务过程。</p><p>　　本文通过ActiveBPEL让大家了解BPEL。如果你已经看过Loan Approval Application for ActiveBPEL 并知道它的内部工作方式，那么现在就能体会到BPEL对给你的Web services和SOA开发所带来的价值。</p><p><br /></p></a>
<img src ="http://www.blogjava.net/hopeshared/aggbug/42974.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-04-25 11:26 <a href="http://www.blogjava.net/hopeshared/archive/2006/04/25/42974.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转载的BPEL&amp;BPEL的几个基本问题，和我的一点想法</title><link>http://www.blogjava.net/hopeshared/archive/2006/04/25/42967.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Tue, 25 Apr 2006 03:05:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/04/25/42967.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/42967.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/04/25/42967.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/42967.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/42967.html</trackback:ping><description><![CDATA[
		<strong>Q:什么是 BPEL？<br /></strong>A: BPEL是一门用于自动化业务流程的形式规约语言。 用XML文档写入BPEL中的流程能在Web 服务之间以标准化的交互方式得到精心组织。这些流程能够在任何一个符合BPEL规范的平台或产品上执行。 所以，通过允许顾客们在各种各样的创作工具和执行平台之间移动这些流程，BPEL使得他们保护了他们在流程自动化上的投资。尽管以前想使业务流程定义标准化，但BPEL已经引起了史无前例的兴趣，而且它最早在软件供应商中获得大量认可。 
<p><b>Q: BPEL、WSBPEL和 BPEL4WS之间的区别是什么?</b><br />A: 除了历史参考文献不同外，没有什么其他的不同。这些名字都涉及到相同的未决标准。“BPEL4WS”是起初规范的名字，它由BEA、IBM和Microsoft编写和公布的。“WSBPEL”目前是规范和未决标准的名称。当这个规范提交到OASIS时,出于Web服务相关标准的努力，按照OASIS命名方案更换了这个名字。尽管如此，大部分团体仍然简单地称这个标准为“BPEL”。 </p><p><b>Q: 什么是 BPELJ？</b><br />A: BPELJ 是BPEL和Java 语言的组合，它允许一起运用这两种编程语言来构建完整的业务流程应用程序。通过允许BPEL和Java一起工作， BPELJ使得每种语言可以做它最擅长的事。BPELJ优于BPEL，但没有它那么有竞争力。</p><p><b>Q:如何把BPELJ和 BPEL联系起来，它们之间区别在哪里？</b><br />A: BPEL基本上向编程发展，它支持业务处理流程的逻辑。这些业务处理流程是独立的应用程序，这些应用使用Web服务作为实现业务功能的活动。BPEL 不会成为一门通用的编程语言。然而，有人认为BPEL将和用来实现业务功能的其他语言（少部分的编程）结合起来。为了方便BPEL和Java 结合起来，BPELJ对BPEL做了一些小的改动并且做了一些扩展。</p><p><b>Q: BPEL不是针对业务分析员吗? 如果是，为什么把Java加进来?</b><br />A: 有这么一个普遍的误解，那就是BPEL想达到非程序设计人员或者所谓的“业务分析员”也能使用的程度。这个错误的概念部分根源于市场上许多针对于这组用户的业务流程管理工具这样的一个事实。无可置疑，工具供应商为构建BPEL和BPELJ流程提供了广泛的可视化接口，但是语言本身的目的是为了开发人员。</p><p><b>Q: BPELJ如何工作？</b><br />A: 通过允许在BPEL流程定义中包含Java代码段（称为Java片断），BPELJ使得Java 和BPEL能够相互协作。 </p><p><b>Q: 难道不应该考虑允许使用任何语言（C#、JavaScript和Java等）来设计代码片断吗？</b><br />A: 这个片断背后想法是有代表性，我们希望它能用于许多不同的语言。然而，要集成BPEL和一门特定的语言包含的不仅仅是用XML包装目标语言。集成变量绑定、事务管理、调用路径等问题必须周全地定义，然而，每种语言是用不同的方法解决这些问题，对所有语言进行统一的绑定是不现实的。所以， BPELJ集中解决 BPEL 和 Java的这些集成问题。我们期待着解决其他的语言的集成问题 。 </p><p><b>Q: 难道BPELJ 没违反“ BPEL中活动是Web服务，数据是XML,数据结构用XML架构描述”这一原则吗？</b><br />A: 并不是世界上所有的服务都是Web服务，它们也不应该是。用J2EE更适合紧密耦合的系统，在这种系统中，容器提供的功能如安全和事务是特别有价值的。那些把业务逻辑部署成J2EE组件的人员应该能够在业务流程中充分利用这些组件，BPEL是描述这个过程最好的一门语言。<br />一些人争论说在程序片断中用Java来完成少量计算和数据操作非常合适，但是应该通过XML/Web服务视图强制所有服务调用。这是一个特别站不住脚的观点。如果您有一个用Java代码片断写的流程，很明显，有一个Java开发人员参与创建这个流程。<br />这意味着您可能有下面的设想：有一个开发人员熟悉用Java调用组件，他想用Java操纵组件的输入和输出。迫使那个人把所有的调用看成好像是调用Web 服务一样，这会产生一层混乱，阻止考虑业务逻辑。 <br /><br /><br />原文地址：<a href="http://dev2dev.bea.com.cn/techdoc/2004120205.html">http://dev2dev.bea.com.cn/techdoc/2004120205.html</a><br /><br /><br />尽管我知道了bpel的理论，但是仍然觉得写一个bpel挺麻烦的。尽管有一些图形化的编辑工具，但是仍然觉得并不好用，可能是我对bpel还是不熟悉的缘故吧<br /><br />但是，我可以写一个jave类，在这个类中用各个方法描述出了各个web service的组合调用关系。现在我要做的，就是找一个bpel编辑器和一个bpel服务器来将这个java类的逻辑变成bpel，然后运行之<br /><br /><font color="#ff9900">为什么没有人将这个步骤作成自动化的呢</font>？？？是因为没有必要还是因为别的什么？？</p><img src ="http://www.blogjava.net/hopeshared/aggbug/42967.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-04-25 11:05 <a href="http://www.blogjava.net/hopeshared/archive/2006/04/25/42967.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转载：ActiveBPEL引擎------安装，配置</title><link>http://www.blogjava.net/hopeshared/archive/2006/04/25/42956.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Tue, 25 Apr 2006 02:18:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/04/25/42956.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/42956.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/04/25/42956.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/42956.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/42956.html</trackback:ping><description><![CDATA[
		<p>本文描述如何安装ActiveBPEL引擎.</p>
		<p> </p>
		<br />
		<p>1.要求：</p>
		<p>ActiveBPEL引擎需要一个servlet容器。安装脚本使用了<font size="+0">CATALINA_HOME环境变量。另外它可以在任何标准servlet容器下运行。<br /><br />2.安装：<br />运行安装脚本文件：install.bat(Windows)或者是install.sh(Unix).它把需要的lib拷贝到CATALINA_HOME/shared/lib下，并且创建一个$CATALINA_HOME/bpr,这个目录是放置.bpr文件的地方。<br /><br />修改引擎配置文件：<br />服务启动时候包含一下参数，他们放在aeEngineConfig.xml文件中，你可以在$CATALINA_HOME/bpr找到它。你可以通过<a href="http://localhost:8080/BpelAdmin/config.jsp">http://localhost:8080/BpelAdmin/config.jsp</a> 修改。<br /></font></p>
		<p>
				<font size="+0">3.发布:</font>
		</p>
		<p>
				<font size="+0">参看专门的文章：发布BPEL。<br />一旦引擎启动，在你发布你的BPEL后，引擎会知道读取对应的.bpr文件。<br /><br />4.启动引擎：</font>
		</p>
		<font size="+0">
				<p>要启动引擎，启动你的servlet引擎即可，对于Tomcat：</p>
				<p>Windows:</p>
				<pre style="MARGIN-BOTTOM: 0px">C:\activebpel&gt; %CATALINA_HOME%\bin\startup.bat</pre>
				<p>Unix:</p>
				<pre style="MARGIN-BOTTOM: 0px">activebpel% $CATALINA_HOME/bin/startup.sh</pre>
				<p>5.引擎状态信息：<br />当servlet引擎运行的时候，有两个web页面可以查看当前的服务的信息：Axis web服务列表，和ActiveBPEL引擎管理页面。</p>
				<p>Axis web服务列表<br />这个页面在<a href="http://localhost:8080/active-bpel/services">http://localhost:8080/active-bpel/services</a> 是Axis生成的。它列出了现有的服务。这是和本引擎独立的。引擎只是把web服务交给Axis去发布。详细知识请看我的Axis的相关文章。</p>
				<p>ActiveBPEL 引擎管理<br />页面在：<a href="http://localhost:8080/BpelAdmin/">http://localhost:8080/BpelAdmin/</a> 在这个页面中，你可以修改一下配置参数，还有在线帮助。可以看到发布的BEPL的一些信息。<br />点击Deployed Processes可以查看已经发布的BPEL列表。<br />点击Active Processes查看激活的BPEL.<br />点击Receive Queue查看Receive Queue.</p>
				<p>Debug</p>
				<p>日志在$CATALINA_HOME/logs 你可以查看。<br /><br /><br />原文地址：<a href="http://robertpi.blogchina.com/421320.html">http://robertpi.blogchina.com/421320.html</a></p>
		</font>
<img src ="http://www.blogjava.net/hopeshared/aggbug/42956.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-04-25 10:18 <a href="http://www.blogjava.net/hopeshared/archive/2006/04/25/42956.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转载：ActiveBPEL------发布BPEL Processes</title><link>http://www.blogjava.net/hopeshared/archive/2006/04/25/42957.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Tue, 25 Apr 2006 02:18:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/04/25/42957.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/42957.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/04/25/42957.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/42957.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/42957.html</trackback:ping><description><![CDATA[
		<p>本文介绍如何发布一个BPEL到一个ActiveBPEL引擎。</p>
		<p> </p>
		<br />
		<p>要发布一个BPEL process,你必须创建，安装一个发布文件来包含你的BPEL文件。一般使用jar。</p>
		<p>发布你的BPEL Process</p>
		<p>发布一个BPEL process 调用创建一个发布文件。（一个jar但是使用.bpr为后缀）并且拷贝到你的servlet容器中。要创建这个文件，你必须把你的文件用特殊的目录结构组织起来，创建一个或者2个配置文件。</p>
		<p>首先创建一个文件夹，这个例子中我们命名为mybpel.创建以下子文件夹：</p>
		<li>
				<font size="+0">bpel</font>
		</li>
		<li>
				<font size="+0">META-INF</font>
		</li>
		<li>
				<font size="+0">wsdl</font>
		</li>
		<li>
				<font size="+0">partners</font> (可选) <br />ActiveBPEL 用到的文件格式可以在我们的另外的文章中有详细说明。作为一个例子，我们假设你有一个BPEL为：my_process.bpel和两个WSDL 文件:service1.wsdl和service2.wsdl.<br />你的文件结构应该是： 
<p><img src="http://www.activebpel.org/images/deploy_dir_struct.jpg" border="0" /></p><p>partners文件夹只有你有.pdef文件才需要。</p><p>使用这个文件结构，创建一个jar文件，然后拷贝到servlet容器中。使用下面的命令：</p><p>Windows:</p><pre style="MARGIN-BOTTOM: 0px">C:\&gt; cd mybpel
C:\mybpel&gt; jar cf mybpel.bpr *.pdd META-INF bpel partners wsdl
C:\mybpel&gt; copy mybpel.bpr $CATALINA_HOME/bpr</pre><p>Unix:</p><pre style="MARGIN-BOTTOM: 0px">% cd mybpel
% jar cf mybpel.bpr *.pdd META-INF bpel partners wsdl
% cp mybpel.bpr $CATALINA_HOME/bpr</pre><pre style="MARGIN-BOTTOM: 0px">你的WSDL文件可以是远程的，但是要写到.pdd中。</pre><pre style="MARGIN-BOTTOM: 0px">如果现在引擎在运行，它马上会发现新的.bpr文件然后自动读取它。你的BPEL process就可以使用了。</pre><pre style="MARGIN-BOTTOM: 0px"> </pre></li>
		<pre style="MARGIN-BOTTOM: 0px">原文地址：<a href="http://robertpi.blogchina.com/422342.html">http://robertpi.blogchina.com/422342.html</a></pre>
<img src ="http://www.blogjava.net/hopeshared/aggbug/42957.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-04-25 10:18 <a href="http://www.blogjava.net/hopeshared/archive/2006/04/25/42957.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转载：Web 服务编排实践</title><link>http://www.blogjava.net/hopeshared/archive/2006/04/24/42789.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Mon, 24 Apr 2006 02:41:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/04/24/42789.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/42789.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/04/24/42789.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/42789.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/42789.html</trackback:ping><description><![CDATA[
		<dd class="ArticleInfo">
				<a class="fwhere">【2005-09-20 14:38】</a>
				<a class="fwhere">【Jerome Josephraj】</a>
				<a class="fwhere">【developerWorks中国】</a>
				<br />
				<br />
				<br />
				<span id="LblContent">
						<p>
						</p>
						<p>
								<a class="f1">
								</a>
						</p>
						<div class="guanggao">
								<span id="contentAdv">
								</span>
						</div>
						<p>　　由于越来越多的公司正投身到 Web 服务的浪潮中，研究者们预测 Web 服务所提供的不仅仅是单端流程。一般来说，复杂应用程序在重要领域日益增多，越来越多的公司将 Web 服务作为复杂流程互动的一部分,<a class="bluekey" href="http://www.yesky.com/key/3012/13012.html" target="_blank">WSC</a> 正好顺应这一趋势。</p>
						<p>　　WSCI 是基于 <a class="bluekey" href="http://www.yesky.com/key/847/847.html" target="_blank">XML</a> 的接口描述语言，它一般与 <a class="bluekey" href="http://www.yesky.com/key/3664/18664.html" target="_blank">WSDL</a> 结合在一起使用。它的目的是通过 Web 服务的力量使公司创建出反映当今动态的、持续变化的业务需求的业务流程。公司可以将他们的应用程序软件和资源作为 Web 服务，以便其它公司能够找到并将其应用到他们自己的业务流程中。创建业务处理过程不仅需要对所有组件的协作模式有一个清晰的定义，也需要一个描述标准的业务到业务(B2B)互动的方法。</p>
						<p>　　下面部分说明了一个简单在线股票交易公司如何使用 Web 服务和 WSDL 发布服务，这种方法的缺点及 WSC 如何克服这些缺点。本文讨论的范围是解释 WSC，提供 WSC 的价值信息以及学习它更多的特性。</p>
						<p>　　<strong>使用 Web 服务的在线交易公司</strong></p>
						<p>　　通过这个简单的股票交易例子，可以很好的解释 WSC 的要求和角色。为了简洁，我们大致概述涉及到的大多数行为。我并不是要讨论买卖股票的所有步骤，因为这不是本文的讨论范围。而是会给出一个简单的股票交易应用程序样例。下面的图 1 描述了一个使用在线 Web 应用程序进行股票买卖的简单及一步一步的业务流程。</p>
						<p>
								<img src="http://searchwebservices.techtarget.com.cn/imagelist/05/09/6142z0on25h2.jpg" border="0" />
						</p>
						<p>　　图 1. 股票交易业务流程</p>
						<p>　　<strong>实例</strong></p>
						<p>　　在线股票交易应用程序从第三方服务(例如 xmethods<a class="bluekey" href="http://www.yesky.com/key/3532/8532.html" target="_blank">.net</a>)获得股票的详细信息, 并将它提供给用户。 用户可能选他或她所感兴趣的股票，并且需要更多的详细信息。在线股票公司使用其中一个第三方提供的 Web 服务来获得详细信息。</p>
						<p>　　一旦用户决定要买哪种股票，他或她就会下购买订单。在线股票应用程序通过其内部流程从股票市场买到股票。之后，在线交易应用程序需要用户确认购买订单，并且为用户强制设置确认订单超时时间。如果一分钟没有确认订单，系统则会向用户发送超时信息。</p>
						<p>　　一旦订单被用户确认后，在线交易应用程序从用户帐户中扣减必要的费用。要实现这一操作，它会使用现存的一个第三方 Web 服务。使用一个 Web 服务来验证信用卡，使用第二个 Web 服务来扣减费用。 这两步都必须处理为一个逻辑工作单元(即事务)，其中任何一个服务的失败都会向用户发送失败的信息。如果信用卡被成功验证，并且这些钱也成功地从用户帐户中转出， 在线股票交易应用程序就会从市场购买所需的股票数。用户可以下多个购买订单，并且每一个订单将会作为一个单独的逻辑单元来处理。</p>
						<p>　　卖方的订单步骤和买方的订单步骤是相似的。用户下订单并在交货时确认。一旦确认了，在线应用程序下卖方订单，在证实用户帐单详细信息后从用户帐户划帐。</p>
						<p>　　为了增加业务渠道，并与其它系统进行协作操作，在线交易公司发布了一个 买/卖 Web 服务应用程序作为 。在一个简单的 Web 服务例子中，您可以<a class="bluekey" href="http://www.yesky.com/key/4883/14883.html" target="_blank">映射</a>上面介绍的步骤到一个 WSDL 文件里。用户使用一些 Web 服务软件，例如 Microsoft VBA 编辑器，或者使用外部应用程序调用 Web 服务，从而调用 WSDL 操作来设置买方或卖方订单。以下链接地址可以说明如何在 VBA 中实现这个任务。 上面的图 1描述了业务过程之间的 WSDL 操作及图形.</p>
						<p>
								<a class="f1">
								</a>
						</p>
						<div class="guanggao">
								<span id="contentAdv">
								</span>
						</div>
						<p>
						</p>
						<p>　　<strong>WSDL 的缺点</strong></p>
						<p>　　一个定义得很好的买卖股票 Web 服务运行的前提是所有过程都是自动的，换句话说，它们彼此不分享任何状态。 但是在这种情况下，WSDL 自身解决了业务整合过程中的一些核心需求，例如:</p>
						<p>　　<strong>流程顺序</strong>使用买/卖 Web 服务的消费者，能以任何顺序调用这些操作。例如，服务消费者可以在调用 placeBuyOrder 或者 placeSellOrder 操作之前调用现金转移操作。WSDL 不会禁止以任何顺序调用操作，使用 WSDL 的 Web 服务应用程序必须在上面的逻辑应用中迎合这一特点。</p>
						<p>　　<strong>消息相关性</strong>相关性是发送信息给别人，期望收到回复，并在返回的消息实例中使用通用数据和发送消息实例相连(或者说，相关联)时，所涉及的一个简单理念。在业务过程的互动中，理解和描述出消息实例间的相关性是非常重要的。 WSDL 不具有关联消息实例的能力。换句话说，它不会保留这些操作的状态。 在一个典型的业务整合流程中，流程之间能分享状态以便提供一个相关联的流程。所有使用 WSDL 发布的操作都是无状态的，它在消息实例间没有相关性。</p>
						<p>　　在本例中，当用户把下订单作为下一步操作时，Web 服务应用程序要求用户确认订单。用户也许决定改变股票数量或是改变购买时间。因为订单被修改了，他或她就要再次下购买订单。这种相互间来回的会话可能会发生几次，用户可能会下几次订单，或者说，用户与 Web 服务应用程序间发起多次对话。但是，使用 WSDL 的 Web 服务没有关联消息实例的能力。</p>
						<p>　　<strong>工作单元(事务)</strong>为了让 Web 服务成为长信息交换的一部分，清楚地定义信息交换什么时候开始触发，什么时候考虑终止，考虑哪个部分以事务方式管理，这些问题都是很重要的。</p>
						<p>　　本例中，placeBuyOrder, confirmBuyOrder 这些操作和 debit money 流程必须在一个单元中完成。Web 服务必须成功执行这三个操作，或者必须在执行前把这些操作恢复到一致状态，您不能把 WSDL 中发布的操作来进行分布式事务。在 WSDL 中，事务的范围是限制在单个的操作中，不能超越一个操作的范围。</p>
						<p>　　<strong>异常处理</strong>虽然 WSDL 使用错误代码来抛出异常，但是它不能处理一些人工模型，比如检查特殊消息，声明超时异常，或者声明仅用于 Web 服务一些局部操作但不是全程服务的异常。</p>
						<p>　　在互动流程中有一个合适的异常人工模型是很有必要的。本例中，如果用户确认买卖订单的时间超过一分钟，Web 服务就会发出超时异常。</p>
						<p>　　<strong>上下文</strong>在业务互动流程中，在参与的流程间建立一个上下文环境来共享信息是很重要的。这些信息可能是一系列的声明、异常事件、或是事务特性。WSDL 不会为流程提供任何可以在上下文环境中处理的特征。</p>
						<p>
								<img style="WIDTH: 489px; HEIGHT: 264px" height="309" src="http://searchwebservices.techtarget.com.cn/imagelist/05/09/eiv8h72ld9v6.jpg" width="581" border="0" />
						</p>
						<p>　　图 2. 使用 WSDL 的股票交易</p>
						<p>　　<strong>WSC 如何提供帮助</strong></p>
						<p>　　WSC 帮助解决以上提到的基于 WSDL 及扩展功能的业务整合流程中的所有缺点。下节解释了 WSCI 如何处理这些问题:</p>
						<p>　　<strong>上下文</strong></p>
						<p>　　要集成一些服务来创建复杂的业务服务，这些服务需要共享上下文环境信息。上下文元素组成一个环境以执行活动。同时，上下文元素也确保一系列的活动作为一个组来执行，这些有上下文环境信息的所有活动能共享声明、异常事件及事务属性。</p>
						<p>　　上下文定义有局部属性和局部过程定义。局部属性只对在当前环境下执行的活动有效。局部过程定义指定在当前环境下实例化的过程。为了调用或产生局部过程，必须是从本地过程定义可见的上下文中。<br /><br /><a class="f1"> </a></p>
						<div class="guanggao">
								<span id="contentAdv">
								</span>
						</div>
						<p>
						</p>
						<p>　　在下面的 清单 1 中, 局部过程定义在买卖股票中有不同的上下文。如果在购买库存的过程中发生错误，它仅限于买的过程。例如，如果环境没有定义，买的过程中发生的错误会拒绝用户使用 Web 服务，而不是发送状态给 placeSellOrder 。以下给出 WSCI 定义的一部分:</p>
						<p>　　清单 1. 上下文元素示例</p>
						<p>
								<font style="BACKGROUND-COLOR: #dddddd">　</font>
								<font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;context&gt;<br /> &lt;foreach select="ns1:arrayOfStockList/leg[position()&gt;1]"&gt;<br />  &lt;process name = "PlaceBuyOrder" instantiation = "other"&gt;<br />   &lt;action name = "PlaceBuyOrder" <br />     role= "tns:trader"<br />     operation= "tns:placeBuyOrder"&gt;<br />   &lt;/action&gt;<br />  &lt;/process&gt;<br /> &lt;/foreach&gt;<br /> &lt;process name = "ConfirmBuyOrder" instantiation = "other"&gt;<br />  &lt;action name = "ConfirmBuyOrder"<br />    role= "tns:trader"<br />    operation= "tns:confirmBuyOrder" &gt;<br />   &lt;correlate correlation = <br />   "defs:buyStockCorrelation" instantiation= "true" /&gt;<br />  &lt;/action&gt;<br />  &lt;exception&gt;<br />   &lt;onTimeout property = <br />   "tns:confirmationTime"<br />     type= "duration"<br />     reference="tns:PlaceBuyOrder@end"&gt;<br />     &lt;compensate transaction = "tns:reverseBuyOrders"/&gt;<br />   &lt;/onTimeout&gt;<br />  &lt;/exception&gt;<br /> &lt;/process&gt;<br /> &lt;process name="transferMoney" instantiation="other"&gt;<br />  &lt;action name = "cashTransaction"<br />    role= "tns:trader"<br />    operation= "tns:debitMoney" &gt;<br />  &lt;/action&gt;<br /> &lt;/process&gt;<br /> &lt;exception&gt;<br />  &lt;onMessage&gt;<br />   &lt;action name = "reverseBuyOrders"<br />    role= "tns:trader"<br />    operation= "tns:cancelBuyOrder"&gt;<br />   &lt;/action&gt;<br />   &lt;fault code = "tns:creditCardTxFaultCode"/&gt;<br />  &lt;/onMessage&gt;<br /> &lt;/exception&gt;<br />&lt;/context&gt;</font>
						</p>
						<p>　　<strong>流程顺序</strong></p>
						<p>　　为了顺序地调用更多的微小业务流程，并在全局业务流程下将它们组合在一起， WSC 使用了接口元素顺序。如它的名称所示，它能确保系统顺序调用流程。当服务消费者要买股票时，在买的流程之前接口元素调用现金转移操作。这是通过在顺序元素中定义所有操作的顺序来完成的, 如以下清单 2 所示。</p>
						<p>　　清单 2. 顺序元素示例</p>
						<p>
								<font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;sequence&gt;<br />        &lt;!-- Web service Choreography Sequence --&gt;<br /> &lt;operation name="placeBuyOrder"&gt;<br />  &lt;input message="buySellOrderRequest"/&gt;<br />  &lt;output message="buySellOrderResponse"/&gt;<br /> &lt;/operation&gt;<br /> &lt;operation name="confirmBuyOrder"&gt;<br />  &lt;input message="buySellOrderResponse"/&gt;<br />  &lt;output message="buySellOrderResponse"/&gt;<br /> &lt;/operation&gt;<br /> &lt;operation name="debitMoney"&gt;<br />  &lt;input message="creditCardDetails"/&gt;<br />  &lt;output message="debitMoneyResponse"/&gt;<br /> &lt;/operation&gt;<br />&lt;/sequence&gt;</font>
						</p>
						<p>　　<strong>信息相关性</strong></p>
						<p>　　在 WSCS 中，当信息传到服务时，就暗示着可以建立实例。WSC 建立的实例可以用数据信息中的关键字识别。本例中，将 confirmBuyOrder 和 placeBuyOrder 过程建立关联是很重要的，因为每个过程都可能在之前的实例中发生. 当确认订单发送到服务消费者时，消费者可能会修改订单(例如，客户可能会因为价格改变修改数量)，并再次下购买订单。这样的对话可能在服务消费者与 Web 服务单发生几次。</p>
						<p>
								<a class="f1"> </a>
						</p>
						<div class="guanggao">
								<span id="contentAdv">
								</span>
						</div>
						<p>
						</p>
						<p>　　服务消费者可能下不只一份购买订单，也会触发不只一次对话。您必须识别每一次对话。这样就会用到 placeOrderId。提供了这种机制，服务消费者想下多少订单就能下多少，并且每次参与都是一个独立的对话。每一次对话，都会创建一个唯一的 placeOrderId。</p>
						<p>　　要实现这样的功能，可以使用包含唯一 ID 的属性来定义关联元素。在这个特例中，股票代码如清单 3所示。</p>
						<p>　　清单 3. 关联元素示例</p>
						<p>
								<font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;correlation name = "buysellCorrelation"<br />property = "tns:placeOrderId" /&gt;</font>
						</p>
						<p>　　<strong>工作单元</strong></p>
						<p>　　WSCI 使用事务元素为 Web 服务行为建模，并且将一组行为作为一个工作单元。Web 服务使用 WSCI 事务与其它服务通信，它要么完全执行完这些活动，要么将其存恢复到执行之前的一致状态。</p>
						<p>　　在买卖股票的例子中，在线股票交易公司与第三方(例如第三方信用卡 Web 服务)提供的不同 Web 服务对话。如果发生异常事件或是不能与任一个第三方完成事务，Web 服务必须保证能回到前一个状态。这是通过使用事务元素和补偿元素来实现的。 清单 4 说明了这部分的代码.</p>
						<p>　　清单 4. 事务元素示例</p>
						<p>
								<font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;transaction name = "reverseBuyOrder"= "atomic"&gt;<br />&lt;compensation&gt;<br />&lt;action name = "reverseBuyOrder"= "tns:trader"= <br />"tns:reverseBuyOrder"/&gt;<br />&lt;/compensation&gt;<br />&lt;/transaction&gt;</font>
						</p>
						<p>
								<font style="BACKGROUND-COLOR: #dddddd" face="Verdana">The transaction can be called in a compensation element when <br />an exception occurs as shown below:</font>
						</p>
						<p>
								<font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;onTimeout property = "tns:confirmationTime"= "duration"=<br />"tns:PlaceBuyOrder@end"&gt;<br />&lt;compensate transaction = "tns:reverseBuyOrder"/&gt;<br />&lt;/onTimeout&gt;</font>
						</p>
						<p>　　<strong>异常处理</strong></p>
						<p>　　在业务整合过程中，异常处理和选取适当的路由与处理正常情况一样重要。 维持，WSCI 使用了异常元素。WSCI 允许声明异常行为，由 Web 服务在编排好的点显示出来。异常行为的声明是上下文定义的一部分，并与异常进行关联，使用一些 Web 服务执行的行为以回应异常。异常是 WSCI 的建模能力，其设计的目的是为在 Web 服务编排的断点中显示的行为建模。它们不必表现出任何“技术错误”</p>
						<p>　　WSCI 能抛出一些异常，它们来自于 WSDL 、信息内容或事件(例如，超时事件)的错误信息。异常发生后，与异常相关的行为被执行，从而实现当前环境终止。所以，WSCI 支持“恢复异常”的概念，它不会导致整个系统重排而停止(和 JAVA 中try/catch的概念相似)。但是，在没有异常行为定义的情况下，错误的发生会使上下文终止，提交到父上下文中。理论上说，异常处理行为在父上下文中定义，就会成为所有子上下文的默认行为，反过来说，在上下文定义中的异常处理行为可以在父上下文中使用来作异常处理。</p>
						<p>　　在 清单 5中, 当用户确认订单的时间超过一分钟，应用程序就会超时。在 WSC 中，是通过超时特性来处理的。超时元素实际上是在异常事件中使用的事件元素。一分钟后，超时事件被触发，系统使用补偿元素回到上一次的 placeBuyOrder 状态。</p>
						<p>　　清单 5. 异常和超时元素示例</p>
						<p>
								<font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;exception&gt;<br />&lt;onTimeout property = "tns:expiryTime"<br />type = "duration"<br />reference="tns:ReserveSeats@end"&gt;<br />&lt;compensate transaction = "tns:seatReservation"/&gt;<br />&lt;/onTimeout&gt;<br />&lt;/exception&gt;</font>
						</p>
						<p>
								<img style="WIDTH: 494px; HEIGHT: 245px" height="315" src="http://searchwebservices.techtarget.com.cn/imagelist/05/09/4t2xq0femdv9.jpg" width="593" border="0" />
						</p>
						<p>　　图 3. 使用 WSCI 的股票交易</p>
						<p>
								<a class="f1"> </a>
						</p>
						<div class="guanggao">
								<span id="contentAdv">
								</span>
						</div>
						<p>
						</p>
						<p>　　<strong>WSCI 的其它特点</strong></p>
						<p>　　下面表 1列出了 WSCI 的其它有用特点。要查看完整的清单，请参考 WSCI 文档。</p>
						<p>　　表 1. WSCI 元素</p>
						<p>
						</p>
						<table style="WIDTH: 473px; HEIGHT: 1411px" bordercolor="#000000" cellspacing="1" cellpadding="1" width="473" bgcolor="#ffffff" border="1" heihgt="">
								<tbody>
										<tr>
												<td>元素名称</td>
												<td>简短描述</td>
												<td>示例</td>
										</tr>
										<tr>
												<td> Selector</td>
												<td> 选择器元素从消息中选择属性值。在抽取复杂的消息到一系列属性时它很有用。</td>
												<td>  
<p><font face="Verdana">您可以使用选择器元素从 getAllStocksResponse 消息中获取持有的总的股票数量: </font></p><p><font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;selector property = "tns:stockCount"<br />            element = “tns: ArrayOfStockList<br />            xpath = “count (./StockList)" /&gt;</font></p></td>
										</tr>
										<tr>
												<td> Call</td>
												<td> 调用元素在动作间调用任意操作(例如，调用第三方 Web 服务)。这是自动进行的，如果在调用的流程里发生错误，动作也会失败。</td>
												<td>  
<p><font face="Verdana">如果应用程序为了审核和重新协调一致，要将所有的事务写入日志，就可以调用任意一个流程来记录: </font></p><p><font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;process name = "DebitMoney" instantiation = "other"&gt;<br />&lt;action name = "debitMoney"<br />role = "tns:trader"<br />operation = "tns:debitMoney"&gt;<br />&lt;/action&gt;<br />&lt;call process = "auditTransactions"/&gt;<br />&lt;/action&gt;<br />&lt;/process&gt;</font></p></td>
										</tr>
										<tr>
												<td> All activity</td>
												<td> 所有活动元素与顺序活动相似，所有在其中定义的操作都会被执行，但是在这个元素中定义的活动能以任意顺序执行。</td>
												<td>  
<p><font face="Verdana">本例中，购买订单和从信用卡减钱操作可以用任何次序执行: </font></p><p><font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;all&gt;<br /> &lt;operation name="confirmBuyOrder"&gt;<br />  &lt;input message="buySellOrderResponse"/&gt;<br />  &lt;output message="buySellOrderResponse"/&gt;<br /> &lt;/operation&gt;<br /> &lt;operation name="debitMoney"&gt;<br />  &lt;input message="creditCardDetails"/&gt;<br />  &lt;output message="debitMoneyResponse"/&gt;<br /> &lt;/operation&gt;<br />&lt;/all&gt;</font></p></td>
										</tr>
										<tr>
												<td> Foreach</td>
												<td> 在循环中执行活动，和 Java 的循环很相似。</td>
												<td>  
<p><font face="Verdana">为每一个在 arrayOfStocks中的股票执行 PlaceSellOrder 操作： </font></p><p><font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;foreach select="ns1:arrayOfStockList/leg[position()&gt;1]"&gt;<br />&lt;process name = "PlaceSellOrder" instantiation = "other"&gt;<br />&lt;action name = "PlaceSellOrder"= "tns:trader"= "tns:placeSellOrder"&gt;<br />&lt;/action&gt;<br />&lt;/process&gt;<br />&lt;/foreach&gt;</font></p></td>
										</tr>
										<tr>
												<td> Switch</td>
												<td> switch 元素从基于条件的活动清单中选择一个活动。</td>
												<td>  
<p><font face="Verdana">条件的次序是很重要的，条件为真的首先执行。这个 Java 的 case 语句很相似: </font></p><p><font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;switch&gt;<br />&lt;case&gt;<br />&lt;condition&gt;tns:reverseBuyOrder&lt;/condition&gt;<br />&lt;action name = "reverseBuyOrder"<br />role = "tns:trader"<br />operation = "tns:reverseBuyOrder"/&gt;<br />&lt;/case&gt;<br />&lt;default&gt;<br />&lt;action name = "confirmBuyOrder"<br />role = "tns:trader"<br />operation = "tns:confirmBuyOrder"/&gt;<br />&lt;/default&gt;<br />&lt;/switch&gt;</font></p></td>
										</tr>
										<tr>
												<td> Until</td>
												<td> 在布尔值的基础上执行所有活动。它至少执行这些活动一次，与 Java 中的 do while 语句相似。</td>
												<td> <font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;until&gt;<br />&lt;condition&gt;tns:creditCardProcessed&lt;/condition&gt;<br />&lt;process name = "DebitMoney" instantiation = "other"&gt;<br />&lt;action name = "debitMoney"<br />role = "tns:trader"<br />operation = "tns:debitMoney"&gt;<br />&lt;/action&gt;<br />&lt;/process&gt;<br />&lt;/until&gt;</font></td>
										</tr>
										<tr>
												<td> While</td>
												<td> 基于条件布尔值，要么所有活动都不执行，要么执行很多次，和 Java 中的 while 语句相似。</td>
												<td> <font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;while&gt;<br />&lt;condition&gt;tns:creditCardProcessed&lt;/condition&gt;<br />&lt;process name = "DebitMoney" instantiation = "other"&gt;<br />&lt;action name = "debitMoney"<br />role = "tns:trader"<br />operation = "tns:debitMoney"&gt;<br />&lt;/action&gt;<br />&lt;/process&gt;<br />&lt;/while&gt;</font></td>
										</tr>
										<tr>
												<td> Delay</td>
												<td> 使用指定的延迟时间后运行活动，如果在活动中发生异常，活动可能会在指定时间前完成。</td>
												<td> <font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;exception&gt;<br />&lt;delay property = "tns:delayTime"<br />type = "duration"<br />reference="tns:delayBuyingStock"&gt;<br />&lt;/delay&gt;<br />&lt;/exception&gt;</font></td>
										</tr>
										<tr>
												<td> Call</td>
												<td> 这个元素实例化一个流程并且等待它执行完毕，call 元素对调用内部流程很有用。</td>
												<td> <font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;call process = “tns:audit" /&gt;</font></td>
										</tr>
										<tr>
												<td> Spawn</td>
												<td> 实例化一个流程但并不等待它执行完毕。</td>
												<td>
														<font style="BACKGROUND-COLOR: #dddddd"> <font face="Verdana">&lt;Spawn process = “tns:logBuyTransaction" /&gt;</font></font>
												</td>
										</tr>
										<tr>
												<td> Join</td>
												<td> 等待 spawned 流程的实例执行完毕。如果没有实例存在或所有实例都完成了，活动也完成了。</td>
												<td> <font style="BACKGROUND-COLOR: #dddddd" face="Verdana">&lt;join process = “tns:logBuyTransaction" /&gt;</font></td>
										</tr>
								</tbody>
						</table>
						<p>　　<strong>结束语</strong></p>
						<p>　　到现在为止，还没有一个标准的方法来描述通过 Web 服务与其它服务编排互动的方式来进行的信息流交换。针对这个问题， BEA 系统、Intalio、SAP AG、以及 Sun Microsystems 开发了 WSCI 。本文中，通过一个简单的例子您已学到了 WSCI 所提供的一些基本功能。但是我只揭开了它的表面的部分，为了更深入地了解 WSCI，您也许想看看 WSCI 规范，并且使用 WSCI 来编写些简单的应用程序样例。<br /><br /></p>
				</span>
		</dd>
<img src ="http://www.blogjava.net/hopeshared/aggbug/42789.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-04-24 10:41 <a href="http://www.blogjava.net/hopeshared/archive/2006/04/24/42789.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转载：BPEL和Java</title><link>http://www.blogjava.net/hopeshared/archive/2006/04/21/42322.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Fri, 21 Apr 2006 07:04:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/04/21/42322.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/42322.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/04/21/42322.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/42322.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/42322.html</trackback:ping><description><![CDATA[
		<strong>关键词</strong>： <a href="http://tag.bokee.com/tag/bpel" target="_blank">bpel</a>    <a href="http://tag.bokee.com/tag/java" target="_blank">java</a>    <a href="http://tag.bokee.com/tag/web%B7%FE%CE%F1" target="_blank">web服务</a>                                           
<p></p><p><font size="2">原文链结：</font><a href="http://www.theserverside.com/articles/article.tss?l=BPELJava">http://www.theserverside.com/articles/article.tss?l=BPELJava</a></p><p align="center">BPEL and Java</p><p><strong>BPEL的作用</strong></p><p>    实现从面向过程到面向服务的转变需要一种语言以描述Web services是怎样被组织成业务流程。如果这种描述是可执行的，即允许我们定义抽象的流程，而且允许我们描述流程准确的执行规则，那将更好。而BPEL正是这样一种语言。事实上它是最先具备以下特性的语言：<br />    1 允许我们定义抽象和可执行的流程<br />    2 有大多数公司支持<br />    3 软件运行在bpel流程可以执行（BPEL服务器）和设计（BPEL设计器）的平台上<br />    在我们对BPEL做更深入的了解之前，先论述一下怎样组织web服务。这通常有两种方法：音乐演奏式和舞蹈式。音乐演奏式为一个中心进程控制相关的web services并协调在操作中被调用的web services中不同操作的执行。音乐演奏时的乐谱就是一次组织过程。被调用的web services并不知道他们被调用以组织成一个流程，也不知道他们是一个更高层业务流程的一部分（它们也不需要知道）。只有音乐演奏中的指挥者知道这些，所以音乐演奏方式是将清晰定义的操作和web services的调用顺序集中起来管理的方式。<br />    相比而言舞蹈方式不依赖一个中心的协调器。每一个在舞蹈方式中被调用的web service清楚的知道何时执行它的操作并且知道与谁合作。舞蹈方式是专注与信息交互的合作方式。所有的参与者需要关注业务流程，操作的执行，信息的交互以及信息交互的时机。<br />    通过对组合web services以执行业务流程的了解，音乐演奏方式比之舞蹈方式为更灵活的处理方法：<br />     我们准确的知道谁对整个业务流程的执行负责<br />     即使是那些不知道他们是一个业务流程一部分的web services，我们也可以组合<br />     当错误发生时我们也可以提供可选择的替代<br />    BPEL遵循音乐演奏的方式。舞台方式为其他标准采用，比如WSCI（Web Services Choreogaphy Interface）和WS-CDL（Web Service Choreography Description Language）。比之BPEL，舞蹈方式还没有获得业界的支持。<br />    2002年8月，BEA、IBM、Microsoft开发出BPEL的第一个版本。从那时候起，越来越多厂商的加入使得在2003年3月在第一个版本基础上做了一些调整和改进的1.1版本的诞生。在2003年3月，BPEL被提交至OASIS组织作为标准，后来WSBPELTC组织成立。<br />    BPEL可以在公司内部和公司之间使用。在公司内部，BPEL的作用是标准化企业应用集成和促进以前孤立系统之间的集成。在企业之间，BPEL使得业务伙伴之间的集成更容易更高效。以BPEL描述的业务流程的定义在不影响现有系统的情况下完成升级。在已经是函数环境或将要通过web services方式提供服务的环境当中BPEL是重要的技术。随着web service技术得到越来越多的使用，BPEL的重要性将日渐增强。<br /><strong>BPEL语言</strong><br />      现在让我们看一下BPEL语言。BPEL作为一种语言具体设计用来定义业务流程。BPEL支持两种不同类型的业务流程：<br />     可执行流程允许我们指定严格的业务流程的细节，他们由音乐演奏引擎执行。在大多数情况下，BPEL被用作定义可执行的流程<br />    抽象的业务协议允许我们指定仅仅在各参与者之间公共的信息交换。他们不包含处理流程的内部细节并且不是可执行的。<br />    BPEL建立在XML和web services之上，它是一种基于XML的语言，支持包括SOAP,WSDL,UDDI,WS-Reliable消息,WS-Addressing,WS-Coordination和WS-Transaction的web services技术栈。BPEL汲取了两种早先的工作流语言：WSFL(Web Services Flow Language)和XLANG。WSFL由IBM设计，基于有向的内容。XLANG由微软设，是一种程序块结构语言。BPEL融合了这两种方法为业务流程的描述提供了丰富的语法。<br />    一个BPEL流程严格指定了参与的web services被调用的顺序。这可以顺序或并行地完成。使用BPEL我们可以表示有条件的行为，例如一个web service的执行可以依赖前一个调用的结果。我们也可以构建循环，申明变量，拷贝和赋值变量，定义错误处理程序等。通过组合这些结构，我们可以以一个算法方式定义复杂的业务流程。<br />    因此BPEL可以与像java这样的一般编程语言相比，不过没有java那样强大。但另一方面，它更简单并适合业务流程的定义。因此BPEL不是对java这样的高级语言的替代而是一个补充。让我们了解一下一个典型的BPEL流程。首先，这个BPEL业务流程收到一个请求。为了处理这个请求，流程开始调用相关的web services并将最后的结果返回给最初的请求发送者。因为BPEL流程需要与其他的web services通信，所以它非常依赖被合成web service所调用的web services的WSDL描述。<br />    一个BPEL流程由很多个步骤组成，每一步骤被称为一个活动。BPEL支持基本的和结构化的活动。基本的活动即为基础的结构，用作公共的任务，比如：<br />    使用<invoke />调用其他的web services<br />    通过发送一个消息等待客户端调用业务流程使用<receive />(收到一个请求)<br />    使用<reply />对同步的操作产生响应<br />    使用<assign />处理数据变量<br />    使用<throw />指示错误和异常<br />    使用<wait />等待一段时间<br />    使用<terminate />结束整个流程等等<br />    这样我们可以组合这些和其他基本的活动定义准确反映业务流程步骤的复杂算法。为了组合基本的活动BPEL支持一些结构化的活动。其中最重要的有：<br />    <sequence />允许我们定义一系列按顺序调用的活动<br />    <flow />用来定义一系列并行调用的活动<br />    <switch />用来构建分支结构<br />    <while />用来定义循环<br />    在许多的替代路径中选择一个的操作使用<pick /><br />    每一个BPEL流程也可以使用<variable />申明变量，使用<partnerlink />定义合作链接。我们将在文章的下面部分对合作链接作更多的探讨。<br />    一个BPEL流程可能是同步也可能是异步的。一个同步的BPEL流程锁定客户端(使用这个流程的)直到这个流程完成并返回一个结果给客户端。一个异步的流程不锁定客户端，而是使用一个回调来返回结果(如果结果存在的话)。通常我们使用异步的流程实现长时间的流程，使用同步实现在一个相对短的时间里返回结果的流程。如果一个BPEL流程使用异步的web services，流程本身同时也是异步的(虽然这不是必须的)。<br />     对于客户端来说，一个BPEL流程看起来就和其他的web service差不多。当我们定义一个流程，实际上我们是在定义一个由已存在服务组合而成的新的web service。为了调用由BPEL描述的业务流程，我们需要调用合成出来的复合web service。下图为一个BPEL流程的示意图：<br />  <img alt="example-bpel-process" src="http://cauzcy.bokee.com/inc/example-bpel-process.gif" onload="function anonymous()&#xD;&#xA;{&#xD;&#xA;function anonymous()&#xD;&#xA;{&#xD;&#xA;function anonymous()&#xD;&#xA;{&#xD;&#xA;function anonymous()&#xD;&#xA;{&#xD;&#xA;function anonymous()&#xD;&#xA;{&#xD;&#xA;function anonymous()&#xD;&#xA;{&#xD;&#xA;function anonymous()&#xD;&#xA;{&#xD;&#xA;function anonymous()&#xD;&#xA;{&#xD;&#xA; img_auto_size(this,450,true);&#xD;&#xA;}&#xD;&#xA;}&#xD;&#xA;}&#xD;&#xA;}&#xD;&#xA;}&#xD;&#xA;}&#xD;&#xA;}&#xD;&#xA;}" align="absMiddle" /><br />   <strong>合作链接</strong><br />上面我们提到BPEL也申明合作链接，现在让我们解释一下什么是合作链接。我们已经提到BPEL和外部的web services的交互有两种方式：<br />   BPEL流程调用其他web services上的操作<br />   BPEL流程接收客户端的调用。在所有客户端中有一个是发起最初调用的BPEL流程的使用者。其他客户端是web services。举例来说，是那些已经为BPEL流程所调用，但是需要回调以返回结果。<br />   BPEL把这些所有和它交互部分的链接称之为合作链接(partner links)。合作者链接可以是被BPEL流程调用的web services，也可以是调用BPEL流程的客户端。每一个BPEL流程至少有一个客户端合作链接，因为必然有一个调用BPEL流程的客户端。<br />    通常一个BPEL流程也至少有一个调用的合作链接，因为它将调用至少一个web service(通常不止一个)。不管怎么样，被调用的合作链接可能成为客户端链接——这通常是在异步服务的情况下，流程调用一个操作的地方。然后这个服务(合作者)调用流程上的回调操作来返回被请求的数据。<br />    BPEL像合作链接一样对待客户端有两个原因。最显而易见的是支持异步交互，第二个原因是基于BPEL流程可以提供服务的事实。这些通过端口类型提供的服务可以为多于一个的客户端使用。流程可能希望区分不同客户端并仅仅提供给他们经授权的功能。举例来说，一个保险流程可能提供给汽车保险客户与房产保险客户不同的一系列操作。<br />    综上述，我们可以看到合作链接描述了指向合作者的链接，这样的合作者可能是：<br />    流程调用的服务<br />    调用流程的服务<br />    两者兼而有之的服务——它们既被流程调用也调用流程</p><p><strong>BPEL的例子<br /></strong>    为了了解BPEL流程究竟是什么样子，下面我们给出一个选择最好保险服务的非常简单的BPEL流程。首先，我们申明指向一个BPEL流程客户端（称作client）和两个保险web服务(称作insuranceA 和 insuranceB)的合作链接。<br /> <br /></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080"> 1</span><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #0000ff">&lt;?</span><span style="COLOR: #ff00ff">xml version="1.0" encoding="utf-8"</span><span style="COLOR: #0000ff">?&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 2</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">process </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="insuranceSelectionProcess"</span><span style="COLOR: #ff0000">          targetNamespace</span><span style="COLOR: #0000ff">="http://packtpub.com/bpel/example/"</span><span style="COLOR: #ff0000">         xmlns</span><span style="COLOR: #0000ff">="http://schemas.xmlsoap.org/ws/2003/03/business-process/"</span><span style="COLOR: #ff0000">         xmlns:ins</span><span style="COLOR: #0000ff">="http://packtpub.com/bpel/insurance/"</span><span style="COLOR: #ff0000">         xmlns:com</span><span style="COLOR: #0000ff">="http://packtpub.com/bpel/company/"</span><span style="COLOR: #ff0000"> </span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 3</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">partnerLinks</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 4</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">partnerLink </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="client"</span><span style="COLOR: #ff0000"><br /></span><span style="COLOR: #008080"> 5</span><span style="COLOR: #ff0000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                 partnerLinkType</span><span style="COLOR: #0000ff">="com:selectionLT"</span><span style="COLOR: #ff0000"><br /></span><span style="COLOR: #008080"> 6</span><span style="COLOR: #ff0000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                   myRole</span><span style="COLOR: #0000ff">="insuranceSelectionService"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 7</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">partnerLink </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="insuranceA"</span><span style="COLOR: #ff0000">                                   partnerLinkType</span><span style="COLOR: #0000ff">="ins:insuranceLT"</span><span style="COLOR: #ff0000"> <br /></span><span style="COLOR: #008080"> 8</span><span style="COLOR: #ff0000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> myRole</span><span style="COLOR: #0000ff">="insuranceRequester"</span><span style="COLOR: #ff0000"><br /></span><span style="COLOR: #008080"> 9</span><span style="COLOR: #ff0000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                   partnerRole</span><span style="COLOR: #0000ff">="insuranceService"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">partnerLink </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="insuranceB"</span><span style="COLOR: #ff0000">                   partnerLinkType</span><span style="COLOR: #0000ff">="ins:insuranceLT"</span><span style="COLOR: #ff0000"><br /></span><span style="COLOR: #008080">11</span><span style="COLOR: #ff0000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                   myRole</span><span style="COLOR: #0000ff">="insuranceRequester"</span><span style="COLOR: #ff0000">                   partnerRole</span><span style="COLOR: #0000ff">="insuranceService"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />   </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">partnerLinks</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">  <br /></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><img src="http://www.blogjava.net/images/dot.gif" /><br /></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><span style="mso-spacerun: yes"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><span style="mso-spacerun: yes"><br /><br /></span></span></span></span>然后，我们为保险请求申明变量(InsuranceRequest)，保险A和B响应(InsuranceAResposne, InsuranceBResposne)，和最终的选择(InsuranceSelectionResponse)<br /><br /></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/dot.gif" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />   </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">variables</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000"> input for BPEL process </span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">variable </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="InsuranceRequest"</span><span style="COLOR: #ff0000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                messageType</span><span style="COLOR: #0000ff">="ins:InsuranceRequestMessage"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000"> output from insurance A </span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">variable </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="InsuranceAResposne"</span><span style="COLOR: #ff0000">                messageType</span><span style="COLOR: #0000ff">="ins:InsuranceResponseMessage"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000"> output from insurance B </span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">variable </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="InsuranceBResposne"</span><span style="COLOR: #ff0000">                messageType</span><span style="COLOR: #0000ff">="ins:InsuranceResponseMessage"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000"> output from BPEL process </span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">variable </span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="InsuranceSelectionResponse"</span><span style="COLOR: #ff0000">                messageType</span><span style="COLOR: #0000ff">="ins:InsuranceResponseMessage"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />   </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">variables</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><img src="http://www.blogjava.net/images/dot.gif" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span></div><p><br /><br />最后，我们具体化流程步骤。首先我们从客户端等待初始的请求信息(<receive />)。然后我们使用<flow />并行调用(<invoke />)两个保险web服务。保险服务返回保额，然后我们选择低的保额(<switch />/ <case />)并使用<reply />将结果返回给客户(BPEL流程的调用者)<br /><br /></p><div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000"><img src="http://www.blogjava.net/images/dot.gif" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />   </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">sequence</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000"> Receive the initial request from client </span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">receive </span><span style="COLOR: #ff0000">partnerLink</span><span style="COLOR: #0000ff">="client"</span><span style="COLOR: #ff0000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />               portType</span><span style="COLOR: #0000ff">="com:InsuranceSelectionPT"</span><span style="COLOR: #ff0000">               operation</span><span style="COLOR: #0000ff">="SelectInsurance"</span><span style="COLOR: #ff0000">               variable</span><span style="COLOR: #0000ff">="InsuranceRequest"</span><span style="COLOR: #ff0000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />               createInstance</span><span style="COLOR: #0000ff">="yes"</span><span style="COLOR: #ff0000"> </span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />     </span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000"> Make concurrent invocations to Insurance A and B </span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">flow</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />         </span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000"> Invoke Insurance A web service </span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />         </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">invoke </span><span style="COLOR: #ff0000">partnerLink</span><span style="COLOR: #0000ff">="insuranceA"</span><span style="COLOR: #ff0000">                 portType</span><span style="COLOR: #0000ff">="ins:ComputeInsurancePremiumPT"</span><span style="COLOR: #ff0000">                 operation</span><span style="COLOR: #0000ff">="ComputeInsurancePremium"</span><span style="COLOR: #ff0000">                 inputVariable</span><span style="COLOR: #0000ff">="InsuranceRequest"</span><span style="COLOR: #ff0000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                 outputVariable</span><span style="COLOR: #0000ff">="InsuranceAResposne"</span><span style="COLOR: #ff0000"> </span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />         </span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000"> Invoke Insurance B web service </span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />         </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">invoke </span><span style="COLOR: #ff0000">partnerLink</span><span style="COLOR: #0000ff">="insuranceB"</span><span style="COLOR: #ff0000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                 portType</span><span style="COLOR: #0000ff">="ins:ComputeInsurancePremiumPT"</span><span style="COLOR: #ff0000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                 operation</span><span style="COLOR: #0000ff">="ComputeInsurancePremium"</span><span style="COLOR: #ff0000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                 inputVariable</span><span style="COLOR: #0000ff">="InsuranceRequest"</span><span style="COLOR: #ff0000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                 outputVariable</span><span style="COLOR: #0000ff">="InsuranceBResposne"</span><span style="COLOR: #ff0000"> </span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">flow</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000"> Select the best offer and construct the response </span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">switch</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />        </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">case </span><span style="COLOR: #ff0000">condition</span><span style="COLOR: #0000ff">="bpws:getVariableData('InsuranceAResposne',<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                         'confirmationData','/confirmationData/Amount')<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                      &lt;= bpws:getVariableData('InsuranceBResposne',<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />                         'confirmationData','/confirmationData/Amount')"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />           </span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000"> Select Insurance A </span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />           </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">assign</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />             </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">copy</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />               </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">from </span><span style="COLOR: #ff0000">variable</span><span style="COLOR: #0000ff">="InsuranceAResposne"</span><span style="COLOR: #ff0000"> </span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />               </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">to </span><span style="COLOR: #ff0000">variable</span><span style="COLOR: #0000ff">="InsuranceSelectionResponse"</span><span style="COLOR: #ff0000"> </span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />             </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">copy</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />           </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">assign</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />        </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">case</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />        </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">otherwise</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />           </span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000"> Select Insurance B </span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />           </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">assign</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />             </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">copy</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />               </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">from </span><span style="COLOR: #ff0000">variable</span><span style="COLOR: #0000ff">="InsuranceBResposne"</span><span style="COLOR: #ff0000"> </span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />               </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">to </span><span style="COLOR: #ff0000">variable</span><span style="COLOR: #0000ff">="InsuranceSelectionResponse"</span><span style="COLOR: #ff0000"> </span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />             </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">copy</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />           </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">assign</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />        </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">otherwise</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">switch</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000"> Send a response to the client </span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />      </span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">reply </span><span style="COLOR: #ff0000">partnerLink</span><span style="COLOR: #0000ff">="client"</span><span style="COLOR: #ff0000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />             portType</span><span style="COLOR: #0000ff">="com:InsuranceSelectionPT"</span><span style="COLOR: #ff0000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />             operation</span><span style="COLOR: #0000ff">="SelectInsurance"</span><span style="COLOR: #ff0000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /> variable</span><span style="COLOR: #0000ff">="InsuranceSelectionResponse"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />   </span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">sequence</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000"><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">process</span><span style="COLOR: #0000ff">&gt;</span></div><p><br /><br />因为每一个BPEL流程都是一个web service，每一个BPEL流程也需要一个WSDL文档。我们将不再对开发BPEL流程的更深入的细节作讨论。更多的资料可以参阅由Packt Publishing于2004年10月出版的《web服务的业务流程执行语言》(Business Process Execution Language for Web Services)<br />  <strong>BPEL和Java<br /></strong>  看到从上面BPEL流程的例子一些人也许会想这样一个组合用java也很容易实现。对于非常简单的流程来说这是正确的。但是对于更复杂的流程来说我们会看到BPEL比之Java的至少两个重要的优势。<br />  BPEL比之Java的第一个优势是BPEL流程是可移植的，甚至可以运行在Java平台之外。BPEL流程可以在基于Java平台的音乐演奏服务器上运行也可以在任何其他的软件平台上运行(如.Net平台)。这在使用不同平台的B-B交互中显得尤为重要。<br />  BPEL的第二个优势是它针对业务流程特性的支持。通常业务流程是长时间运行的，特别是他们在internet上实现与其他合作者交互的时候。有可能这样流程的执行需要几分钟，几小时，甚至是几天才能完成。有可能它们调用一个web service需要等待一个相对长的时间以获得回调的结果。如果我们不使用一个BPEL流程而是使用一个Java应用程序我们的大部分时间将会担心什么线程已经完成，什么仍然在运行。我们将不得不跟踪Java线程以确定那些我们能结束，又有哪些需要继续运行以获得回调结果。<br />  BPEL也用相对简单的方式支持补偿。对在业务流程中那些已经成功完成操作的补偿，或者撤销操作是业务流程中最重要的问题之一。补偿的目的是恢复这个被撤销的业务流程中已经执行完成的活动。<br />   补偿与大多数业务流程的特性相关，这种业务流程是长时间运行的并且使用异步的方式与松散耦合的web servcies通信。就成功完成来说业务流程是非常脆弱的，因为他们所使用的数据本身就是脆弱的。因为它们通常横跨多个合作伙伴(同时是多个企业)，所以需要关注业务流程可能是完整执行也可能部分结果是未完成的，即补偿。这和在企业信息系统中的ACID事务类似。BPEL使用定义的补偿操作的能力支持补偿的概念(某种范围上讲这是特殊处理)，这种特性称之为长时间事务(LRT)。<br />    业务流程也可能需要对中心事件做出反映。这样的事件可能是消息事件或者警告事件。通过在端口类型上的调用操作消息事件由引入消息触发。警告事件是时间相关的，并且在一段持续时间之后或者一个特殊的时间触发。BPEL对业务流程中的事务管理提供了很好的支持。<br />    这样就有并发活动。在BPEL中并发活动使用<flow />活动来模拟。在<flow />标签内聚集嵌套的活动非常直观，也对表示那些并不太复杂的并发场景非常有帮助。为了表达更复杂的场景，<flow />提供在活动之间表达同步依赖的能力。换句话说，我们可以具体指定哪个活动能够开始，什么时候开始(依赖其他的活动)并且可以定义复杂的依赖。举例来说，我们常常指定一个特定的活动或几个活动必须在其他一个或几个活动结束之后才能开始。<br />    与web services的无状态模式相比业务流程模式需要使用一个有状态的模式。当一个客户端开始一个业务流程，一个新的实例将会创建。这个实例在业务流程的生命周期中存在。发送给业务流程的消息(使用在端口类型和通信端口上的操作)需要被转送到正确的业务流程实例。BPEL提供使用特定业务数据来保存指向特定业务流程实例的机制。这种功能称为相关性(correlation)。<br />    我们可以继续讨论，不过很明显BPEL已设计用来满足定义业务流程的需要。很明显，BPEL作为一种编程语言或是一个平台来说都不能取代Java。事实上，Java平台是运行BPEL流程的一个选择。<br />    <strong>BPEL服务器和开发工具<br /></strong>    为了执行BPEL流程我们需要一个音乐演奏式的服务器。这样的服务器为可执行的BPEL业务流程提供一个运行的环境。BPEL与web services紧密相关，也和支持web service开发的现代软件平台紧密相关，特别是J2EE和.Net平台。<br />    BPEL服务器可以使用J2EE或者.Net应用服务器的环境，这样他们可以使用应用服务器提供的服务，比如安全，事务，可伸缩性，和数据库的集成，EJB组件服务，如JMS的消息服务等等。<br />    BPEL服务器在J2EE和.Net平台上都已存在。在J2EE平台下我们至少可以在以下中选择：<br />     Oracle BPEL Process Manager (<a href="http://www.oracle.com/technology/products/ias/bpel/index.html">http://www.oracle.com/technology/products/ias/bpel/index.html</a>) <br />     IBM WebSphere Business Integration Server Foundation        (<a href="http://www.ibm.com/software/integration/wbisf">http://www.ibm.com/software/integration/wbisf</a>) <br />    IBM alphaWorks BPWS4J (<a href="http://www.alphaworks.ibm.com/tech/bpws4j">http://www.alphaworks.ibm.com/tech/bpws4j</a>) <br />    OpenStorm Service Orchestrator (<a href="http://www.openstorm.com/">http://www.openstorm.com</a>) <br />     Vergil VCAB Server (<a href="http://www.vergiltech.com/products_VCAB.php">http://www.vergiltech.com/products_VCAB.php</a>) <br />    Active Endpoints ActiveWebflow Server (<a href="http://www.active-endpoints.com/products/index.html">http://www.active-endpoints.com/products/index.html</a>) <br />    ActiveBPEL engine (<a href="http://www.activebpel.org/">http://www.activebpel.org/</a>) <br />    Fivesight Process eXecution Engine (<a href="http://www.fivesight.com/pxe.shtml">http://www.fivesight.com/pxe.shtml</a>) <br />    基于.Net平台的BPEL服务器包括：<br />Microsoft BizTalk 2004 (<a href="http://www.microsoft.com/biztalk/">http://www.microsoft.com/biztalk/</a>) <br />OpenStorm Service Orchestrator (<a href="http://www.openstorm.com/">http://www.openstorm.com</a>) <br />  OpenStorm提供包括J2EE和.NET平台上的解决方案。除了BPEL音乐演奏式服务器之外还有一些可用的BPEL设计工具。这些工具支持对BPEL流程的图形化开发并通常和服务器集成在一起：<br />   Oracle BPEL Designer <br />  IBM WebSphere Studio Application Developer, Integration Edition <br />  IBM BPWS4J Editor <br />  Vergil VCAB Composer <br /> Active Endpoints ActiveWebflow Designer <br />当Vergil VCAB Composer在.NET平台上建立时，Oracle, IBM和Active Endpoints的解决方案则是基于Java Eclipse框架。我们可以看到在Java平台上更多可用的BPEL服务器和设计器。<br /><strong>BPEL+jAVA</strong><br />  我们已经看到BPEL是组合web services成为业务流程的合适语言。BPEL不是一般普适性语言(也不想成为)。因此BPEL和JAVA相互配合，Java负责web services的编程实现和web services与BPEL流程的执行平台。<br />   如在规格说明书中提到的，BPEL是可扩展的。特别是BPEL可以扩展至web services之外是非常有前景的。这意味着我们可以使用BPEL组合不同的资源而不仅仅是web services。在J2EE平台中，可能包括EJBs，JMS，RMI，JCA和其他资源。对于这个问题通常有两种解决方法：<br />    支持BPEL和Java代码的混合，这就是BPELJ的思想<br />    用WSDL描述所有的资源(Java classes,EJBs,JMS等等)，这是Web Services调用框架中的思想<br />  BPELJ提供在BPEL流程定义中包含java代码(称之为JAVA片断)的可能性。这一方面使我们能够从BPEL中直接调用Java资源(BPELJ支持Java合作者链接)，另一方面，它给了BPELJ增强的能力，因为使用java片断，我们可以执行诸如计算值，构建XML文档之类的任务，也可以不用创建web服务就执行其他代码。我们也可以使用BPEL变量表达JAVA代码片段。IBM和BEA支持BPELJ，并且已经发表了BPELJ的白皮书。<br />    将java代码整合进BPEL流程以支持调用JAVA资源是非常有用的。但是，在某些情况下这样的处理方式也会带来缺点。对一个Java资源的调用不同于对一个web service的调用。web服务调用框架(WSIF)遵循另外一种处理思路：在BPEL中使用相同的语法调用资源或服务并使用WSDL来描述，即使它是一个不通过SOAP协议通信的Java资源。WSIF也允许我们将这样的服务和实际的实现与协议相映射。<br />    换句话说，我们可以把对抽象服务的描述与基于SOAP协议的实现绑定，与Java类绑定，与EJB绑定或者其它支持的资源，这只需要修改WSDL绑定即可。在BPEL中没有代码的更改是必须的而支持BPEL扩展也是需要的。对这种绑定的支持在由WSIF提供的支持者那里是坚定不移的。<br />   WSIF是最初由IBM的WSTK (Web Services Toolkit)开发中alphaWorks部分发展而来的Apache技术。现在如Oracle BPEL Process Manager的一些BPEL服务器已经支持WSIF。<br />   这两种方法，BPELJ和WSIF都适合现实世界的场景并且使得BPEL在EAI和B2B中都非常有用。<br /><strong>结束语</strong><br />    BPEL是面向过程转向面向服务的一种重要语言。因为BPEL具体设计用来定义业务流程，因此对业务流程的很多特殊性有很好的支持，如长时间事务，补偿，事件管理，相关性等等。BPEL非常适合和J2EE平台一起使用，很多BPEL服务器也是建立在J2EE之上的。结合BPEL和Java的BPELJ以及WSIF的思路使得BPEL的可用性越来越好。应该看到正在制定的JBI(Java Business Integration)规范将会在JAVA平台里给业务集成和BPEL一个更好的备有证明文件的位置。  <br /> <br /><br /><br />地址：<a href="http://cauzcy.bokee.com/4749126.html">http://cauzcy.bokee.com/4749126.html</a></p><img src ="http://www.blogjava.net/hopeshared/aggbug/42322.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-04-21 15:04 <a href="http://www.blogjava.net/hopeshared/archive/2006/04/21/42322.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>探索：Eclipse+Spring+XFire+Resin开发Web service(3) </title><link>http://www.blogjava.net/hopeshared/archive/2006/04/21/42319.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Fri, 21 Apr 2006 07:01:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/04/21/42319.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/42319.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/04/21/42319.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/42319.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/42319.html</trackback:ping><description><![CDATA[给江南白衣留言有大半天了，没有见到回复，看来他挺忙。<br /><br /><br />在标题的配置环境下，输入localhost:port/pro/services/yourservice?wsdl总是报一个错误，跟踪的结果是：这个请求过去之后，XFire开始写WSDL，错误的发生就是在AbstractWSDLWriter中，写出的wsdl是一个QDocument对象，接下来调用dom4j的api来写成xml文件，于是这个时候报错是说QDocument对象的name为空，我跟踪的时候那个对象的name确实是空的，但是在调试器的变量视图中看看错误信息是FileNotFound的错误<br /> <br /><br />很纳闷，究竟是什么File呢？是什么引起的这个错误呢？<br /><br /><br />网上找不到相关资料。<br /><br /><br />于是暂定此方法不通，但是这个问题<u><font style="BACKGROUND-COLOR: #ffc0cb">需要进一步研究</font></u>，写在这里，先做个标记<br /><br /><br />接下来看了SpringSide的环境配置说明，于是偶想，会不会放在MyEclipse中就好了呢？于是折腾阿折腾，把MyEclipse环境全部配置成功，居然报根前面一样的错误！！！！<br /><br /><br />这个时候我都快崩溃了<br /><br /><br />抱着最后一线希望，我尝试了wtp，使用的是Tomcat，这个时候居然正常了，不可思议<br /><br /><br />那么前面的bug是由服务器引起的还是XFire的？请听下回分解<br /><img src ="http://www.blogjava.net/hopeshared/aggbug/42319.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-04-21 15:01 <a href="http://www.blogjava.net/hopeshared/archive/2006/04/21/42319.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>探索：Eclipse+Spring+XFire+Resin开发Web service(2)</title><link>http://www.blogjava.net/hopeshared/archive/2006/04/21/42281.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Fri, 21 Apr 2006 02:36:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/04/21/42281.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/42281.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/04/21/42281.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/42281.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/42281.html</trackback:ping><description><![CDATA[昨天折腾了一天，似乎发现了XFire的一个Bug，也可能是XFire跟我用的Spring不兼容吧，反正单独测试XFire不成功，转而使用Spring来发布Web Service，发现工程根本就没有部署到resin上去，不明白为什么<br /><br /><br />刚刚看到了这片文章：<br /><a href="http://blog.csdn.net/bwsabc/archive/2006/04/18/667190.aspx">http://blog.csdn.net/bwsabc/archive/2006/04/18/667190.aspx</a><br />看来这位同学根我要做的事情是一样的，唯一的问题是WTP不能使用Resin。<br /><br /><br />现在我正在下载MyEclipse4.1，这个也是江南白衣在SpringSide中推荐的一个配置方案，恐怕我的标题该改成“探索：Eclipse+MyEclipse+XFire+Resin开发Web service”了<br /><br /><br />正在下载MyEclipse，等弄好了再发文<img src ="http://www.blogjava.net/hopeshared/aggbug/42281.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-04-21 10:36 <a href="http://www.blogjava.net/hopeshared/archive/2006/04/21/42281.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>探索：Eclipse+Spring+XFire+Resin开发Web service（1）</title><link>http://www.blogjava.net/hopeshared/archive/2006/04/20/42152.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Thu, 20 Apr 2006 06:07:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/04/20/42152.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/42152.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/04/20/42152.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/42152.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/42152.html</trackback:ping><description><![CDATA[
		<p>本探索源于老板给我的任务：制作3个Web service A,B and C,其中C是A与B的组合，A与B分布在两台机器上，分别采用XFire, Axis，WAS来发布服务，进行排列组合测试<br /><br /><br />偶没有使用过XFire，另外两个都ok了。看了看XFire的文档，说是目前支持Spring，那我就纳闷了，Axis作为Service发布容器并没有说要支持啥开发环境阿。于是偶想，时间比较充足，偶就慢慢来尝试吧<br /><br /><br />WAS采用的是9080端口，Axis利用Tomcat的8080端口，看来，我需要另外找个Server，于是这个时候想到了Resin。<br /><br /><br />于是我昨天已下午的时间全部浪费在了配置Eclipse+resin的环境问题上。<br /><br /><br />我下载了n个版本的resin，因为尝试的次数太多，并且全部失败了。<br />resin地址：<a href="http://www.caucho.com/download/index.xtp">http://www.caucho.com/download/index.xtp</a><br />还需要安装eclipse的resin插件<br />插件地址：<a href="http://www.improve-technologies.com/alpha/resin/#download">http://www.improve-technologies.com/alpha/resin/#download</a><br /><br /><br />网上关于配置它们的资料我看了很多，但是始终没有解决问题，至少我昨天是没有解决的。<br /><br /><br />今天可能rp比较好，稍微试了试，居然配好了。是这样，jdk用1.4的（或许1.5也不会出错 ），eclipse用3.1，resin用3.0.18,resin插件是3.0.0。安装插件，resin解压。通常resin只要解压就可以用了，我将resin的端口改成了8088，因为8080是猫猫(tomcat)用的。启动resin，输入<a href="http://localhost:8088">http://localhost:8088</a>，安装ok了。<br />启动Eclipse，在首选项中的resin中输入resin地址和java编译器，这个readme中有。新建一个resin项目<br /><br /><br />接着，最郁闷的事情就发生了，如何调试？<br /><br /><br />要这样，选择菜单上的Run..打开Run向导，选择Resin，new一个，你只需要在出来的选项卡的第一页的第二行（第一行是默认的）中填入一个your.conf全路径名，没有也没关系，它会给你创建一个。<br /><br /><br />接着运行。<br /><br /><br />我运行的时候报错，说一个什么Cache找不到，于是很郁闷，好在我有两台电脑，另一台电脑是ok的，原因是那个conf文件是从resin/conf中copy过来的，改了个名字，在&lt;/host&gt;之前加了句<br />&lt;web-app id='/youproname' document-directory="yourpropath\yourproname\web"/&gt;<br /><br /><br />再运行就ok了<br /><br /><br />另外，我看到resin插件的readme中有这么一段：<br />Resin 3</p>
		<p>If you get this error when starting resin<br />"Can't load JNI VFS library.  Resin will still run,"<br />Follow the instruction for unix, for window the easiest way is to copy resin.dll into the windows/system32 directory<br /><br />好像我的某次尝试报的就是这个错误，我不知道如何解决就放弃了那个解决方法，似乎是采用这个方法的时候：<a href="http://blog.csdn.net/chinarefers/archive/2005/03/09/315590.aspx">http://blog.csdn.net/chinarefers/archive/2005/03/09/315590.aspx</a><br /><br /><br />接下来的任务是配置XFire，这个过程是复杂而曲折的。。。<br /><br />好，等下篇再写，我干活先<img height="20" src="http://www.blogjava.net/Emoticons/QQ/07.gif" width="20" border="0" />因为现在还没弄清spring框架，那个service还不能跑呢，呵呵<br /></p>
<img src ="http://www.blogjava.net/hopeshared/aggbug/42152.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-04-20 14:07 <a href="http://www.blogjava.net/hopeshared/archive/2006/04/20/42152.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：使用Jena RDF API 开发脚本语言管理资源描述框架模型</title><link>http://www.blogjava.net/hopeshared/archive/2006/04/17/41444.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Mon, 17 Apr 2006 05:06:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/04/17/41444.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/41444.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/04/17/41444.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/41444.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/41444.html</trackback:ping><description><![CDATA[
		<div align="left">译者：<span style="COLOR: brown">gracepig</span></div>
		<br />
		<div align="left">E-mail &amp; MSN : zhangchi_nwpu@hotmail.com<br /><br /><br /><span style="COLOR: purple">版权声明</span>：可以任意转载，转载时请务必以超链接形式标明文章原始出处和作者信息及本声明<br />英文原文地址：<br /><a href="http://www.javaworld.com/javaworld/jw-07-2005/jw-0704-jena.html" target="_new">http://www.javaworld.com/javaworld/jw-07-2005/jw-0704-jena.html</a><br /><br />中文地址<br /><a href="http://www.matrix.org.cn/resource/article/43/43598_RDF_JAVA.html" target="_new">http://www.matrix.org.cn/resource/article/43/43598_RDF_JAVA.html</a><br /><br />关键词：Resource Description Framework models RDF XML Jena Protégé <br /><br /><b><span style="FONT-SIZE: 18px">摘要</span></b><br />资源描述框架（Resource Description Framework RDF）是一种以XML格式描述元数据的标准格式。Jena是一种用于将关系数据库或是文本文件中所表示的数据建立为元数据模型的框架方法。Protégé 用用来创建RDF元数据文档的编辑工具。 建立这种数据库和文件的元数据模型需要由用户自己定义脚本。本文介绍介绍了SemantiRDFUtils这种脚本，它拥有多个功能块可以用于维护Jena RDF 元数据模型.(2200词，2005-7-4) By Venkata N.VAsam<br /><br />与XML成为不同软件厂商之间数据交互的标准过程相似，资源描述框架（RDF）也沿着这条道路前进，希望能够成为描述与交互元数据的标准。XML 使用文件类型定义（DTD）和XML格式定义（XSD）来描述数据。RDF使用XML语法和RDF Schema（RFDS）来将元数据描述成为数据模型。<br /><br />本文介绍了一种使用Jena RDF API 编写的用户自定义工具，使用这种工具来管理存储在关系数据库或是文本文件的数据模型。这种工具是由HP实验室开发的，Jena框架是一个RDF，RDFS以及OWL（Web Ontology Language）的开源实现， 它包含着一个基于规则的推论引擎。它提供了建立和操纵RDF模型的Java API。本文介绍的SemanticRDFUtils.bat是一种使用Jena开发的脚本。使用这种脚本，我们可以维护存储在关系数据库和文本文件中的元数据模型。本文还介绍了怎样使用Protégé来将建RDF的语意描述文件（.rdfs）和数据文件(.rdf)。<br /><br /><b><span style="FONT-SIZE: 18px">软件安装</span></b><br />在使用SemanticRDFUtils.bat之前必须先安装以下的软件。关于以下工具的链接请参看文中所附的资源。<br />        J2SE 1.3 或更高的版本<br />        Jena 2.0 <br />        Oracle 9.2.0.1.0 <br />        Apache Ant 1.5.4 或更新的版本 <br />        Protégé 2.1<br /><br /><br /><b>RDF和RDFS 文件简要介绍</b><br />下面的XML格式的RDF和RDFS文件用于显示一个字母顺序的交叉引用模型。它们是使用Protégé 2.1 的图形界面工具创建的。当执行脚本和RDF查询工具的时候我们可以动态的引入RDF文件。RDFS文件则在我们使用Protégé 给RDF文件中加入更多数据时使用。<br /><br /><br /><b>列表1. RDFTest1.rdf</b><br /><br /><pre class="overflow">&lt;?xml version='1.0' encoding='UTF-8'?&gt;<br />&lt;!DOCTYPE rdf:RDF [<br />   &lt;!ENTITY rdf 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'&gt;<br />   &lt;!ENTITY rdfs 'http://www.w3.org/TR/1999/PR-rdf-schema-19990303#'&gt;<br />   &lt;!ENTITY Maana 'http://www.vvasam.com/Maana#'&gt;<br />]&gt;<br />&lt;rdf:RDF xmlns:rdf="&amp;rdf;"<br />   xmlns:Maana="&amp;Maana;"<br />   xmlns:rdfs="&amp;rdfs;"&gt;<br />&lt;Maana:ASCII rdf:about="&amp;Maana;RDFTest_Instance_0"<br />   Maana:Name="A"<br />   Maana:value="65"<br />   rdfs:label="A:65"&gt;<br />   &lt;Maana:system rdf:resource="&amp;Maana;RDFTest_Instance_2"/&gt;<br />&lt;/Maana:ASCII&gt;<br />&lt;Maana:System rdf:about="&amp;Maana;RDFTest_Instance_1"<br />   Maana:Name="lowercase"<br />   rdfs:label="lowercase"/&gt;<br />&lt;Maana:ASCII rdf:about="&amp;Maana;RDFTest_Instance_10000"<br />   Maana:Name="b"<br />   Maana:value="98"<br />   rdfs:label="b:98"&gt;<br />   &lt;Maana:system rdf:resource="&amp;Maana;RDFTest_Instance_1"/&gt;<br />&lt;/Maana:ASCII&gt;<br />&lt;Maana:ASCII rdf:about="&amp;Maana;RDFTest_Instance_10001"<br />   Maana:Name="B"<br />   Maana:value="66"<br />   rdfs:label="B:66"&gt;<br />   &lt;Maana:system rdf:resource="&amp;Maana;RDFTest_Instance_2"/&gt;<br />&lt;/Maana:ASCII&gt;<br />&lt;Maana:AscXRef rdf:about="&amp;Maana;RDFTest_Instance_10002"<br />   rdfs:label="b:98:B:66"&gt;<br />   &lt;Maana:keyName rdf:resource="&amp;Maana;RDFTest_Instance_10000"/&gt;<br />   &lt;Maana:keyValue rdf:resource="&amp;Maana;RDFTest_Instance_10001"/&gt;<br />&lt;/Maana:AscXRef&gt;<br />&lt;Maana:AscXRef rdf:about="&amp;Maana;RDFTest_Instance_10005"<br />   rdfs:label="a:97:A:65"&gt;<br />   &lt;Maana:keyValue rdf:resource="&amp;Maana;RDFTest_Instance_0"/&gt;<br />   &lt;Maana:keyName rdf:resource="&amp;Maana;RDFTest_Instance_8"/&gt;<br />&lt;/Maana:AscXRef&gt;<br />&lt;Maana:System rdf:about="&amp;Maana;RDFTest_Instance_2"<br />   Maana:Name="uppercase"<br />   rdfs:label="uppercase"/&gt;<br />&lt;Maana:ASCII rdf:about="&amp;Maana;RDFTest_Instance_8"<br />   Maana:Name="a"<br />   Maana:value="97"<br />   rdfs:label="a:97"&gt;<br />   &lt;Maana:system rdf:resource="&amp;Maana;RDFTest_Instance_1"/&gt;<br />&lt;/Maana:ASCII&gt;<br />&lt;/rdf:RDF&gt;</pre><br /><br /><b>列表 2. RDFTest1.rdfs</b><br /><br /><pre class="overflow">&lt;?xml version='1.0' encoding='UTF-8'?&gt;<br />&lt;!DOCTYPE rdf:RDF [<br />   &lt;!ENTITY rdf 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'&gt;<br />   &lt;!ENTITY system 'http://protege.stanford.edu/system#'&gt;<br />   &lt;!ENTITY Maana 'http://www.vvasam.com/Maana#'&gt;<br />   &lt;!ENTITY rdfs 'http://www.w3.org/TR/1999/PR-rdf-schema-19990303#'&gt;<br />]&gt;<br />&lt;rdf:RDF xmlns:rdf="&amp;rdf;"<br />   xmlns:system="&amp;system;"<br />   xmlns:rdfs="&amp;rdfs;"<br />   xmlns:Maana="&amp;Maana;"&gt;<br />&lt;rdf:Property rdf:about="&amp;system;maxCardinality"<br />   rdfs:label="system:maxCardinality"/&gt;<br />&lt;rdf:Property rdf:about="&amp;system;minCardinality"<br />   rdfs:label="system:minCardinality"/&gt;<br />&lt;rdf:Property rdf:about="&amp;system;range"<br />   rdfs:label="system:range"/&gt;<br />&lt;rdfs:Class rdf:about="&amp;Maana;ASCII"<br />   rdfs:label="ASCII"&gt;<br />   &lt;rdfs:subClassOf rdf:resource="&amp;rdfs;Resource"/&gt;<br />&lt;/rdfs:Class&gt;<br />&lt;rdfs:Class rdf:about="&amp;Maana;AscXRef"<br />   rdfs:label="AscXRef"&gt;<br />   &lt;rdfs:subClassOf rdf:resource="&amp;rdfs;Resource"/&gt;<br />&lt;/rdfs:Class&gt;<br />&lt;rdf:Property rdf:about="&amp;Maana;Name"<br />   rdfs:label="Name"&gt;<br />   &lt;rdfs:domain rdf:resource="&amp;Maana;ASCII"/&gt;<br />   &lt;rdfs:domain rdf:resource="&amp;Maana;System"/&gt;<br />   &lt;rdfs:range rdf:resource="&amp;rdfs;Literal"/&gt;<br />&lt;/rdf:Property&gt;<br />&lt;rdf:Property rdf:about="&amp;Maana;RDFTest_Slot_10003"<br />   rdfs:label="RDFTest_Slot_10003"&gt;<br />   &lt;rdfs:range rdf:resource="&amp;rdfs;Literal"/&gt;<br />&lt;/rdf:Property&gt;<br />&lt;rdfs:Class rdf:about="&amp;Maana;System"<br />   rdfs:label="System"&gt;<br />   &lt;rdfs:subClassOf rdf:resource="&amp;rdfs;Resource"/&gt;<br />&lt;/rdfs:Class&gt;<br />&lt;rdf:Property rdf:about="&amp;Maana;keyName"<br />   rdfs:label="keyName"&gt;<br />   &lt;rdfs:range rdf:resource="&amp;Maana;ASCII"/&gt;<br />   &lt;rdfs:domain rdf:resource="&amp;Maana;AscXRef"/&gt;<br />&lt;/rdf:Property&gt;<br />&lt;rdf:Property rdf:about="&amp;Maana;keyValue"<br />   rdfs:label="keyValue"&gt;<br />   &lt;rdfs:range rdf:resource="&amp;Maana;ASCII"/&gt;<br />   &lt;rdfs:domain rdf:resource="&amp;Maana;AscXRef"/&gt;<br />&lt;/rdf:Property&gt;<br />&lt;rdf:Property rdf:about="&amp;Maana;system"<br />   rdfs:label="system"&gt;<br />   &lt;rdfs:domain rdf:resource="&amp;Maana;ASCII"/&gt;<br />   &lt;rdfs:range rdf:resource="&amp;Maana;System"/&gt;<br /><br />&lt;/rdf:Property&gt;<br />&lt;rdf:Property rdf:about="&amp;Maana;value"<br />   rdfs:label="value"&gt;<br />   &lt;rdfs:domain rdf:resource="&amp;Maana;ASCII"/&gt;<br />   &lt;rdfs:range rdf:resource="&amp;rdfs;Literal"/&gt;<br />&lt;/rdf:Property&gt;<br />&lt;/rdf:RDF&gt;</pre><br /><br /><b><span style="FONT-SIZE: 18px">Jena和Protégé概述</span></b><br />本节在宏观层面上介绍Jena和Protégé。用户可以在附加资源中得到关于这两个产品更多的信息。本文的目的是使您对Jena和Protégé有一个比较清晰的理解。<br /><br /><b><span style="FONT-SIZE: 15px">Jena RDF 和RDQL</span></b><br /><br />RDF数据模型是一个声明（statement）的集合，每一个声明都包括三个部分：资源，属性和值。 资源（resource）可以是任何使用URI标示的内容，它可以包含其它属性。每一个属性有一个值。<br />Jena可以将RDF模型保存在关系数据库或是文件当中。RDQL是用来查询RDF模型的语言。RDF提供一种节点可以为资源或是文本的有向图（有向图的概念请参看《离散数学》）。RDQL则提供一种方式，由用户定义一种图模式，使用这种模式对目标图集合进行匹配，获得所有符合定义模式的结果。图1 使用RDF图来表示列表1和列表2中文件<br /><br /><center><img onmouseover="javascript:imgShowTip(this);" style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="resized image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_17_000933_KlFWJSPLUI.jpg" width="600" onload="javascript:imgLoad(this);" border="0" resized="1" /></center><br /><center><b>图1:范例RDF文件的RDF 图表示</b></center><br /><br />上图中，椭圆代表资源，长方形代表描述。资源通过箭头连接到其它的资源或是描述值（一个对象或是一个值）上，这样一组关系形成一个三元组，成为一个声明（statement）。<br />下面给我一个RDQL查询的例子。三元组(?x &lt;http://www.vvasam.com/Maana#value&gt; "97")是一个声明。X是一个绑定的变量用来代表一个资源；http://www.vvasam.com/Maana#value是一个叫做“value”的属性；97是这个属性的值。<br /><br /><b>SELECT ?x WHERE (?x &lt;http://www.vvasam.com/Maana#value&gt; "97") </b><br /><br />Jena的toolkit提供了一个在命令行方式执行的Java类（jjena.rdfquery）来进行RDQL查询。下面的例子演示了如果使用这个命令进行查询并将查询结果存入test1.rdql当中。<br />java jena.rdfquery --data RDFTest1.rdf --query test1.rdql<br />x<br />================================================<br />http://www.vvasam.com/Maana#RDFTest_Instance_8 <br /><br /><b>注意</b>:通过文后的资源链接来获得关于RDF和RDQL更多的信息。<br /><br /><br /><b><span style="FONT-SIZE: 15px">RDF 中使用Protégé</span></b><br /><br />Protégé 是一个用来建立和编辑ontologies和知识库的GUI工具。Protégé可以在RDF格式下创建和保存数据。在使用Protégé建立RDF模型时，需要在新建一个工程的时候选取RDF Schema，如图2所示。<br /><br /><center><img onmouseover="javascript:imgShowTip(this);" style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="" src="http://www.matrix.org.cn/resource/upload/content/2005_08_17_001303_rQCMiMiJma.jpg" onload="javascript:imgLoad(this);" border="0" resized="0" /></center><br /><center>图2. RDF Schema工程</center><br /><br />在Protégé's工程菜单选择新建工程时，选择格式（Select Format）对话框会弹出。点击OK按钮，图3的窗口会出现。<br /><br /><center><img onmouseover="javascript:imgShowTip(this);" style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="" src="http://www.matrix.org.cn/resource/upload/content/2005_08_17_001343_lGVLgynODG.jpg" onload="javascript:imgLoad(this);" border="0" resized="0" /></center><br /><center>图3. 缺省Protégé工程视图</center><br /><br />正如您在图3中所看到的那样，Protégé有一些标签。本文主要介绍其中的Classes，Instances和Algernon标签。<br />图4显示了Protégé的保存对话框。在其中用户可以填入工程，类文件，实例文件，和命名空间的名字。如图4所示，类文件名中包括RDF Schema的信息，实例文件名中包括RDF的数据。命名空间中以唯一URI的方式标示出RDF模型。<br /><br /><center><img onmouseover="javascript:imgShowTip(this);" style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="" src="http://www.matrix.org.cn/resource/upload/content/2005_08_17_001443_texPBISZkB.jpg" onload="javascript:imgLoad(this);" border="0" resized="0" /></center><br /><center>图4: Protégé's保存对话框</center><br /><br />图5和图6显示的是Protégé's类标签和实例标签，分别表示了列表1和列表2中的.rdf和.rdfs文件。这些文件使用Protégé's schema 格式创建。<br /><br /><center><img onmouseover="javascript:imgShowTip(this);" style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="" src="http://www.matrix.org.cn/resource/upload/content/2005_08_17_001515_fjdZOLJnuX.jpg" onload="javascript:imgLoad(this);" border="0" resized="0" /></center><br /><center>图5: Protégé的类标签</center><br /><br /><center><img onmouseover="javascript:imgShowTip(this);" style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="" src="http://www.matrix.org.cn/resource/upload/content/2005_08_17_001608_aKdneyTvXb.jpg" onload="javascript:imgLoad(this);" border="0" resized="0" /></center><br /><center>图6: Protégé的实例标签</center><br /><br /><b><span style="FONT-SIZE: 15px">Protégé中的Algeronon 查询</span></b><br />Protégé's的Algernon query标签为进行Algernon查讯提供了一个图形界面，用户可以在这个UI当中进行查询，并查看结果。Algernon是一种基于三元组的查询语言，如图7所示Algernon将资源以遍历（traversal）路径的方式返回给用户。缺省的Algernon并不会如下图那样显示。要看到这个标签，用户必须从工程菜单的设置子菜单中选择。<br /><br /><br /><center><img onmouseover="javascript:imgShowTip(this);" style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="" src="http://www.matrix.org.cn/resource/upload/content/2005_08_17_001747_BLJxGTSxfY.jpg" onload="javascript:imgLoad(this);" border="0" resized="0" /></center><br /><center>图7. Algernon 标签</center><br /><br /><b><span style="FONT-SIZE: 15px">Jena和Protégé之间的命名（terminology）映射</span></b><br />由于Jena和Protégé是两个不同的开源技术，所以他们的RDF 命名（terminology）存在差别。下表中列出了这些命名规则，用户可以更具这些命名规则来创建和处理RDF文件。<br /><br /><br /><center>表1. Jena 和 Protégé 命名比较</center><br /><center><img onmouseover="javascript:imgShowTip(this);" style="DISPLAY: inline" onclick="javascript:imgClick(this);" alt="" src="http://www.matrix.org.cn/resource/upload/content/2005_08_17_001842_AQXHJFEJFm.gif" onload="javascript:imgLoad(this);" border="0" resized="0" /></center><br /><br /><b><span style="FONT-SIZE: 15px">Jena 的语义RDF工具</span></b><br /><br />一节讲解了一些用于维护Jena数据库和文件模型的有用的工具/脚本。这些脚本文件包含在SemanticRDFUtils-scripts-files.zip文件当中，您可以在资源当中找到。下面的列表中描述了这些脚本文件可以执行的任务。当用户以没有任务ID号作为参数的命令行方式执行SemanticRDFUtils批处理文件时，下面的内容将会出现在你的控制台当中<br /><br /><pre class="overflow">C:\RDF\SemanticRDFUtils<br />Usage: SemanticRDFUtils taskid<br />   Where taskid should be any one of the following:<br />    1 --&gt; To create and initialize the Jena system tables with a system model name as JenaRDFSystem<br />    2 --&gt; To create a database model<br />    3 --&gt; To remove a database model.<br />    4 --&gt; To list the contents of a given model.<br />    5 --&gt; To import RDF/XML file to a database.<br />    6 --&gt; To list existing database model names<br />    7 --&gt; To export a database model to a RDF/XML file<br />    8 --&gt; To delete all the contents of a database model<br />    9 --&gt; To create a union(RDF/XML file) of RDF/XML file models<br />    10 --&gt; To create an intersection(RDF/XML file) of RDF/XML file models<br />    11 --&gt; To create a difference(RDF/XML file) of RDF/XML file models<br />    12 --&gt; To get the size of the given model<br />    13 --&gt; Export the RDF query results as RDF/XML file.<br />    14 --&gt; Delete the resource(s) from a model based on RDF query</pre><br /><br /><br />以上各任务ID的意思分别为：<br />1:建立并初始化一个Jena系统表，系统模型名为JenaRDFSystem<br />2:建立数据库模型<br />3:删除一个数据库模型<br />4:列出所给出模型当中的内容<br />5:将RDF/XML文件导入数据库<br />6:列出存在数据库模型的名字<br />7:将数据库模型导出到RDF/XML文件中<br />8:删除一个数据库模型当中的所有内容<br />9: 为不同RDF/XML文件模型建立一个合并的RDF/XML文件<br />10:建立不同RDF/XML文件直接的交集文件。<br />11: 建立不同RDF/XML文件直接的差集文件。<br />12:得到给定模型的大小<br />13:将RDF查询结果保存在RDF/XML文件当中<br />14:从RDF查询结果模型当中删除资源<br /><br />SemanticRDFUtils脚本使用SemanticRDFUtils.properties文件储存配置信息。下表给出了配置信息中的所有属性：<br /><br /><center>表 2. 属性设置</center><br /><br /><center><img onmouseover="javascript:imgShowTip(this);" style="DISPLAY: inline" onclick="javascript:imgClick(this);" height="450" alt="resized image" src="http://www.matrix.org.cn/resource/upload/content/2005_08_17_002008_BkkmggsQZV.gif" width="302" onload="javascript:imgLoad(this);" border="0" resized="1" /></center><br /><br /><b>任务</b><br />第一个任务是在数据库中建立一个Jena 系统表并要求下列属性的正确值：<br />        rdf_sytem_model_name <br />        db_user <br />        db_password <br />        isRDFInDB <br />        url<br /><br />第二个任务是在数据库建立一个新的RDF模型并要求下列属性的正确值：<br />        rdf_sytem_model_name <br />        db_user <br />        db_password <br />        isRDFInDB <br />        url <br />        modelName (如果这个属性为空，那么脚本会提示用户从键盘输入值)<br /><br />第三个任务是从数据库中删除RDF模型并要求以下属性的正确值：<br />        rdf_sytem_model_name <br />        db_user <br />        db_password <br />        isRDFInDB <br />        url <br />        modelName (如果这个属性为空，那么脚本会提示用户从键盘输入值)<br /><br />第四个任务是列出RDF数据库中的内容并要求以下属性的正确值：<br />        rdf_sytem_model_name <br />        db_user <br />        db_password <br />        isRDFInDB <br />        url <br />        modelName (如果这个属性为空，那么脚本会提示用户从键盘输入值)<br /><br />第五个任务是将RDF导入到数据库模型当中，并要求以下属性的正确值：<br />        rdf_sytem_model_name <br />        db_user <br />        db_password <br />        isRDFInDB <br />        url <br />        modelName (如果这个属性为空，那么脚本会提示用户从键盘输入值) <br />        import_rdffile_abs_name<br />属性import_rdffile_abs_name值将被置为.rdf文件的绝对路径（如下的例子所示）。如果这个值为空那么脚本会提示用户从键盘输入值。<br />import_rdffile_abs_name=C:\temp\RDFTest1.rdf <br /><br />第六个任务是列出一个数据库模型中所有的模型，需要以下的属性的正确值：<br />        rdf_sytem_model_name <br />        db_user <br />        db_password <br />        isRDFInDB <br />        url <br /><br />第七个任务是将指定数据库模型的内容导出到一个RDF文件当中，需要以下的属性的正确值：<br />        rdf_sytem_model_name <br />        db_user <br />        db_password <br />        isRDFInDB <br />        url <br />        modelName (如果这个属性值为空，脚本将提示用户从键盘输入)<br />        import_rdffile_abs_name <br />属性export_rdffile_abs_name值将被置为.rdf文件的绝对路径（如下的例子所示）。如果这个值为空那么脚本会提示用户从键盘输入值。<br />export_rdffile_abs_name=C:/temp/export.rdf <br /><br />第八个任务是从数据模型中删除内容，需要以下正确的属性值：<br />        rdf_sytem_model_name <br />        db_user <br />        db_password <br />        isRDFInDB <br />        url <br />The ninth task performs a union operation on two file models and requires appropriate values for the following properties: <br /><br />第九个任务是对两个文档模型进行并集操作，需要以下正确的属性值：<br />        isRDFInDB <br />        url <br />               file_rdfmodel1_abs_name <br />        file_rdfmodel2_abs_name <br />        result_rdfmodel_abs_name <br />下面是一个范例的属性值：<br /><pre class="overflow">file_rdfmodel1_abs_name=C:/temp/RDFTest1.rdf<br /><br />file_rdfmodel2_abs_name=C:/temp/RDFTest2.rdf<br /><br />result_rdfmodel_abs_name=C:/temp/RDFTestUnion.rdf</pre><br />当使用SemanticRDFUtils执行任务9的时候，两个.rdf文件会被合并。如果要在一个合并的.rdf文件上建立一个Protégé工程，.rdfs文件必须被手工生成。<br /><br />第10个任务是执行两个文件模型的交集操作，需要以下属性的正确值：<br />        isRDFInDB <br />        url <br />        file_rdfmodel1_abs_name <br />        file_rdfmodel2_abs_name <br />        result_rdfmodel_abs_name <br />下面是一个范例的属性值：<br /><pre class="overflow">file_rdfmodel1_abs_name=C:/temp/RDFTest1.rdf<br />file_rdfmodel2_abs_name=C:/temp/RDFTest2.rdf<br />result_rdfmodel_abs_name=C:/temp/RDFTestInterSection.rdf</pre><br /><br />第11个任务是执行两个文件模型的差集操作，需要以下属性的正确值：<br />        isRDFInDB <br />        url <br />        file_rdfmodel1_abs_name <br />        file_rdfmodel2_abs_name <br />        result_rdfmodel_abs_name <br />下面是一个范例的属性值：<br /><pre class="overflow">file_rdfmodel1_abs_name=C:/temp/RDFTest1.rdf<br />file_rdfmodel2_abs_name=C:/temp/RDFTest2.rdf<br />result_rdfmodel_abs_name=C:/temp/ RDFTestDifference.rdf</pre><br /><br />第12个任务是列出指定数据库模型的大小，需要以下属性的正确值：<br />        rdf_sytem_model_name <br />        db_user <br />        db_password <br />        isRDFInDB <br />        url <br />        modelName (如果这个值为空那么脚本会提示用户从键盘输入值) <br /><br />第13个任务将对数据库模型的一个RDF查询结果导出到一个RDF文件中，需要以下属性的正确值：<br />        rdf_sytem_model_name <br />        db_user <br />        db_password <br />        isRDFInDB <br />        url <br />        modelName (如果这个属性值为空，脚本会要求用户从键盘输入值) <br />        rdf_query <br />        bind_var_name <br />        export_rdffile_abs_name <br />下面是一个范例的属性值：<br /><pre class="overflow">rdf_query=SELECT ?x WHERE (?x    "65")<br />bind_var_name=x<br />export_rdffile_abs_name=C:/temp/exportquery.rdf</pre><br /><br />第14个任务是将一个将数据库模型的RDF查询结果删除，需要以下属性的正确值：<br />        rdf_sytem_model_name <br />        db_user <br />        db_password <br />        isRDFInDB <br />        url <br />        modelName (如果这个属性值为空，脚本会要求用户从键盘输入值) <br />        rdf_query <br />        bind_var_name <br />下面是一个范例的属性值：<br /><pre class="overflow">rdf_query=SELECT ?x WHERE (?x    "65")<br />bind_var_name=x</pre><br /><br /><b>结论</b>：<br />这篇文章介绍了怎么样使用Jena和Protégé来创建RDF源数据模型。并描述了怎样使用SemanticRDFUtils在命令行脚本方式下维护RDF模型。在这篇文章的资源中的SemanticRDFUtils-source-files.zip文件包含了能够用来创建基于Web接口或是Protégé的插件的源文件，使用它们可以管理RDF模型。针对每一个RDF模型所加载的脚文会有所不同，所以需要区别对待，每一种情况都要独立处理。<br /><br />关于作者：<br />Venkata N. Vasam 主要工作领域是J2EE/Web services/EAI 架构。目前他使用SeeBeyond集成工具包（eGate和ICAN）为A2A和B2B集成需求提供Web服务/J2EE/EAI 架构。他获得了J.N.T University，Hyderabad, India的计算机科学与工程学位。业余时间Vasam喜欢打网球看喜剧和运动电影。<br /><br /><span style="COLOR: purple">gracepig</span>是(<a href="http://www.matrix.org.cn/" target="_new">Matrix.org.cn</a>)的会员，可以通过zhangchi_nwpu@hotmail.com和他联系。<br /><br /><br />资源 <br />文中的源码下载地址<br />http://www.javaworld.com/javaworld/jw-07-2005/jena/jw-0704-jena.zip <br />"What is RDF?" 作者 Tim Bray (XML.com, 一月 2001): http://www.xml.com/pub/a/2001/01/24/rdf.html <br />        RDF 规范<br />http://www.w3.org/RDF/ <br />        Jena下载地址<br />http://jena.sourceforge.net/downloads.html <br />        RDF和Jena RDF API简介<br />http://jena.sourceforge.net/tutorial/RDF_API/index.html <br />        Jena2: 一种语意Web框架<br />http://www.hpl.hp.com/semweb/jena2.htm <br />        RDQL: <br />http://jena.sourceforge.net/tutorial/RDQL/index.html <br />        RDF 入门 <br />http://www710.univ-lyon1.fr/~champin/rdf-tutorial/ <br />        Protégé 入门<br />http://protege.stanford.edu/doc/tutorial/get_started/index.html <br />        Protégé 下载<br />http://protege.stanford.edu/download/download.html <br />        Algernon标签<br />http://algernon-j.sourceforge.net/doc/algernon-protege.html <br />        ava 下载地址<br />http://java.sun.com/ <br />        Oracle下载地址<br />http://www.oracle.com/technology/software/index.html <br />                Matrix java门户<br /><a href="http://www.matrix.org.cn/" target="_new">http://www.matrix.org.cn</a></div>
<img src ="http://www.blogjava.net/hopeshared/aggbug/41444.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-04-17 13:06 <a href="http://www.blogjava.net/hopeshared/archive/2006/04/17/41444.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>概述：在线园艺零售商 Web service 方案</title><link>http://www.blogjava.net/hopeshared/archive/2006/03/15/35417.html</link><dc:creator>hopeshared</dc:creator><author>hopeshared</author><pubDate>Wed, 15 Mar 2006 07:34:00 GMT</pubDate><guid>http://www.blogjava.net/hopeshared/archive/2006/03/15/35417.html</guid><wfw:comment>http://www.blogjava.net/hopeshared/comments/35417.html</wfw:comment><comments>http://www.blogjava.net/hopeshared/archive/2006/03/15/35417.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hopeshared/comments/commentRss/35417.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hopeshared/services/trackbacks/35417.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 本文档取自IBM Websphere的帮助文档														此方案集由名为				 Plants by WebSphere 				的在线零售商设计。				Plants by WebSphere 				使用				 WebSphere Application Server 				中的				 Web service 			...&nbsp;&nbsp;<a href='http://www.blogjava.net/hopeshared/archive/2006/03/15/35417.html'>阅读全文</a><img src ="http://www.blogjava.net/hopeshared/aggbug/35417.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hopeshared/" target="_blank">hopeshared</a> 2006-03-15 15:34 <a href="http://www.blogjava.net/hopeshared/archive/2006/03/15/35417.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>