Содержание


Поддержка JAX-WS 2.1 в соответствии со спецификацией WS-Addressing в WebSphere Application Server V7

Comments

Java™ API для Web-сервисов на базе XML (JAX-WS) представляет собой развитие предыдущего стандарта Java API для RPC на базе XML (JAX-RPC). JAX-RPC 1.0 и JAX-RPC 1.1 определяли API и соглашения для поддержки стиля обращения к Web-сервисам Remote Procedure Call (RPC). С тех пор, однако, Web-сервисы перешли на стиль, больше ориентированный на документы. JAX-WS 2.0 содержит полностью переработанные API и соглашения для поддержки этого нового стиля взаимодействия с Web-сервисами. Был сделан также особый упор на упрощение разработки при написании приложений Web-сервисов. В разделе "Ресурсы" приведены ссылки на статьи, в которых подробнее объясняется разница между JAX-WS и JAX-RPC.

JAX-WS 2.1 продолжает тенденцию к упрощению, начатую в JAX-WS 2.0, облегчая разработчикам создание полноценных Web-сервисов. Это достигается путем добавления в JAX-WS API прямой поддержки спецификации WS-Addressing. В этой статье мы приведем пример приложения, который показывает, как использовать эти новые интерфейсы API с поддержкой WS-Addressing для написания полноценного Web-сервиса, но сначала подробнее рассмотрим сами эти 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 – ERP). ERP включает в себя все сведения, необходимые для успешного попадания в конечную точку Web-сервиса. В API добавлен новый класс EndpointReference, цель которого – представление указателей конечных точек. Этот класс не предназначен непосредственно для разработчиков – им следует использовать лишь один из его подклассов.

API JAX-WS 2.1 содержит подкласс EndpointReference, называемый W3CEndpointReference. Он предназначен для представления ERP в соответствии со спецификацией WS-Addressing 1.0 Core. В WebSphere Application Server V7 имеется второй подкласс, SubmissionEndpointReference, для представления ERP в соответствии со спецификацией 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 позволяет разработчику указать любые свойства ERP. В листинге 1 мы указываем только адрес и параметр указателя, однако вместо адреса можно задать имя сервиса Web Services Description Language (WSDL) и имя конечной точки (порт). Процесс времени выполнения на основании этой комбинации имени сервиса и имени конечной точки определит конечную точку, для которой требуется указатель, и возвратит W3CEndpointReference с правильно заполненным адресом.

Если вместо W3CEndpointReference требуется SubmissionEndpointReference, то в 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();

При использовании комбинации имени сервиса и конечной точки с помощью классов W3CEndpointReferenceBuilder и SubmissionEndpointReferenceBuilder можно определить ERP для любой конечной точки, размещенной в том же приложении 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 единственное свойство, которое может быть указано явно - это параметр указателя. Элемент адреса заполняется средой времени выполнения вместе со всеми остальными свойствами. Если вместо этого требуется 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);

ERP, созданные в приложении, можно возвратить клиенту по сети. Затем клиент может использовать этот ERP для обращения к данной конечной точке по мере необходимости. Любые параметры указателя, включенные в ERP, будут автоматически добавлены в качестве заголовков в конверт SOAP, отправляемый в соответствии со спецификацией WS-Addressing. 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<Element> list =
   (List<Element>) context.getMessageContext().get(MessageContext.REFERENCE_PARAMETERS);

Затем этот список можно использовать для поиска параметров указателей. Если же приложение написано в соответствии со спецификацией WS-Addressing Member Submission, применять этот механизм для извлечения указателей нельзя. Вместо него следует применять класс EndpointReferenceManager, входящий в состав специального API WS-Addressing, предоставляемого WebSphere Application Server V7. Это показано в листинге 6. В данном случае для извлечения параметра указателя нужно указывать его имя.

Листинг 6. EndpointReferenceManager
import javax.xml.namespace.QName;
import com.ibm.websphere.wsaddressing.EndpointReferenceManager;

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

Функции

В JAX-WS 2.1 также введено понятие функций. Функция (feature) – это механизм, который позволяет разработчику клиента программно управлять особенностями его поведения. Все функции являются производными от класса WebServiceFeature. Это позволяет разработчику клиента передавать различные типы WebServiceFeature тем API со стороны клиента, которым они требуются. На рисунке 2 приведены функции, относящиеся к WS-Addressing.

Рисунок 2. Функции WS-Addressing
Функции WS-Addressing
Функции WS-Addressing

Для управления использованием WS-Addressing применяется класс AddressingFeature. Он позволяет разработчику разрешать/запрещать использование WS-Addressing клиентом. Если оно разрешено, клиент будет включать в отправляемые им сообщения SOAP заголовки WS-Addressing. Эти заголовки соответствуют пространству имен спецификации WS-Addressing 1.0 Core: http://www.w3.org/2005/08/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 интенсивно использует аннотации для упрощения разработки серверных приложений. Аннотация @Addressing – это эквивалент AddressingFeature для сервера. Она используется для разрешения/запрещения WS-Addressing для конечных точек Web-сервисов. Если режим WS-Addressing включен, то среда времени выполнения будет обрабатывать любые присутствующие во входящих запросах заголовки WS-Addressing в пространстве имен http://www.w3.org/2005/08/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, за исключением того, что относится к заголовкам WS-Addressing в пространстве имен http://schemas.xmlsoap.org/ws/2004/08/addressing. Эти классы показаны на рисунке 3.

Рисунок 3. Класс Addressing
Класс Addressing
Класс Addressing

В JAX-WS 2.1 также добавлены новые аннотации для поддержки отображения действий WS-Addressing на операции WSDL. Это аннотации @Action и @FaultAction. Аннотация @Action позволяет явно связывать действия с входными и выходными данными операции WSDL. Аннотация @FaultAction используется внутри аннотации @Action для связывания каждого отказа с определенным действием. Эти классы показаны на рисунке 4. Аннотация @Addressing обязательна при использовании аннотаций @Action и @FaultAction, в противном случае они будут игнорироваться.

Рисунок 4. Классы Fault и Action
Классы Fault и Action
Классы Fault и Action

Приложение

Теперь, когда мы завершили краткое описание появившиеся в JAX-WS 2.1 новых понятий, связанных с WS-Addressing, можно собрать их все вместе в полезном приложении. В представленном ниже приложении Calculator клиент делает запрос к Web-сервису, который складывает два числа и возвращает результат. Однако прежде чем клиент сможет это сделать, он должен получить от Web-сервиса билет – разрешение на отправку запроса на сложение двух чисел. Билет передается клиенту в качестве параметра ссылки внутри ERP. Затем клиент может использовать этот ERP для подачи запроса на сложение двух чисел.

Приложение Calculator доступно для загрузки. Приложение, предоставляемое в виде файла .ear, можно импортировать в IBM Rational® Application Developer V7.5.1 или установить на WebSphere Application Server V7. Чтобы успешно скомпилировать архив com. ibm. jaxws. thinclient_7. 0. 0. jar в Rational Application Developer, его нужно добавить в classpath созданных проектов CalculatorClient и CalculatorService. Этот архив можно найти в каталоге runtimes установки WebSphere Application Server.

Для начала посмотрим на WSDL нашего сервиса Calculator. Этот WSDL приведен в листинге 7. В нем вы увидите четыре операции: getTicket, add, getSubmissionTicket и addSubmission. Операция GetTicket возвращает ERP, который в качестве параметра указателя будет содержать наш билет. Операция сложения позволяет сложить два числа. Другие две операции выполняют те же функции, но с использованием спецификации WS-Addressing Member Submission вместо спецификации WS-Addressing 1.0 Core.

Листинг 7. Calculator.wsdl
<?xml version="1.0" encoding="UTF-8"?>
<definitions targetNamespace="http://calculator.jaxws.developerworks"
             name="Calculator"
             xmlns="http://schemas.xmlsoap.org/wsdl/"
             xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
             xmlns:tns="http://calculator.jaxws.developerworks"
             xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
    <types>
        <xsd:schema>
            <xsd:import namespace="http://calculator.jaxws.developerworks"
                        schemaLocation="Calculator_schema1.xsd"/>
        </xsd:schema>
    </types>
    <message name="getTicket">
        <part name="parameters" element="tns:getTicket"/>
    </message>
    <message name="getTicketResponse">
        <part name="parameters" element="tns:getTicketResponse"/>
    </message>
    <message name="add">
        <part name="parameters" element="tns:add"/>
    </message>
    <message name="addResponse">
        <part name="parameters" element="tns:addResponse"/>
    </message>
    <message name="getSubmissionTicket">
        <part name="parameters" element="tns:getSubmissionTicket"/>
    </message>
    <message name="getSubmissionTicketResponse">
        <part name="parameters" element="tns:getSubmissionTicketResponse"/>
    </message>
    <message name="addSubmission">
        <part name="parameters" element="tns:addSubmission"/>
    </message>
    <message name="addSubmissionResponse">
        <part name="parameters" element="tns:addSubmissionResponse"/>
    </message>
    <message name="AddNumbersException">
        <part name="fault" element="tns:AddNumbersException"/>
    </message>
    <portType name="Calculator">
        <operation name="getTicket">
            <input message="tns:getTicket"/>
            <output message="tns:getTicketResponse"/>
        </operation>
        <operation name="getSubmissionTicket">
            <input message="tns:getSubmissionTicket"/>
            <output message="tns:getSubmissionTicketResponse"/>
        </operation>
        <operation name="add">
            <input wsaw:Action="http://calculator.jaxws.developerworks/add" 
                   message="tns:add"/>
            <output wsaw:Action="http://calculator.jaxws.developerworks/addResponse" 
                    message="tns:addResponse"/>
            <fault message="tns:AddNumbersException" name="AddNumbersException"
                   wsaw:Action="http://calculator.jaxws.developerworks/addFault"/>
        </operation>
        <operation name="addSubmission">
            <input wsaw:Action="http://calculator.jaxws.developerworks/addSubmission"
                   message="tns:addSubmission"/>
            <output 
               wsaw:Action="http://calculator.jaxws.developerworks/addSubmissionResponse" 
                    message="tns:addSubmissionResponse"/>
            <fault message="tns:AddNumbersException" name="AddNumbersException"
                wsaw:Action="http://calculator.jaxws.developerworks/addSubmissionFault"/>
        </operation>
    </portType>
    <binding name="CalculatorPortBinding" type="tns:Calculator">
        <wsaw:UsingAddressing/>
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
        <operation name="getTicket">
            <soap:operation soapAction=""/>
            <input>
                <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
        </operation>
        <operation name="getSubmissionTicket">
            <soap:operation soapAction=""/>
            <input>
                <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
        </operation>
        <operation name="add">
            <soap:operation soapAction=""/>
            <input>
                <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
            <fault name="AddNumbersException">
                <soap:fault name="AddNumbersException" use="literal"/>
            </fault>
        </operation>
        <operation name="addSubmission">
            <soap:operation soapAction=""/>
            <input>
                <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
            <fault name="AddNumbersException">
                <soap:fault name="AddNumbersException" use="literal"/>
            </fault>
        </operation>
    </binding>
    <service name="Calculator">
        <port name="CalculatorPort" binding="tns:CalculatorPortBinding">
            <soap:address location="http://localhost:9080/CalculatorService/Calculator"/>
        </port>
    </service>
</definitions>

Service Endpoint Interface (SEI) можно сгенерировать, используя этот WSDL и схему Calculator_schema1.xsd из ear-файла приложения. Это делается с помощью инструмента wsimport, который находится в подкаталоге bin установочного каталога WebSphere Application Sever. Сгенерированный SEI показан в листинге 8. Он содержит четыре метода: getTicket(), add(), getSubmissionTicket() и addSubmission(). Метод getTicket() возвращает W3CEndpointReference, а метод getSubmissionTicket()SubmissionEndpointReference. Методы add() и addSubmission() возвращают значение int и содержат аннотацию @Action. В аннотацию @Action входит аннотация @FaultAction, которая отображает AddNumbersException на действие.

Листинг 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",
            output = "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",
            output = "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() создает ERP, содержащий билет. Методы 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;
    }
}

В листинге 10 показан клиент, демонстрирующий использование нашего сервиса Calculator. Он рассчитан на применение обеих спецификаций WS-Addressing 1.0 и WS-Addressing Member Submission. Для этого клиент обращается к сервису, используя методы get ticket для получения ERP, который содержит билет в качестве параметра указателя. Затем он использует этот ERP для отправки запроса к соответствующему методу add, чтобы сложить два числа. При использовании ERP содержащийся в нем параметр указателя будет автоматически включен в запрос в качестве заголовка 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();

            // Извлечение билета W3CEndpointRefence
            W3CEndpointReference epr = port1.getTicket();
            Calculator port2 = epr.getPort(Calculator.class,
                    new AddressingFeature());

            // Сложение чисел с использованием билета W3CEndpointRefence
            int answer = port2.add(value0, value1);
            System.out
                    .println("The answer using a W3CEndpointRefence ticket is: "
                            + answer);
            // Извлечение билета SubmissionEndpointReference
            SubmissionEndpointReference submissionEpr = port1
                    .getSubmissionTicket();
            port2 = submissionEpr.getPort(Calculator.class,
                    new SubmissionAddressingFeature());

            // Сложение чисел с использованием 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, поскольку в методе getTicket() из листинга 8 не было аннотации @Action. Шаблон действия по умолчанию спецификации WS-Addressing задает способ определения действия на основе свойств операции WSDL.

Листинг 11. Запрос GetTicket
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
        <wsa:To>http://localhost:9080/CalculatorService/Calculator</wsa:To>
        <wsa:MessageID>urn:uuid:14C1B8561B19D0B1261258998512414</wsa:MessageID>
        <wsa:Action>
            http://calculator.jaxws.developerworks/Calculator/getTicketRequest
        </wsa:Action>
    </soapenv:Header>
    <soapenv:Body>
        <ns4: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"/>
    </soapenv:Body>
</soapenv:Envelope>

В листинге 12 приведено ответное сообщение. Обратите внимание, что в ReferenceParameters возвращенного EndpointReference содержится TicketId и что по-прежнему используется шаблон действия по умолчанию. Заметьте также, что для EndpointReference используется пространство имен спецификации WS-Addressing 1.0 Core, как и для заголовков WS-Addressing последующих запроса и ответа с использованием этого EndpointReference.

Листинг 12. Ответ GetTicket
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/>
    <soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
        <wsa:Action>
            http://calculator.jaxws.developerworks/Calculator/getTicketResponse
        </wsa:Action>
        <wsa:RelatesTo>urn:uuid:14C1B8561B19D0B1261258998512414</wsa:RelatesTo>
    </soapenv:Header>
    <soapenv:Body>
        <ns4: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">
            <return>
                <ns3:Address>
                    http://L32H82K:9080/CalculatorService/Calculator
                </ns3:Address>
                <ns3:ReferenceParameters>
                    <ns4:TicketId
                         xmlns="http://calculator.jaxws.developerworks" 
                         xmlns:wsa="http://www.w3.org/2005/08/addressing">
                        123456789
                    </ns4:TicketId>
                </ns3:ReferenceParameters>
                <ns3:Metadata>
                    <wsam:ServiceName
                         xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata"
                         xmlns:axis2ns5="http://calculator.jaxws.developerworks"
                         xmlns:wsa="http://www.w3.org/2005/08/addressing"
                         EndpointName="CalculatorPort">
                        axis2ns5:Calculator
                    </wsam:ServiceName>
                </ns3:Metadata>
            </return>
        </ns4:getTicketResponse>
   </soapenv:Body>

В листинге 13 мы видим сообщение, отправленное при обращении к методу add(). Заметьте, что в заголовки сообщения входит TicketId. Отметим также, что действие совпадает с входным действием в аннотации @Action метода add из листинга 8.

Листинг 13. Запрос Add
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
        <ns4: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</ns4:TicketId>
        <wsa:To>http://L32H82K:9080/CalculatorService/Calculator</wsa:To>
        <wsa:MessageID>urn:uuid:14C1B8561B19D0B1261258998516588</wsa:MessageID>
        <wsa:Action>http://calculator.jaxws.developerworks/add</wsa:Action>
    </soapenv:Header>
    <soapenv:Body>
        <ns4: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">
            <arg0>1</arg0>
            <arg1>2</arg1>
        </ns4:add>
    </soapenv:Body>
</soapenv:Envelope>

В листинге 14 приведено окончательное ответное сообщение с ожидаемым результатом и выходным действием, заданными в листинге 8.

Листинг 14. Ответ Add
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
        <wsa:Action>http://calculator.jaxws.developerworks/addResponse</wsa:Action>
        <wsa:RelatesTo>urn:uuid:14C1B8561B19D0B1261258998516588</wsa:RelatesTo>
    </soapenv:Header>
    <soapenv:Body>
        <ns4: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">
            <return>3</return>
        </ns4:addResponse>
    </soapenv:Body>
</soapenv:Envelope>

В листинге 15 представлены соответствующие сообщения, отправленные при использовании EndpointReference в соответствии со спецификацией WS-Addressing Member Submission.

Листинг 15. Спецификация WS-Addressing Member Submission
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
        <wsa:To>http://localhost:9080/CalculatorService/Calculator</wsa:To>
        <wsa:MessageID>urn:uuid:14C1B8561B19D0B1261258998516636</wsa:MessageID>
        <wsa:Action>
        http://calculator.jaxws.developerworks/Calculator/getSubmissionTicketRequest
        </wsa:Action>
    </soapenv:Header>
    <soapenv:Body>
        <ns4: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"/>
    </soapenv:Body>
</soapenv:Envelope>

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
        <wsa:Action>
        http://calculator.jaxws.developerworks/Calculator/getSubmissionTicketResponse
        </wsa:Action>
        <wsa:RelatesTo>urn:uuid:14C1B8561B19D0B1261258998516636</wsa:RelatesTo>
    </soapenv:Header>
    <soapenv:Body>
        <ns4: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">
            <return>
                <ns2:Address>
                    http://L32H82K:9080/CalculatorService/Calculator
                </ns2:Address>
                <ns2:ReferenceParameters>
                    <ns4:TicketId xmlns="http://calculator.jaxws.developerworks"
                         xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
                        123456789
                    </ns4:TicketId>
                </ns2:ReferenceParameters>
                <ns2:ServiceName PortName="CalculatorPort">
                    ns4:Calculator
                </ns2:ServiceName>
            </return>
        </ns4:getSubmissionTicketResponse>
    </soapenv:Body>
</soapenv:Envelope>

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
        <ns4: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</ns4:TicketId>
        <wsa:To>http://L32H82K:9080/CalculatorService/Calculator</wsa:To>
        <wsa:ReplyTo>
            <wsa:Address>
                http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
            </wsa:Address>
        </wsa:ReplyTo>
        <wsa:MessageID>urn:uuid:14C1B8561B19D0B1261258998516715</wsa:MessageID>
        <wsa:Action>http://calculator.jaxws.developerworks/addSubmission</wsa:Action>
    </soapenv:Header>
    <soapenv:Body>
        <ns4: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">
            <arg0>1</arg0>
            <arg1>2</arg1>
        </ns4:addSubmission>
    </soapenv:Body>
</soapenv:Envelope>

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Header xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
        <wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
        <wsa:MessageID>urn:uuid:A9C31FB6B32D8A45DD1258998519215</wsa:MessageID>
        <wsa:Action>
            http://calculator.jaxws.developerworks/addSubmissionResponse
        </wsa:Action>
        <wsa:RelatesTo>urn:uuid:14C1B8561B19D0B1261258998516715</wsa:RelatesTo>
    </soapenv:Header>
    <soapenv:Body>
        <ns4: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">
            <return>3</return>
        </ns4:addSubmissionResponse>
    </soapenv:Body>
</soapenv:Envelope>

Заключение

В этой статье мы представили новые понятия, относящиеся к спецификации WS-Addressing, добавленные в спецификацию JAX-WS 2.1, и продемонстрировали, как их можно использовать для написания полноценных приложений Web-сервисов. Мы показали также, как был расширен стандартный API в целях поддержки спецификации WS-Addressing Member Submission в дополнение к спецификациям WS-Addressing 1.0, которые требуются для JAX-WS 2.1.


Ресурсы для скачивания


Похожие темы


Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=SOA и web-сервисы, WebSphere
ArticleID=643342
ArticleTitle=Поддержка JAX-WS 2.1 в соответствии со спецификацией WS-Addressing в WebSphere Application Server V7
publish-date=03252011