Продолжается подписка на наши издания! Вы не забыли подписаться?

Разработка Web-сервисов на платформе Java 2 Enterprise Edition (J2EE) 1.4

Автор: Qusay H. Mahmoud

Обзор Web-сервисов
J2EE 1.4 SDK
JSR 109
Web-сервисы J2EE
Работа с JAX-RPC
Создание Web-сервисов
1. Дизайн и кодирование endpoint-интерфейса Web-сервиса
2. Реализация endpoint-интерфейса сервиса
3. Создание конфигурационного файла
4. Генерирование mapping-файлов
5. Упаковка сервиса в WAR-файл и его распространение
Создание клиентов Web-сервиса.
1. Статическая заглушка (static stub)
2. Динамический прокси.
Консольный клиент – J2EE-приложение
Клиент на базе броузера
Заключение

В Java 2 Platform, Enterprise Edition (J2EE) version 1.4 появилась возможность интеграции с Web-сервисами. Web-сервисы теперь являются одним из способов предоставления услуг платформы J2EE. Существующие J2EE-компоненты могут быть легко представлены в виде Web-сервисов. Web-сервисам теперь доступны многие преимущества платформы J2EE, включая переносимость, масштабируемость, надежность и отсутствие привязки к одному вендору. Например, J2EE-контейнеры предоставляют поддержку транзакций, подключение к БД, управление жизненным циклом и другие службы – масштабируемые и не требующие кодирования.

Платформа J2EE предоставляет поддержку Web-сервисов посредством JAX-RPC 1.1 API, которое можно использовать для создания конечных точек (endpoints) Web-сервисов на основе SOAP. JAX-RPC 1.1 поддерживает взаимодействие с Web-сервисами, основанными на WSDL и SOAP. Платформа J2EE поддерживает также и JSR 109, надстройку над JAX-RPC, которая представляет собой программную модель для реализации Web-сервисов и на развертывание Web-сервисов на платформе J2EE 1.4. Кроме всего прочего, J2EE 1.4 поддерживает WS-I Basic Profile. Это значит, что разработанные на платформе J2EE Web-сервисы являются переносимыми не только между реализациями J2EE, но и могут взаимодействовать с любыми Web-сервисами, соответствующим стандартам WS-I.

Для разработки Web-сервисов разработчику обычно нужны обширные знания XML-стандартов и протоколов (таких, как WSDL и SOAP), а также немалый опыт программирования. На платформе J2EE 1.4, однако, для разработки Web-сервисов не требуется знания WSDL и SOAP. Преобразование между Java и этими XML-стандартами берет на себя runtime-система Web-сервисов, тем самым освобождая программиста от низкоуровневых деталей.

Эта статья содержит пошаговые инструкции по разработке, развертыванию и использованию Web-сервисов с использованием J2EE 1.4 SDK и минимумом программирования. Ниже вы найдете:

Обзор Web-сервисов

Web-сервисы – это приложения, предназначенные для поддержки межмашинного взаимодействия по сети. Это взаимодействие осуществляется с помощью набора открытых XML-стандартов, таких, как WSDL, SOAP и UDDI. Эти стандарты определяют общий подход к определению, публикации и использованию Web-сервисов. Если вы до сих пор ничего не знаете об этих технологиях, не стоит волноваться: J2EE 1.4 позволяет создавать Web-сервисы абсолютно ничего не зная обо всем этом. На рисунке 1 показано, какие роли играют Java API for XML Registries (JAXR) и Java API for XML Remote Procedure Calls (JAX-RPC) в публикации, обнаружении и использовании Web-сервисов.


Рисунок 1. Модель Publish-Discover-Invoke в J2EE 1.4.

С точки зрения архитектора ПО, Web-сервис можно рассматривать как сервис-ориентированную архитектуру, состоящую из служб, общающихся друг с другом (и с клиентом) через строго определенные интерфейсы. Одно из достоинств сервис-ориентированной архитектуры состоит в том, что она допускает разработку свободно связанных приложений, которые можно распространять по сети и к которым можно обращаться с любого клиента.

В J2EE 1.4 SDK имеются средства, позволяющие быстро создавать, тестировать и разворачивать Web-сервисы и клиентов, взаимодействующих с другими Web-сервисами и клиентами, работающими как на платформе Java, так и на других платформах. Кроме того, они позволяют представить в виде Web-сервисов уже имеющиеся J2EE-приложения. Сервлеты и EJB-компоненты могут быть представлены в виде Web-сервисов, к которым впоследствии могут получить доступ как Java-, так и не Java-клиенты. Сами J2EE-приложения могут выступать в качестве клиентов Web-сервисов, и обращаться к другим Web-сервисам независимо от того, как они реализованы.

J2EE 1.4 SDK

Лучший способ узнать, что нового появилось на платформе J2EE – скачать J2EE 1.4 SDK, и разобраться в этом самому. В J2EE 1.4 SDK входит следующее:

По умолчанию J2EE 1.4 SDK на платформе Windows устанавливается в c:\sun\AppServer, а JDK 1.4.2_01 в c:\sun\AppServer\jdk.

После установки нужно включить в переменную среды Path пути к каталогам c:\sun\AppServer\bin и c:\sun\AppServer\jdk\bin. В этих каталогах содержится несколько инструментальных средств (включая wscompile), генерирующих клиентские заглушки или серверные каркасы, или же WSDL-описание на основе определения интерфейса сервиса.

JSR 109

Процесс разработки и развертывания Web-сервиса тесно связан с runtime-системой. Например, развертывание Web-сервиса на Apache Axis отличается от развертывания того же Web-сервиса на Apache SOAP или любой другой платформе. Спецификация Java Community Process (JCP) JSR 109 (Implementing Enterprise Web Services) определяет создание переносимых Web-сервисов в среде J2EE 1.4. Эта спецификация включает:

Web-сервисы J2EE

JAX-RPC – это Java API для XML RPC. Его можно использовать для создания клиентов и Web-сервисов, использующих XML и RPC. RPC работает через такие XML-протоколы, как SOAP, определяющие структуру обертки, правила кодирования и соглашения по представлению RPC-вызовов и ответов на них, передаваемых в виде SOAP-сообщений через HTTP. Преимущество JAX-RPC состоит в том, что сложность SOAP-сообщений скрыта от разработчика. Вот как это работает:

Разработчик указывает удаленные процедуры (Web-сервисы), которые могут быть вызваны клиентами через Java-интерфейс, и реализует этот интерфейс. Для клиента Web-сервис выглядит как набор методов, реализующих бизнес-логику от имени клиента. Клиент обращается к Web-сервису, используя Service Endpoint Interface, как определено в JAX-RPC. Разработчики клиента создают автоматически генерирующееся прокси (локальный объект, представляющий удаленный сервис), а затем просто вызывают методы прокси. Разработчику не нужно волноваться насчет генерирования или разбора SOAP-сообщений, все это выполняет runtime JAX-RPC. Заметьте, что J2EE Web-сервисы могут быть вызваны любым Web-клиентом, и что любой J2EE-клиент может обратиться к любому Web-сервису.

Чтобы получить представление о происходящем за кулисами, рассмотрим рисунок 2, где показано, как Java-клиент общается с Java Web-сервисом на платформе J2EE 1.4. Заметим, что J2EE-приложение может использовать Web-сервисы, опубликованные другими провайдерами, независимо от того, как именно они реализованы. В случае не-Java клиентов и сервисов схема слегка изменится. Как уже говорилось, все, что происходит между вызовом и получением ответа, скрыто от глаз. Вы работаете с привычной семантикой языка Java, то есть с вызовами методов и типами данных. Нет причины думать об отображении Java на XML и наоборот, или о конструировании SOAP-сообщений. Вся эта низкоуровневая работа остается за сценой, позволяя сконцентрироваться на высокоуровневых проблемах.


Рисунок 2. Java-клиент, вызывающий J2EE Web-сервис.

Заметьте, что клиент Web-сервиса никогда не обращается к сервису непосредственно, но всегда – через контейнер. Это хорошо, поскольку позволяет Web-сервису использовать функциональность, предоставляемую контейнером – то есть безопасность, ведение логов и гарантии QoS.

Работа с JAX-RPC

При работе с JAX-RPC нужно помнить, что он отображает типы Java на определения XML/WSDL. Конечно, хорошо, что не нужно знать детали этих отображений, но следует понимать, что в JAX-RPC не все классы J2EE могут быть использованы как параметры методов или возвращаемые значения. JAX-RPC поддерживает следующие примитивные типы данных: : boolean, byte, double, float, int, long, short и массивы. Кроме того, поддерживаются следующие классы-обертки и классы-утилиты:

java.lang.Boolean
java.lang.Byte
java.lang.Double
java.lang.Float
java.lang.Integer
java.lang.Long
java.lang.Short
java.lang.String
java.math.BigDecimal
java.math.BigInteger
java.net.URI
java.util.Calendar
java.util.Date

JAX-RPC также поддерживает нечто под названием value type, что означает класс, который может передаваться между клиентом и сервисом в качестве параметра или возвращаемого значения. Value type должен отвечать следующим правилам:

Создание Web-сервисов

Создание Web-сервисов в стиле XML-RPC с использованием платформы J2EE 1.4 можно разбить на пять этапов:

  1. Дизайн и кодирование endpoint-интерфейса Web-сервиса.
  2. Реализация интерфейса.
  3. Создание конфигурационного файла.
  4. Генерирование необходимых файлов.
  5. Использование deploytool для упаковки сервиса в WAR-файл и его распространения.

1. Дизайн и кодирование endpoint-интерфейса Web-сервиса

Первым шагом в создании Web-сервиса является разработка и кодирование endpoint-интерфейса Web-сервиса, где объявляются методы, которые может вызывать удаленный клиент. При разработке такого интерфейса убедитесь, что:

Для начала создайте любой каталог по вашему выбору. Для следующего примера я создал каталог apps в c:\sun\AppServer, и подкаталог build в нем. Каталог apps содержит .java-файлы, build содержит .class, а также остальные файлы, которые будут сгенерированы автоматически.

Web-сервис, который я собираюсь создать, будет суммировать два числа. Ничего особенного, но достаточно, чтобы показать, как создаются, распространяются и используются Web-сервисы. Листинг 1 показывает endpoint-интерфейс сервиса, обычный Java-интерфейс, расширяющий интерфейс java.rmi.Remote. В этом интерфейсе, MathFace, объявляется один метод, add, принимающий два целочисленных значения и возвращающий целочисленное значение, представляющее собой сумму двух целочисленных параметров.

Листинг 1: MathFace.java

package math;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface MathFace extends Remote {
  public int add(int a, int b) throws RemoteException;
}

2. Реализация endpoint-интерфейса сервиса

Следующий шаг – это реализация интерфейса MathFace, определенного в листинге 1, весьма несложная, как вы можете видеть в листинге 2:

Листинг 2: MathImpl.java

package math;

import java.rmi.RemoteException;

public class MathImpl implements MathFace 
{
  public int add(int a, int b) throws RemoteException 
  {
    return a + b;
  }
}

Теперь нужно скомпилировать .java-файлы, указав, что .class-файлы нужно поместить в каталог build, созданный ранее. Это делается с помощью опции компилятора –d:

prompt> javac -d build Math*.java 

3. Создание конфигурационного файла

Следующий шаг – создание конфигурационного файла, который передается утилите wscompile. Я назвал этот файл config.xml (и сохранил его в каталоге app). В этом конфигурационном файле (см. листинг 3) содержится имя сервиса, его пространство имен, название пакета (в данном случае math) и имя интерфейса (MathFace).

Листинг 3: config.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration
  xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
  <service
      name="MyFirstService"
      targetNamespace="urn:Foo"
      typeNamespace="urn:Foo"
      packageName="math">
      <interface name="math.MathFace"/>
  </service>
</configuration>

Этот файл приказывает wscompile создать WSDL-файл со следующей информацией:

4. Генерирование mapping-файлов

Теперь с помощью утилиты wscompile нужно сгенерировать необходимые файлы. Это делается с помощью следующей команды из каталога apps:

prompt> wscompile -define -mapping build/mapping.xml -d 
  build -nd build -classpath build config.xml 

Эта команда считывает созданный ранее файл config.xml и создает файлы MyFirstService.wsdl и mapping.xml в каталоге build. Опции командной строки и флаги:

Хотите – верьте, хотите – нет, но вы только что создали Web-сервис, готовый к установке.

WSDL-файл MyFirstService.wsdl, сгенерированный утилитой wscompile, приведен в листинге 4. Этот файл содержит XML-описание (основанное на WSDL) сервиса, который может быть вызван клиентом. Чтобы разобраться в деталях файла, нужно некоторое знание WSDL, но поскольку вам не нужно разбираться во всех деталях, можете об этом не беспокоиться.

Листинг 4: MyFirstService.wsdl

<?xml version="1.0" encoding="UTF-8"?>

<definitions name="MyFirstService" targetNamespace="urn:Foo" 
    xmlns:tns="urn:Foo"
    xmlns="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
  <types/>
  <message name="MathFace_add">
    <part name="int_1" type="xsd:int"/>
    <part name="int_2" type="xsd:int"/></message>
  <message name="MathFace_addResponse">
    <part name="result" type="xsd:int"/></message>
  <portType name="MathFace">
    <operation name="add" parameterOrder="int_1 int_2">
      <input message="tns:MathFace_add"/>
      <output message="tns:MathFace_addResponse"/></operation></portType>
  <binding name="MathFaceBinding" type="tns:MathFace">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" 
                  style="rpc"/>
    <operation name="add">
      <soap:operation soapAction=""/>
      <input>
        <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
          use="encoded" namespace="urn:Foo"/>
      </input>
      <output>
        <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 
                   use="encoded" namespace="urn:Foo"/>
      </output>
    </operation></binding>
  <service name="MyFirstService">
    <port name="MathFacePort" binding="tns:MathFaceBinding">
      <soap:address location="REPLACE_WITH_ACTUAL_URL"/>
    </port>
  </service>
</definitions>

Mapping-файл mapping.xml, сгенерированный утилитой wscompile, приведен в листинге 5. Этот файл следует стандарту отображений Java <-> WSDL. Как видите, структура mapping-файла JAX-RPC очень похожа на структуру WSDL-файла – обратите внимание на связь между Java-пакетами и пространствами имен XML. Каждый сервис представлен элементом service-interface-mapping. Этот элемент содержит отображение полностью квалифицированного имени класса интерфейса сервиса, а также имена сервиса и порта в WSDL. Кроме того, JAX-RPC mapping-файл содержит отображения WSDL-связываний, имен портов WSDL, WSDL-сообщений и т.д. И опять же, хорошо то, что для работы с Web-сервисами вам в этом разбираться не нужно!

Листинг 5: mapping.xml

<?xml version="1.0" encoding="UTF-8"?>
<java-wsdl-mapping version="1.1" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
    http://www.ibm.com/webservices/xsd/j2ee_jaxrpc_mapping_1_1.xsd">
  <package-mapping>
    <package-type>math</package-type>
    <namespaceURI>urn:Foo</namespaceURI>
  </package-mapping>
  <package-mapping>
    <package-type>math</package-type>
    <namespaceURI>urn:Foo</namespaceURI>
  </package-mapping>
  <service-interface-mapping>
    <service-interface>math.MyFirstService</service-interface>
    <wsdl-service-name 
      xmlns:serviceNS="urn:Foo">serviceNS:MyFirstService</wsdl-service-name>
    <port-mapping>
      <port-name>MathFacePort</port-name>
      <java-port-name>MathFacePort</java-port-name>
    </port-mapping>
  </service-interface-mapping>
  <service-endpoint-interface-mapping>
    <service-endpoint-interface>math.MathFace</service-endpoint-interface>
    <wsdl-port-type xmlns:portTypeNS="urn:Foo">portTypeNS:MathFace
    </wsdl-port-type>
    <wsdl-binding xmlns:bindingNS="urn:Foo">bindingNS:MathFaceBinding
    </wsdl-binding>
    <service-endpoint-method-mapping>
      <java-method-name>add</java-method-name>
      <wsdl-operation>add</wsdl-operation>
      <method-param-parts-mapping>
        <param-position>0</param-position>
        <param-type>int</param-type>
        <wsdl-message-mapping>
          <wsdl-message 
            xmlns:wsdlMsgNS="urn:Foo">wsdlMsgNS:MathFace_add</wsdl-message>
          <wsdl-message-part-name>int_1</wsdl-message-part-name>
          <parameter-mode>IN</parameter-mode>
        </wsdl-message-mapping>
      </method-param-parts-mapping>
      <method-param-parts-mapping>
        <param-position>1</param-position>
        <param-type>int</param-type>
        <wsdl-message-mapping>
          <wsdl-message 
            xmlns:wsdlMsgNS="urn:Foo">wsdlMsgNS:MathFace_add</wsdl-message>
          <wsdl-message-part-name>int_2</wsdl-message-part-name>
          <parameter-mode>IN</parameter-mode>
        </wsdl-message-mapping>
      </method-param-parts-mapping>
      <wsdl-return-value-mapping>
        <method-return-value>int</method-return-value>
        <wsdl-message 
          xmlns:wsdlMsgNS="urn:Foo">wsdlMsgNS:MathFace_addResponse
          </wsdl-message>
        <wsdl-message-part-name>result</wsdl-message-part-name>
      </wsdl-return-value-mapping>
    </service-endpoint-method-mapping>
  </service-endpoint-interface-mapping>
</java-wsdl-mapping>

5. Упаковка сервиса в WAR-файл и его распространение

JAX-RPC Web-сервис – это на самом деле сервлет (или, в терминологии J2EE, Web-компонент), следовательно, для его упаковки, создания всех необходимых конфигурационных файлов и последующего распространения можно использовать deploytool. Далее в статье я буду считать, что сервис доступен по URL http://localhost:8080/math-service/math.

Создание клиентов Web-сервиса.

Теперь нужно создать клиента, обращающегося к только что созданному Web-сервису. Клиент вызывает Web-сервис так же, как и локальный метод. Существует три типа клиентов Web-сервисов:

  1. Статическая заглушка (stub). Java-класс, статически связанный с endpoint-интерфейсом сервиса. Заглушка, или клиентский proxy-объект, определяет все методы, определенные в endpoint-интерфейсе сервиса. Таким образом, клиент может вызывать методы Web-сервиса непосредственно через заглушку. Преимущество такого подхода заключается в том, что он прост в реализации. Недостаток же в том, что малейшее изменение определения Web-сервиса делает заглушку бесполезной… и означает, что ее нужно генерировать заново. Используйте этот способ, если не собираетесь изменять определение Web-сервиса в будущем.
  2. Динамическое прокси. Поддерживает endpoint-интерфейс сервиса динамически во время исполнения. Данный метод не требует генерации кода статической заглушки. Прокси создается во время исполнения и требует наличия экземпляра endpoint-интерфейса сервиса. Что же касается вызова, тут все так же, как и с заглушкой. Полезно в случае тестирования Web-сервиса, определение которого изменяется. Динамическое прокси нужно пересоздавать, но не генерировать заново, как в случае с заглушкой.
  3. Динамический интерфейс вызова (Dynamic Invocation Interface, DII): Определяет экземпляр объекта javax.xml.rpc.Call для динамического вызова. В отличие от заглушек и прокси должен быть сконфигурирован перед использованием. Клиент должен сообщить ему имя операции, имена и типы параметров, а также тип порта. Главное достоинство состоит в том, что, поскольку Call ни к чему не привязан, на клиентскую сторону никак не влияют изменения определения Web-сервиса. Рассмотрение DII-клиента выходит за рамки этой статьи.


Рисунок 3. MyFirstService.wsdl.

1. Статическая заглушка (static stub)

Давайте создадим автономного клиента, вызывающего метод add Web-сервиса MyFirstService. Он производит вызов через заглушку, или локальный объект, действующий как клиентский прокси удаленного сервиса. Он называется статической заглушкой, поскольку заглушка генерируется до исполнения утилитой wscompile. Перед разработкой самого Java-клиента нужно создать конфигурационный XML-файл (см. листинг 6), в котором указано местоположение WSDL-файла (MyFirstService.wsdl). Создайте в каталоге apps подкаталог static-stub (в котором будут храниться .xml и .java файлы), а в нем – подкаталог build.

Листинг 6: config-wsdl.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration
  xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
  <wsdl location="http://localhost:8080/math-service/math?WSDL"
       packageName="sstub"/>
</configuration>

Как видите, местоположение WSDL-файла для MyFirstService.wsdl указано в URL http://localhost:8080/math-service/math?WSDL. Если обратиться по этому URL, можно увидеть что-то подобное изображенному на рисунке 3 (Стр: 31 предполагая, что вы установили web-сервис, разработанный ранее).

После создания конфигурационного файла можно сгенерировать и клиентские заглушки командой:

prompt> wscompile -gen:client -d build -classpath build config-wsdl.xml 

Эта команда читает MyFirstService.wsdl, а затем генерирует файлы, основываясь на информации из WSDL-файла и флагов командной строки. Флаг -gen:client говорит wscompile сгенерировать заглушку и остальные необходимые файлы, такие, как сериализаторы и value types. Флаги –d говорят утилите записать результат в каталог build.

Теперь все готово для создания клиента. Пример реализации показан в листинге 7. Заметьте, что используется заглушка, сгенерированная ранее, а для поиска сервиса используется адрес его endpoint-а http://localhost:8080/math-service/math. Как видите, объект-заглушка создается с использованием объекта MathFirstService_Impl, сгенерированного утилитой wscompile, задается адрес endpoint-а, используемого заглушкой для доступа к сервису, затем заглушка привязывается к сервису MathFace, и наконец, вызывается метод add.

Листинг 7: MathClient.java

package sstub;

import javax.xml.rpc.Stub;

public class MathClient {

   private String endpointAddress;

   public static void main(String argv[]) {
      try 
      {
         // Вызов createProxy() для создания объекта-заглушки
         Stub stub = createProxy();

         // Задание endpoint-адреса, используемого 
         // заглушкой при доступе к сервису
         stub._setProperty(javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY, 
           "http://localhost:8080/math-service/math");

         MathFace math = (MathFace) stub;

         // Вызов метода add
         System.out.println(math.add(12, 24));
      } 
      catch (Exception ex) 
      {
         ex.printStackTrace();
      }
   }

   private static Stub createProxy() 
   {
      // Создание объекта-заглушки
      // Заметьте, что MyFirstService_Impl, 
      // созданный wscompile, зависит от реализации
      return (Stub) (new MyFirstService_Impl().getMathFacePort());
   }
}

Теперь можно скомпилировать MathClient.java и записать результат в каталог build.

C:\sun\APPSER~1\apps\static-stub> javac -classpath build -d build MathClient.java 

Запустите клиента:

C:\sun\APPSER~1\apps\static-stub> java -classpath build sstub.MathClient 

2. Динамический прокси.

В этом случае клиент вызывает удаленную процедуру через динамический прокси или класс, создаваемый во время исполнения. Заметьте, что в случае статической заглушки код полагается на класс, зависящий от реализации. В данном же случае (динамического прокси) это ограничение отсутствует. Первым делом нужно создать конфигурационный файл. Можно использовать приведенный в листинге 6, изменив packageName на dynamicproxy или что-нибудь вроде этого. Создайте в каталоге apps подкаталог dynamic-proxy, а в нем – подкаталог build.

Теперь сгенерируйте нужные интерфейсы с помощью wscompile.

C:\Sun\APPSER~1\apps\dynamic-proxy> wscompile -import -d build -nd build -f:norpc structures -classpath build config-wsdl.xml 

После всего этого можно создать клиента. Листинг 8 содержит пример реализации. В нем создается экземпляр фабрики сервисов. Фабрика сервисов используется для создания объекта сервиса, который действует как фабрика прокси. Как видите, метод createService принимает два параметра: URL WSDL-файлов и объект QName, кортеж, представляющий квалифицированное имя сервиса. Затем создается прокси-объект, и, наконец, вызывается метод add этого объекта.

Листинг 8: MathClient.java

package dynamicproxy;

import java.net.URL;
import javax.xml.rpc.Service;
import javax.xml.rpc.JAXRPCException;
import javax.xml.namespace.QName;
import javax.xml.rpc.ServiceFactory;
import dynamicproxy.FirstIF;


public class MathClient {

  public static void main(String[] args) 
  {
    try 
    {
      String nameSpaceUri = "urn:Foo";
      String serviceName = "MyFirstService";
      String portName = "MathFacePort";

      // Указываем местоположение  WSDL-файла
      URL url = new URL("http://localhost:8080/math-service/math?WSDL");

      // Создаем экземпляр фабрики сервиса
      ServiceFactory serviceFactory = ServiceFactory.newInstance();

      // Создаем объект сервиса, работающий как фабрика прокси
      Service mathService = serviceFactory.createService(url,
              new QName(nameSpaceUri, serviceName));

      // Создаем прокси
      dynamicproxy.MathFace
        myProxy = (dynamicproxy.MathFace) mathService.getPort(new 
        QName(nameSpaceUri, portName), dynamicproxy.MathFace.class);

      // Вызываем метод add 
      System.out.println(myProxy.add(23, 12));
    } 
    catch (Exception ex) 
    {
      ex.printStackTrace();
    }
  }
}

Скомпилируйте клиента:

c:\Sun\APPSER~1\apps\dynamic-proxy> javac -classpath build -d build MathClient.java 

И запустите его:

C:\Sun\APPSER~1\apps\dynamic-proxy> java -classpath build dynamicproxy.MathClient 

Консольный клиент – J2EE-приложение

В отличие от автономного клиента, клиент-приложение J2EE может получить интерфейс сервиса, используя JNDI lookup. В этом случае разработчик клиента определяет для Web-сервиса логическое JNDI-имя (ссылку на сервис). Контейнер связывает реализацию интерфейса сервиса с контекстом среды клиента java:comp/env, используя логическое имя ссылки на сервис:

try 
{
  Context ic = new InitialContext();
  MyFirstService myFirstService = (MyFirstService) 
    ic.lookup("java:comp/env/service/MyFirst");
  j2ee.MathFace mathPort = myFirstService.getMathFacePort();
  ((Stub) mathPort)._setProperty(Stub.ENDPOINT_ADDRESS_PROPERTY, 
    "http://localhost:8080/math-service/math");
  System.out.println(mathPort.add(22, 1));
} 
catch (Exception ex) 
{
  ex.printStackTrace();
  System.exit(1);
}

Клиент на базе броузера

Наконец, рассмотрим, как создать Web-клиента, вызывающего Web-сервис из формы в броузере (здесь используется статическая заглушка). Для начала потребуется конфигурационный файл, похожий на приведенный в листинге 6. Замените в нем packageName, например, на webclient. После этого сгенерируйте клиентскую заглушку следующей командой:

c:\Sun\APPSER~1\aps\web\>wscompile -gen:client -d build -classpath build config-wsdl.xml 

Следующий шаг – создание Web-клиента в форме сервлета или JSP-страницы. В листингах 9 и 10 приведена JSP-реализация Web-клиента. Листинг 9 – это код, выводящий форму пользователю и принимающий параметры. Код в листинге 10 (статическая заглушка) похож на клиента из листинга 7.

Листинг 9: math.jsp

<html>
<head><title>Hello</title></head>
<body bgcolor="#ffcccc">
<h2>Welcome to the Math Web Service</h2>
<form method="get">
<input type="text" name="num1" size="25">
<p></p>
<input type="text" name="num2" size="25">
<p></p>
<input type="submit" value="AddNumbers">
<input type="reset" value="Reset">
</form>

<%
    String str1 = request.getParameter("num1");
    String str2 = request.getParameter("num2");
    if ( str1 != null && str2 != null ) {
%>
    <%@include file="add.jsp" %>
<%
    }
%>
</body>
</html>

Листинг 10: add.jsp

<%@ page import="javax.xml.rpc.Stub,javax.naming.*,webclient.*" %>
<%
  String resp = null;
  int result = 0;

  try 
  {
    // Создание объекта-заглушки
    Stub stub = (Stub)(new MyFirstService_Impl().getMathFacePort());

    // Установка адреса endpoint-а используемого заглушкой.
    stub._setProperty(javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY,
      "http://localhost:8080/math-service/math");
    MathFace math = (MathFace)stub;
    // Получение и разбор параметров
    int x = Integer.parseInt(request.getParameter("num1"));
    int y = Integer.parseInt(request.getParameter("num2"));
    // Вызов метода
    result = math.add(x, y);

    } 
    catch (Exception ex) 
    {
    }
%>
<h2>The sum is: <%=result%></h2>

Следующий шаг – развертывание Web-клиента как JSP Web-компонента с помощью deploytool. Для доступа к сервису у меня используется URL http://localhost:8080/math-webservice/add.


Рисунок 4. JSP-клиент, вызывающий Web-сервис.

Заключение

Web-сервисы- это следующий шаг в эволюции Web. Они предлагают инфраструктуру и средства для автоматизации отношений В2В через Internet. Интегрирование Web-сервисов в платформу J2EE 1.4 упрощает задачу создания и использования Web-сервисов, освобождая Java-разработчика от низкоуровневых деталей.

v


Copyright © 1994-2016 ООО "К-Пресс"