在 WebSphere Application Server V7 中為 WS-Addressing 提供 JAX-WS 2.1 支援

CloudSpace發表於2010-08-17
Brian T. De Pradine, 軟體工程師, IBM
Katherine Sanders, 軟體工程師, IBM

簡介: IBM WebSphere Application Server V7 包括了對 Java API for XML-Based Web Services (JAX-WS) 2.1 規範的支援。JAX-WS 2.1 是 Java Specification Request (JSR) 224 的維護版本,通過增加新功能對 JAX-WS 2.0 規範提供的功能進行了擴充套件。其中最重要的新功能就是在應用程式程式設計介面(Application Programming Interface,API)中支援 Web Services Addressing (WS-Addressing)。在本文中,我們將瞭解如何使用這個新的 WS-Addressing 支援,以及如何幫助 web 服務開發人員簡化有狀態 web 服務的開發。

簡介

Java™ API for XML-Based Web Services (JAX-WS) 接替了此前的標準 Java API for XML based RPC (JAX-RPC)。JAX-RPC 1.0 和 JAX-RPC 1.1 為支援 Remote Procedure Call (RPC) 風格的 Web 服務呼叫定義了 API 和約定。然而,從那時起,Web 服務開始朝更加面向文件的風格發展。JAX-WS 2.0 提供了完全不同的應用程式程式設計介面(API)和約定來支援更新風格的 web 服務互動。並且還特別注重簡化開發人員在編寫 Web 服務應用程式時的體驗。參見參考資料部分,獲得詳細介紹 JAX-WS 和 JAX-RPC 之間差別的文章的連結。

JAX-WS 2.1 繼承了從 JAX-WS 2.0 開始出現的簡化趨勢,使開發人員更易於編寫有狀態 Web 服務。這是通過向 JAX-WS API 新增明確的 Web Services Addressing (WS-Addressing) 支援實現的。在本文中,我們將給出一個示例應用程式,它展示瞭如何使用這些新的 API 編寫有狀態 Web 服務,但是首先我們將詳細瞭解一下這些與 WS-Addressing 有關的新 API。

不過,在開始之前,我們需要指出 JAX-WS 2.1 規範只支援 WS-Addressing 1.0 Core 和 Simple Object Access Protocol (SOAP) Binding 規範。如果需要支援 WS-Addressing 規範的不同版本,那麼 JAX-WS 2.1 規範還為供應商提供了擴充套件 API 的能力。在 IBM® WebSphere® Application Server V7 中,我們利用了這種功能,以支援較舊的 WS-Addressing Member Submission 規範(參見參考資料)。這些擴充套件也將在本文中加以介紹。

端點引用

JAX-WS 2.1 規範引入了端點引用(endpoint reference)的概念。端點引用封裝了用於成功定位 Web 服務端點所需的所有細節。API 引入了一個新類,EndpointReference,用於表示端點引用。然而,該類並不是由開發人員直接使用,而是應當使用它的子類。

JAX-WS 2.1 API 包括了 EndpointReference 的一個子類,名為 W3CEndpointReference。它的作用是根據 WS-Addressing 1.0 Core 規範的要求表示端點引用。在 WebSphere Application Server V7 中,我們提供了另一個子類 SubmissionEndpointReference,用於根據 WS-Addressing Member Submission 規範表示端點引用。這兩個類之間的關係如圖 1 所示。


圖 1. 端點關係
端點關係

JAX-WS 2.1 規範還定義了多種在應用程式中建立端點引用的方法。清單 1 中的程式碼片段使用 W3CEndpointReferenceBuilder 類顯示了其中一種方法。為清晰起見,我們在下面的示例中忽略了一些細節,但是可以通過本文末尾的應用程式獲得完整的示例。


清單 1. JAX-WS 2.1 示例

				
		
import org.w3c.dom.Element;
import javax.xml.ws.wsaddressing.W3CEndpointReference;
import javax.xml.ws.wsaddressing.W3CEndpointReferenceBuilder;

String address = ...
Element referenceParameter = ...

W3CEndpointReferenceBuilder builder =
    new W3CEndpointReferenceBuilder();
builder.address(address);
builder.referenceParameter(referenceParameter);
W3CEndpointReference epr = builder.build();

W3CEndpointReferenceBuilder 使開發人員能夠指定端點引用的任意屬性。在清單 1 中,我們僅僅指定了一個地址和一個引用引數,然而,還可以指定 Web Services Description Language (WSDL) 服務名和端點(埠)名來代替地址。執行時將使用服務名和端點名的組合來識別引用所需的端點,並且返回一個填充有正確地址的 W3CEndpointReference

如果需要使用 SubmissionEndpointReference 替代 W3CEndpointReference,那麼在 WebSphere Application Server V7 中,可以使用 SubmissionEndpointReferenceBuilder 類,如清單 2 中的程式碼片段所示。


清單 2. SubmissionEndpointReference

				
				
import org.w3c.dom.Element;
import com.ibm.websphere.wsaddressing.jaxws21.SubmissionEndpointReference;
import com.ibm.websphere.wsaddressing.jaxws21.SubmissionEndpointReferenceBuilder;

String address = ...
Element referenceParameter = ...

SubmissionEndpointReferenceBuilder builder =
    new SubmissionEndpointReferenceBuilder();
builder.address(address);
builder.referenceParameter(referenceParameter);
SubmissionEndpointReference epr = builder.build();

如果使用的是服務名和端點名的組合,那麼可以使用 W3CEndpointReferenceBuilderSubmissionEndpointReferenceBuilder 類為同一個 Java Platform, Enterprise Edition (Java EE) 應用程式中部署的任意端點建立端點引用。這表示,如果端點不在同一個應用程式中,那麼必須明確指定地址。如果端點所需的僅是對其本身的引用,那麼 JAX-WS 2.1 提供了一種更簡單的替代方法來使用構建程式。WebServiceContext 類被擴充套件,以支援端點引用的建立。如清單 3 所示。


清單 3. WebServiceContext 類

				
			
import org.w3c.dom.Element;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.wsaddressing.W3CEndpointReference;

@Resource
private WebServiceContext context;

Element referenceParameter = ...

W3CEndpointReference w3cEPR =
    (W3CEndpointReference) context.getEndpointReference(referenceParameter);

在叢集中建立端點引用

如果應用程式被部署到叢集中,那麼使用構建程式或 WebServiceContext 建立的任何端點引用都不會支援對某個特定伺服器或端點的相關性(affinity)。不過,簡單的工作負載管理是可行的,因為使用這種端點引用通過代理髮出的任何請求都將以輪循(round-robin)方式分佈到叢集成員中。

在使用 WebServiceContext 時,惟一可以明確指定的屬性是一個引用引數。地址元素以及所有其他屬性由執行時填充。如果需要一個 SubmissionEndpointReference,那麼在 WebSphere Application Server V7 中,可以使用 JAX-WS 2.1 提供的擴充套件機制。如清單 4 的程式碼片段所示。


清單 4. SubmissionEndpointReference

				
		
import org.w3c.dom.Element;
import javax.xml.ws.WebServiceContext;
import com.ibm.websphere.wsaddressing.jaxws21.SubmissionEndpointReference;

@Resource
private WebServiceContext context;

Element referenceParameter = ...

SubmissionEndpointReference epr =
    context.getEndpointReference(SubmissionEndpointReference.class, referenceParameter);

應用程式中建立的端點引用可以通過連線返回到客戶端。客戶端隨後可以使用該端點引用按需呼叫端點。根據 WS-Addressing 規範,端點引用中包含的任何引用引數都將被作為頭部(header)自動新增到要傳送的 SOAP 信封。JAX-WS 2.1 還提供了一種工具,允許 Web 服務應用程式檢索這些引用引數,如清單 5 所示。


清單 5. 檢索引用引數

				
	
import org.w3c.dom.Element;    
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;

@Resource
private WebServiceContext context;

List list =
   (List) context.getMessageContext().get(MessageContext.REFERENCE_PARAMETERS);

該列表隨後將被讀取,以從中找出引用引數。然而,如果遵守 WS-Addressing Member Submission 規範編寫應用程式,那麼就不能使用這種機制檢索引用引數。相反,必須使用 EndpointReferenceManager 類,這是 WebSphere Application Server V7 提供的專有 WS-Addressing API 的一部分。如清單 6 所示。在這種情況下,必須提供引用引數的名稱才能檢索它。


清單 6. EndpointReferenceManager

				
			
import javax.xml.namespace.QName;
import com.ibm.websphere.wsaddressing.EndpointReferenceManager;

QName name = ...
String refParam =
    EndpointReferenceManager.getReferenceParameterFromMessageContext(name);

Feature

JAX-WS 2.1 還引入了 feature 概念。一個 feature 就是指一種允許客戶端開發人員通過程式設計方式控制客戶端具體行為的機制。所有 feature 都來自 WebServiceFeature 類。這允許客戶端開發人員將不同型別的 WebServiceFeature 傳遞給需要它們的客戶端 API。與 WS-Addressing 有關的 feature 如圖 2 所示。


圖 2. WS-Addressing Feature
WS-Addressing Feature

AddressingFeature 用於控制 WS-Addressing 的使用。它允許開發人員啟用/禁用客戶端對 WS-Addressing 的使用。如果啟用了 WS-Addressing,客戶端將在要傳送的 SOAP 訊息中包含 WS-Addressing 頭。這些頭將位於 WS-Addressing 1.0 Core 規範名稱空間 http://www.w3.org/2005/08/addressing 中。如果禁用 WS-Addressing,那麼不會傳送任何 WS-Addressing 頭。

在 WebSphere Application Server V7 中,我們還提供一個 SubmissionAddressingFeature 類。該類與 AddressingFeature 的工作方式相同,惟一不同之處是如果它得到啟用,那麼由客戶端傳送的任何 WS-Addressing 頭都將位於 WS-Addressing Member Submission 規範名稱空間 http://schemas.xmlsoap.org/ws/2004/08/addressing 中。在 WebSphere Application Server V7 中,可以使用其他機制啟用客戶端中的 WS-Addressing 支援,但是這不屬於本文的討論範圍。請參見參考資料部分,獲得介紹這些機制的相關連結。

註釋

JAX-WS 2.1 大量使用了註釋(annotation)來簡化伺服器端的應用程式開發。@Addressing 註釋在伺服器端起到與 AddressingFeature 相同的作用。它用於對 web 服務端點啟用/禁用 WS-Addressing。如果啟用了 WS-Addressing,那麼執行時將處理傳入請求中包含的 http://www.w3.org/2005/08/addressing 名稱空間中的任何 WS-Addressing 頭。此外,任何響應訊息在適當時都會將 WS-Addressing 頭新增到自身。如果 WS-Addressing 被禁用,那麼傳入請求中的任何 WS-Addressing 頭部都將被忽略。

@Addressing 註釋還支援一個名為 required 的屬性。如果將該屬性設定為 true,那麼任何傳入 web 服務的訊息都必須包含 WS-Addressing 頭,否則將向客戶端返回一個錯誤。required 屬性也出現在 AddressingFeature 中,但是根據 JAX-WS 2.1 規範,它將被客戶端忽略。在 WebSphere Application Server V7 中,我們還提供了 @SubmissionAddressing 註釋。它與 @Addressing 的工作方式相同,不同之處在於它與 http://schemas.xmlsoap.org/ws/2004/08/addressing 名稱空間中的 WS-Addressing 頭有關。這些類如圖 3 所示。


圖 3. Addressing 類
Addressing 類

JAX-WS 2.1 還引入了新的註釋來支援 WS-Addressing 動作和 WSDL 操作的對映。這些新註釋是 @Action@FaultAction@Action 註釋允許將一個動作顯式地關聯到一個 WSDL 操作的輸入和輸出。@FaultAction 註釋在 @Action 註釋的內部使用,用於將每個錯誤關聯到一個操作。這些類如圖 4 所示。要使用 @Action@FaultAction 註釋,需要用到 @Addressing 註釋,否則它們將被忽略。


圖 4. Fault 和 Action 類
Fault 和 Action 類 

應用程式

現在我們已經簡要介紹了 JAX-WS 2.1 中引入的與 WS-Addressing 有關的新概念,接下來我們將把它們組合到一個有用的應用程式中。在下面給出的 Calculator 應用程式中,客戶端向 web 服務發出一個請求,要求將兩個數相加並返回結果。然而,在客戶端發出請求之前,它必須首先從 web 服務獲得一個票證(ticket),之後才能夠發出請求來將兩個數字相加。這個票證被作為端點引用內部的一個引用引數傳送給客戶端。客戶端隨後可以使用這個端點引用來傳送請求,將兩個數字相加。

還可以下載獲得這個 Calculator 應用程式。該應用程式以 .ear 檔案的形式提供,可以被匯入到 IBM Rational® Application Developer V7.5.1 或安裝到 WebSphere Application Server V7 上。要在 Rational Application Developer 上完整編譯,必須將 com.ibm.jaxws.thinclient_7.0.0.jar 新增到建立的 CalculatorClientCalculatorService 專案的類路徑。jar 檔案可以在 WebSphere Application Server 安裝的執行時目錄中找到。

讓我們首先看一下 Calculator 服務的 WSDL。WSDL 如清單 7 所示。我們可以看到其中包含 4 個操作:getTicketaddgetSubmissionTicketaddSubmission。getTicket 操作返回一個端點引用,其中包含作為引用引數提供的票證。add 操作允許我們將兩個數字相加。其他兩個操作執行相同的功能,但是使用的是 WS-Addressing Member Submission 規範而不是 WS-Addressing 1.0 Core 規範。


清單 7. Calculator.wsdl

				
			


    
        
            
        
    
    
        
    
    
        
    
    
        
    
    
        
    
    
        
    
    
        
    
    
        
    
    
        
    
    
        
    
    
        "getTicket">
            
            
        
        "getSubmissionTicket">
            
            
        
        "add">
            
            
            
        
        "addSubmission">
            
            
            
        
    
    
        
        
        
            
            
                
            
            
                
            
        
        
            
            
                
            
            
                
            
        
        
            
            
                
            
            
                
            
            
                
            
        
        
            
            
                
            
            
                
            
            
                
            
        
    
    
        
            

生成一個 SEI

當使用清單 7 中的 WSDL 生成 SEI 後,@Action@FaultAction 註釋不會被自動新增。在清單 8 中的 SEI 中,我們手動新增了註釋。

通過使用這個 WSDL 以及應用程式 ear 檔案中的 Calculator_schema1.xsd 模式,我們可以生成一個 Service Endpoint Interface (SEI)。這可以通過使用 WebSphere Application Sever 安裝的 bin 目錄中的 wsimport 工具完成。生成的 SEI 如清單 8 所示。它包含 4 個方法:getTicket()add()getSubmissionTicket()addSubmission() getTicket() 方法返回一個 W3CEndpointReference,而 getSubmissionTicket() 方法返回一個 SubmissionEndpointReferenceadd()addSubmission() 方法返回一個 int,並且它們還使用 @Action 進行了註釋。@Action 註釋包含一個將 AddNumbersException 對映到動作 @FaultAction 註釋。


清單 8. Calculator.java

				
			
package developerworks.jaxws.calculator;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.Action;
import javax.xml.ws.FaultAction;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
import javax.xml.ws.wsaddressing.W3CEndpointReference;

import com.ibm.websphere.wsaddressing.jaxws21.SubmissionEndpointReference;

@WebService(name = "Calculator", targetNamespace = 
            "http://calculator.jaxws.developerworks")
@XmlSeeAlso({
    ObjectFactory.class
})
public interface Calculator {

    @WebMethod
    @WebResult(targetNamespace = "")
    @RequestWrapper(localName = "getTicket",
                 targetNamespace = "http://calculator.jaxws.developerworks",
                 className = "developerworks.jaxws.calculator.GetTicket")
    @ResponseWrapper(localName = "getTicketResponse",
                 targetNamespace = "http://calculator.jaxws.developerworks",
                 className = "developerworks.jaxws.calculator.GetTicketResponse")
    public W3CEndpointReference getTicket();

    @WebMethod
    @WebResult(targetNamespace = "")
    @RequestWrapper(localName = "getSubmissionTicket",
                targetNamespace = "http://calculator.jaxws.developerworks",
                className = "developerworks.jaxws.calculator.GetSubmissionTicket")
    @ResponseWrapper(localName = "getSubmissionTicketResponse",
                targetNamespace = "http://calculator.jaxws.developerworks",
                className = "developerworks.jaxws.calculator.GetSubmissionTicketResponse")
    public SubmissionEndpointReference getSubmissionTicket();

    @WebMethod
    @WebResult(targetNamespace = "")
    @RequestWrapper(localName = "add",
                targetNamespace = "http://calculator.jaxws.developerworks",
                className = "developerworks.jaxws.calculator.Add")
    @ResponseWrapper(localName = "addResponse",
                targetNamespace = "http://calculator.jaxws.developerworks",
                className = "developerworks.jaxws.calculator.AddResponse")
    @Action(input = "http://calculator.jaxws.developerworks/add",
            utput = "http://calculator.jaxws.developerworks/addResponse",
            fault = {@FaultAction(className = AddNumbersException.class,
            value = "http://calculator.jaxws.developerworks/addFault")})
    public int add(
        @WebParam(name = "arg0", targetNamespace = "")
        int arg0,
        @WebParam(name = "arg1", targetNamespace = "")
        int arg1)
        throws AddNumbersException_Exception;

    @WebMethod
    @WebResult(targetNamespace = "")
    @RequestWrapper(localName = "addSubmission",
                targetNamespace = "http://calculator.jaxws.developerworks",
                className = "developerworks.jaxws.calculator.AddSubmission")
    @ResponseWrapper(localName = "addSubmissionResponse",
                targetNamespace = "http://calculator.jaxws.developerworks",
                className = "developerworks.jaxws.calculator.AddSubmissionResponse")
    @Action(input = "http://calculator.jaxws.developerworks/addSubmission",
            utput = "http://calculator.jaxws.developerworks/addSubmissionResponse",
            fault = {@FaultAction(className = AddNumbersException.class,
            value = "http://calculator.jaxws.developerworks/addSubmissionFault")})
    public int addSubmission(
        @WebParam(name = "arg0", targetNamespace = "")
        int arg0,
        @WebParam(name = "arg1", targetNamespace = "")
        int arg1)
        throws AddNumbersException_Exception;

}

在清單 9 中顯示了我們的 web 服務的實現。它使用 @Addressing@SubmissionAddressing 進行了註釋,表示通過這兩種規範對應用程式啟用了 WS-Addressing。注意,@Addressing@SubmissionAddressing 必須被新增到實現類而不是 SEI 中。getTicket()getSubmissionTicket() 方法各自建立了一個包含票證的端點引用。在將兩個數字相加之前,add()addSubmission() 方法將檢查該票證。考慮到我們的這個簡單示例的意圖,我們僅僅硬編碼了一個字串來充當票證。然而,在一個更加真實的場景中,我們可以想象得到這個票證實際上表示資料庫中某個記錄的鍵(舉例而言)。


清單 9. CalculatorService.java

				
		    
package developerworks.jaxws.calculator.impl;

import java.util.List;
import javax.annotation.Resource;
import javax.jws.WebService;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.soap.Addressing;
import javax.xml.ws.wsaddressing.W3CEndpointReference;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.ibm.websphere.wsaddressing.EndpointReferenceManager;
import com.ibm.websphere.wsaddressing.ReferenceParameterCreationException;
import com.ibm.websphere.wsaddressing.jaxws21.SubmissionAddressing;
import com.ibm.websphere.wsaddressing.jaxws21.SubmissionEndpointReference;

import developerworks.jaxws.calculator.AddNumbersException;
import developerworks.jaxws.calculator.AddNumbersException_Exception;
import developerworks.jaxws.calculator.Calculator;

@Addressing
@SubmissionAddressing
@WebService(endpointInterface = "developerworks.jaxws.calculator.Calculator",
            serviceName = "Calculator",
            portName = "CalculatorPort",
            targetNamespace = "http://calculator.jaxws.developerworks")
public class CalculatorService implements Calculator {

    @Resource
    private WebServiceContext context;

    public W3CEndpointReference getTicket() {
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        Element element = null;

        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.newDocument();
            element = document.createElementNS(
                          "http://calculator.jaxws.developerworks",
                          "TicketId");
            element.appendChild( document.createTextNode("123456789") );
        } catch (ParserConfigurationException pce) {
            throw new WebServiceException("Unable to create ticket.", pce);
        }

        return (W3CEndpointReference) context.getEndpointReference(element);
    }

    public SubmissionEndpointReference getSubmissionTicket() {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        Element element = null;

        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.newDocument();
            element = document.createElementNS(
                          "http://calculator.jaxws.developerworks",
                          "TicketId");
            element.appendChild( document.createTextNode("123456789") );
        } catch (ParserConfigurationException pce) {
            throw new WebServiceException("Unable to create ticket.", pce);
        }

        return (SubmissionEndpointReference) context.getEndpointReference(
                SubmissionEndpointReference.class, element);
    }

    public int add(int value1, int value2) throws AddNumbersException_Exception {
        List> list = (List>) context.getMessageContext().get(
                MessageContext.REFERENCE_PARAMETERS);

        if (list.isEmpty())
            throw new AddNumbersException_Exception("No ticket found.",
                new AddNumbersException());

        Element element = (Element) list.get(0);

        if (!"123456789".equals(element.getTextContent()))
            throw new AddNumbersException_Exception("Invalid ticket: "
                    + element.getTextContent(), new AddNumbersException());

        return value1 + value2;
    }

    public int addSubmission(int value1, int value2)
            throws AddNumbersException_Exception {
        String refParam;
        try {
            refParam = EndpointReferenceManager
                    .getReferenceParameterFromMessageContext(new QName(
                            "http://calculator.jaxws.developerworks",
                            "TicketId"));
        } catch (ReferenceParameterCreationException e) {
            throw new AddNumbersException_Exception("No ticket found.",
                    new AddNumbersException());
        }
	    
        if (!"123456789".equals(refParam)) {
            throw new AddNumbersException_Exception("Invalid ticket: "
                    + refParam, new AddNumbersException());
        }

        return value1 + value2;
    }
}

對 WS-Addressing Member Submission 規範的支援

在使用 wsimport 工具生成客戶端專案時,將自動把 WS-Addressing Core 1.0 名稱空間中的端點引用對映到 W3CEndpointReference 類。然而,要將 WS-Addressing Member Submission 名稱空間的端點引用對映到 SubmissionEndpointReference 類,您需要將所提供的繫結檔案 SubmissionEndpointReference.xjb 指定為工具的 -b 引數。繫結檔案可以在 WebSphere Application Server 安裝的 util 目錄中找到。

清單 10 展示的客戶端演示了對 Calculator 服務的應用。它被編寫為同時使用 WS-Addressing 1.0 規範和 WS-Addressing Member Submission 規範。為此,它使用 get ticket 方法呼叫服務來獲取端點引用,後者包含作為引用引數提供的票證。隨後使用端點引用向對應的 add 方法傳送請求,要求將兩個數字相加。使用端點引用將使所包含的引用引數被作為 SOAP 頭自動包含到請求中。web 服務將首先檢查這一點,然後再執行數字相加併傳送結果。


清單 10. CalculatorClient.java

				
			    
package developerworks.jaxws.calculator.client;

import javax.xml.ws.soap.AddressingFeature;
import javax.xml.ws.wsaddressing.W3CEndpointReference;

import com.ibm.websphere.wsaddressing.jaxws21.SubmissionAddressingFeature;
import com.ibm.websphere.wsaddressing.jaxws21.SubmissionEndpointReference;

import developerworks.jaxws.calculator.Calculator;
import developerworks.jaxws.calculator.Calculator_Service;

public class CalculatorClient {
    /**
     * @param args
     */
    public static void main(String[] args) {
        try {            
            int value0 = Integer.parseInt(args[0]);
            int value1 = Integer.parseInt(args[1]);
	
            Calculator_Service service = new Calculator_Service();
            Calculator port1 = service.getCalculatorPort();

            // Retrieve W3CEndpointRefence ticket
            W3CEndpointReference epr = port1.getTicket();
            Calculator port2 = epr.getPort(Calculator.class,
                    new AddressingFeature());
	        
            // Add numbers using W3CEndpointRefence ticket
            int answer = port2.add(value0, value1);
            System.out
                    .println("The answer using a W3CEndpointRefence ticket is: "
                            + answer);
            // Retrieve SubmissionEndpointReference ticket
            SubmissionEndpointReference submissionEpr = port1
                    .getSubmissionTicket();
            port2 = submissionEpr.getPort(Calculator.class,
                    new SubmissionAddressingFeature());
	        
            // Add numbers using a SubmissionEndpointReference
            answer = port2.addSubmission(value0, value1);
            System.out
                    .println("The answer using a SubmissionEndpointReference ticket is: "
                            + answer);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在清單 11 中,我們看到在使用 getTicket() 方法請求票證時訊息被髮送。注意,使用了 WS-Addressing 的預設動作模式來確定要使用的動作,因為清單 8 中的 getTicket() 方法中沒有使用 @Action 註釋。預設動作模式是由 WS-Addressing 規範定義的一種方式,用於根據 WSDL 操作的屬性確定操作。


清單 11. GetTicket Request

				
		    

    
http://localhost:9080/CalculatorService/Calculator urn:uuid:14C1B8561B19D0B1261258998512414 http://calculator.jaxws.developerworks/Calculator/getTicketRequest
getTicket xmlns:ns2="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:ns3="http://www.w3.org/2005/08/addressing" xmlns:ns4="http://calculator.jaxws.developerworks"/>

在清單 12 中,我們看到了響應訊息。注意,TicketId 包含在返回的 EndpointReferenceReferenceParameters 中,而且預設的動作模式仍在使用中。還需注意,WS-Addressing 1.0 Core 規範名稱空間被用於 EndpointReference,以及使用該 EndpointReference 的後續請求和響應的 WS-Addressing 頭。


清單 12. GetTicket Response

				
		    

        
            http://calculator.jaxws.developerworks/Calculator/getTicketResponse
        
        urn:uuid:14C1B8561B19D0B1261258998512414
    
    
        getTicketResponse
             xmlns:ns2="http://schemas.xmlsoap.org/ws/2004/08/addressing"
             xmlns:ns3="http://www.w3.org/2005/08/addressing" 
             xmlns:ns4="http://calculator.jaxws.developerworks">
            
                <ns3:Address>
                    http://L32H82K:9080/CalculatorService/Calculator
                
                <ns3:ReferenceParameters>
                    TicketId
                         xmlns="http://calculator.jaxws.developerworks" 
                         xmlns:wsa="http://www.w3.org/2005/08/addressing">
                        123456789
                    
                
                <ns3:Metadata>
                    
                        axis2ns5:Calculator
                    
                
            
        
   

在清單 13 中,我們看到在呼叫 add() 方法時訊息被髮送。注意 TicketId 包含在訊息頭中。還要注意該動作與清單 8 中 add 方法中的 @Action 註釋的輸入動作匹配。


清單 13. Add Request

				
		    

    
wsa="http://www.w3.org/2005/08/addressing"> TicketId xmlns:ns4="http://calculator.jaxws.developerworks" xmlns="http://calculator.jaxws.developerworks" xmlns:ns2="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:ns3="http://www.w3.org/2005/08/addressing" ns3:IsReferenceParameter="true">123456789 <wsa:To>http://L32H82K:9080/CalculatorService/Calculator <wsa:MessageID>urn:uuid:14C1B8561B19D0B1261258998516588 <wsa:Action>http://calculator.jaxws.developerworks/add
add xmlns:ns2="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:ns3="http://www.w3.org/2005/08/addressing" xmlns:ns4="http://calculator.jaxws.developerworks"> 1 2

在清單 14 中顯示了最終的響應訊息,其中包含預期的結果和清單 8 中設定的輸出動作。


清單 14. Add Response

				
		    

    
wsa="http://www.w3.org/2005/08/addressing"> <wsa:Action>http://calculator.jaxws.developerworks/addResponse <wsa:RelatesTo>urn:uuid:14C1B8561B19D0B1261258998516588
addResponse xmlns:ns2="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:ns3="http://www.w3.org/2005/08/addressing" xmlns:ns4="http://calculator.jaxws.developerworks"> 3

在清單 15 中顯示了在使用 WS-Addressing Member Submission 規範 EndpointReference 時傳送的相應訊息。


清單 15. WS-Addressing Member Submission 規範

				
			

    
http://localhost:9080/CalculatorService/Calculator urn:uuid:14C1B8561B19D0B1261258998516636 http://calculator.jaxws.developerworks/Calculator/getSubmissionTicketRequest
getSubmissionTicket xmlns:ns2="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:ns3="http://www.w3.org/2005/08/addressing" xmlns:ns4="http://calculator.jaxws.developerworks"/>
http://calculator.jaxws.developerworks/Calculator/getSubmissionTicketResponse urn:uuid:14C1B8561B19D0B1261258998516636
getSubmissionTicketResponse xmlns:ns2="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:ns3="http://www.w3.org/2005/08/addressing" xmlns:ns4="http://calculator.jaxws.developerworks"> <ns2:Address> http://L32H82K:9080/CalculatorService/Calculator <ns2:ReferenceParameters> TicketId xmlns="http://calculator.jaxws.developerworks" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"> 123456789 <ns2:ServiceName PortName="CalculatorPort"> ns4:Calculator
wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"> TicketId xmlns:ns4="http://calculator.jaxws.developerworks" xmlns="http://calculator.jaxws.developerworks" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:ns2="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:ns3="http://www.w3.org/2005/08/addressing">123456789 <wsa:To>http://L32H82K:9080/CalculatorService/Calculator <wsa:ReplyTo> <wsa:Address> http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous <wsa:MessageID>urn:uuid:14C1B8561B19D0B1261258998516715 <wsa:Action>http://calculator.jaxws.developerworks/addSubmission
addSubmission xmlns:ns2="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:ns3="http://www.w3.org/2005/08/addressing" xmlns:ns4="http://calculator.jaxws.developerworks"> 1 2
wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"> <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous <wsa:MessageID>urn:uuid:A9C31FB6B32D8A45DD1258998519215 <wsa:Action> http://calculator.jaxws.developerworks/addSubmissionResponse <wsa:RelatesTo>urn:uuid:14C1B8561B19D0B1261258998516715
addSubmissionResponse xmlns:ns2="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:ns3="http://www.w3.org/2005/08/addressing" xmlns:ns4="http://calculator.jaxws.developerworks"> 3

結束語

在本文中,我們介紹了 JAX-WS 2.1 規範中引入的與 WS-Addressing 有關的新概念,並展示瞭如何使用它們編寫一個有狀態 web 服務應用程式。除了支援 JAX-WS 2.1 所需的 WS-Addressing 1.0 規範外,我們還展示瞭如何擴充套件一個標準 API 來支援 WS-Addressing Member Submission 規範。

致謝

非常感謝 Esther Dovey 和 Sara Mitchell,他們為本書的撰寫提供了寶貴的意見。

IBM、WebSphere 和 Rational 是 International Business Machines Corporation 在美國和/或其他國家的商標。Java 和所有基於 Java 的商標和徽標是 Sun Microsystems, Inc. 在美國和/或其他國家的商標。其他公司、產品或服務名稱可能是其他公司的商標或服務標誌。

原文連結:http://www.ibm.com/developerworks/cn/webservices/ws-JAXsupport/index.html

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14789789/viewspace-671151/,如需轉載,請註明出處,否則將追究法律責任。

相關文章