Берт Ламб,
инженер-консультант по разработке ПО,
IBM

Расширяемость сервисов на основе сервисно-компонентной архитектуры (SCA)

Уровень сложности: средний

Источник: сайт корпорации IBM, http://www.ibm.com/developerworks/ru/library/ws-soa-scafutureproof/index.html, 11.11.2008

Узнайте, как архитектура SCA может помочь вам создавать решения, легко приспосабливающиеся к существующей инфраструктуре и расширяемые при необходимости в будущем.

Введение

Сервисно-компонентная архитектура (SCA) - спецификация, или, скорее, набор спецификаций, разработанный для описания модели создания приложений и систем на базе сервисно-ориентированной архитектуры (SOA). SCA предоставляет модель построения приложений, состоящих из совокупности сервисов и бизнес-функционала.

Преимущества SCA над прочими SOA-технологиями не всегда очевидны сразу. Во время создания первоначального варианта SOA-системы обычно предусматривается наличие гомогенной среды, все компоненты которой используют единый стандарт Web-сервисов и один общий язык программирования. Проблема состоит в том, что часто такое окружение нереалистично. Обычно есть уже существующие унаследованные приложения, требующие интеграции с системой и зачастую плохо вписывающиеся в гетерогенное окружение. Что, если выбранный для интеграции стандарт Web-сервисов окажется неподходящим? Что, если потребуется использовать более новый стандарт для взаимодействия с сервисами внешних поставщиков, или будет выбран иной метод для предоставления сервисов вашей компании третьей стороне? Пришло время переписывать все сервисы? Только не с архитектурой SCA.

Apache Tuscany

Apache Tuscany - проект с открытыми исходными кодами, посвященный созданию реализаций спецификации SCA (а так же и спецификаций-"родственников" - сервисных объектов данных (Service Data Objects, SDO) и сервиса доступа к данным (Data Access Service, DAS)). В данной статье я подробно остановлюсь на реализации SCA, предложенной Apache Tuscany, т.к. она бесплатна и проста в использовании. Должен, однако, заметить. что есть несколько компаний, которые разрабатывают собственные реализации спецификации SCA.

Скомпилированный дистрибутив Apache Tuscany Java SCA доступен здесь: http://incubator.apache.org/tuscany/sca-java-releases.html. Последняя версия во время написания данной статьи была 1.0.1-incubating, и примеры в статье используют именно ее.

Как только вы загрузите бинарный дистрибутив и распакуете его, взгляните на пример Hello World Web Service. Он расположен в директории <tuscany_home>/samples/helloworld-ws-service.


Листинг 1. Структура директорий для примера Hello World Web Service
                
helloworld-ws-service/
    src/
        main/
            java/
                helloworld/
                    HelloWorldImpl.java
                    HelloWorldServer.java
                    HelloWorldService.java
            resources/
                wsdl/
                    helloworld.wsdl
                helloworldws.composite
        test/
            java/
                helloworld/
                    HelloWorldServerTestCase.java
    target/
       sample-helloworld-ws-service.jar
    build.xml
    pom.xml
    README

Tuscany использует систему сборки Maven, так что, надеемся, такое расположение вам знакомо. Основная программа располагается в трех Java-файлах, HelloWorldService.java - интерфейс для сервиса, HelloWorldImpl.java - реализация сервиса и HelloWorldServer.java - исполняемый класс, содержащий метод main, который загружает SCA во время исполнения. Файл, с которым мы в основном будем разбираться - helloworldws.composite.

Листинг 2. helloworldws.composite


                
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
	targetNamespace="http://helloworld"
	xmlns:hw="http://helloworld"
    name="helloworldws">

    <component name="HelloWorldServiceComponent">
        <implementation.java class="helloworld.HelloWorldImpl" />
	    <service name="HelloWorldService">
	        <interface.wsdl interface="http://helloworld#wsdl.interface
	        (HelloWorld)" />
	        <binding.ws uri="http://localhost:8085/HelloWorldService"/>

	    </service>
    </component>

</composite>

Это файл компоновки, в котором определяется наша композиция SCA. Здесь мы определяем, какие компоненты есть в нашей композиции и какие сервисы публикуются или требуют ссылок для наших компонентов в композиции. Это очень простая композиция, содержащая один компонент под именем HelloWorldServiceComponent, публикующий один сервис HelloWorldService, который должен быть опубликован с использованием связывания с Web-сервисом, использующего URI http://localhost:8085/HelloWorldService . Также заметим, что сервис реализован Java-классом helloworld.HelloWorldImpl.

Для того, чтобы пример заработал, убедитесь, что ваша версия Ant не ниже 1.6.5, введите ant run, нажмите Enter, и вы должны получить следующее:

Листинг 3. Запуск Web-сервиса Hello World на сервере
                
Buildfile: build.xml

run:
     [java] Dec 10, 2007 8:53:09 AM org.apache.tuscany.sca.http.jetty.JettyServer 
            addServletMapping
     [java] INFO: Added Servlet mapping: http://localhost:8085/HelloWorldService
                     [java] HelloWorld server started (press enter to shutdown)
            

Теперь вы можете открыть еще одну консоль и изменить в ней текущую директорию на <tuscany_home>/samples/helloworld-ws-reference. Здесь располагается пример клиентской части для Web-сервиса. Введите ant run для запуска клиента уже запущенного на сервере Web-сервиса. Вы должны получить следующее:

Листинг 4. Запуск клиента Web-сервиса Hello World
                
Buildfile: build.xml

run:
     [java] Injected helloWorldService
     [java] Called getGreetings
     [java] Hello World

BUILD SUCCESSFUL

Вместо запуска клиента вы могли бы также использовать Web Service Definition Language (WSDL), доступный на http://localhost:8085/HelloWorldService?wsdl, и создать своего собственного клиента для Web-сервиса - на ваше усмотрение. Когда вы убедитесь в работе системы, нажмите Enter в консоли сервера для его остановки.

Добавление нового связывания

А рассмотрим то, что кажется мне основным преимуществом SCA. У нас уже есть созданный сервис и мы можем опубликовать тот же самый сервис другим способом, просто сделав несколько изменений в файле компоновки.

Листинг 5. Измененный файл helloworldws.composite
                
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
    xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0"
    targetNamespace="http://helloworld"
    xmlns:hw="http://helloworld"
    name="helloworldws">
   
<service name="HelloWorldService" 
promote="HelloWorldServiceComponent/HelloWorldService">
                    <interface.wsdl interface=
                "http://helloworld#wsdl.interface(HelloWorld)" />

                     <binding.ws uri="http://localhost:8085/HelloWorldService"/>
                </service>
                
<service name="HelloWorldService" promote="HelloWorldServiceComponent/HelloWorldService"> <interface.java interface="helloworld.HelloWorldService"/> <tuscany:binding.jsonrpc/> </service>
<component name="HelloWorldServiceComponent"> <implementation.java class="helloworld.HelloWorldImpl"/> </component>
</composite>

Эти изменения теперь публикуют HelloWorldServiceComponent, используя как связывание с Web-сервисом, так и связывание с JSON-RPC. Чтобы все работало, мне пришлось внести несколько изменений, но я думаю, так стало более понятно. Во-первых, у нас есть HelloWorldService, опубликованный с использованием связывания с Web-сервисом. В определении сервиса описан WSDL-интерфейс, указан URI Web-сервиса, на котором он должен быть доступен, а также какой компонент поддерживает сервис.

Следующая секция предназначена для публикации сервиса JSON-RPC. Она определяет используемый Java-интерфейс, и также указывает, какой компонент должен поддерживать сервис, точно так же как и в случае с SOAP Web-сервисом. Связывание с JSON-RPC не является "официальной" частью SCA-связываний, поэтому его описание размещено в пространстве имен Tuscany XML вместо используемого по умолчанию OSOA SCA. Это сделано для предотвращения потенциального конфликта имен между нестандартными связываниями от других поставщиков.

Для внесения в JAR-файл наших изменений в helloworldws.composite нам надо пересобрать пример с помощью команды ant. Кроме того, вы можете пересобрать проект с использованием Maven, запустив команду mvn.

Как только сборка завершена, запуск ant run выдает нам следующее:

Listing 6. Запуск сервера Web-сервиса Hello World со связыванием JSON-RPC
                
Buildfile: build.xml

run:
     [java] Dec 10, 2007 9:01:14 AM org.apache.tuscany.sca.http.jetty.JettyServer 
            addServletMapping
    [java] INFO: Added Servlet mapping: http://localhost:8085/HelloWorldService
     [java] Dec 10, 2007 9:01:14 AM org.apache.tuscany.sca.http.jetty.JettyServer 
            addServletMapping
    [java] INFO: Added Servlet mapping: http://localhost:8080/HelloWorldService
     [java] Dec 10, 2007 9:01:14 AM org.apache.tuscany.sca.http.jetty.JettyServer 
            addServletMapping
    [java] INFO: Added Servlet mapping: http://localhost:8080/SCADomain/scaDomain.jsb>
     [java] HelloWorld server started (press enter to shutdown)

Отсюда видно, что у нас все еще есть наш запущенный SOAP Web-сервис, точно как и ранее, на http://localhost:8085/HelloWorldService, но теперь имеется и JSON-RPC-сервис, работающий на http://localhost:8080/HelloWorldService (кроме того, есть и вспомогательный JavaScript, доступный по адресу http://localhost:8080/SCADomain/scaDomain.js, но пока не обращайте на это внимания). Подключение браузера к http://localhost:8080/HelloWorldService?smd выдаст простое описание метода для JSON-RPC-сервиса. Вот оно! Простая модификация - и наш существующий сервис теперь опубликован с помощью совершенно иной технологии. Кроме того, он мог быть и не JSON-RPC-сервисом; Tuscany поддерживает связывание по RMI, DWR и еще некоторые. Вы могли бы даже написать собственный вариант связывания, если есть желание!

Связывание JSON-RPC в действии

Давайте сделаем еще несколько добавлений, чтобы увидеть наш JSON-RPC-сервис в действии.

Мы могли бы пересобрать наше приложение в WAR-файл и установить его на сервер приложений JavaEE™, но Tuscany содержит HTTP-связывание, которое может быть использовано для публикации статических Web-ресурсов, и потому все, что нам надо для публикации нашего простого JSON-RPC-сервиса - статическая HTML-страница, которая будет превосходно работать. Для начала добавим наш собственный файл HTML. Давайте назовем его HelloWorldJSONRPC.html и поместим в директорию <tuscany_home>/samples/helloworld-ws-service/src/main/resources/web.

Этот файл и законченный файл компоновки доступны по ссылке на код примера, приложенной к статье.

Листинг 7. HelloWorldJSONRPC.html
                
<html>
  <head>
    <title>Tuscany JSON-RPC HelloWorld Example</TITLE>
    <script type="text/javascript" src="/SCADomain/scaDomain.js"></script>

                    <script language="JavaScript">
                       function getGreeting() {
                          var name = document.getElementById("name").value;
                          jsonRpcClient = new JSONRpcClient("/HelloWorldService");
                          jsonRpcClient.HelloWorldService.getGreetings
                (name, handleResponse);
                       }
                
function handleResponse(result) { document.getElementById('greeting').innerHTML=result; } </script> </head> <body> <h2>Tuscany JSON-RPC HelloWorld Sample</h2> <p> Name please: &nbsp;&nbsp;&nbsp; <input type="text" id="name" size="30" value="World" /> <input type="button" value="Submit" onclick="getGreeting()" /> <div id='greeting'>None Yet.</div> </p> </body> </html>

Этот файл использует преимущества JavaScript-сервиса, который мы рассмотрели ранее. Данный JavaScript обслуживается связыванием с JSON-RPC и предоставляет функциональность JavaScript JSON-RPC. Следующий фрагмент скрипта объявляет функцию getGreeting, которая будет использовать JavaScript-библиотеку JSON-RPC для создания клиента JSON-RPC к нашему HelloWorldService и вызывать метод getGreetings этого сервиса.

Теперь я покажу вам, как изменить файл компоновки с использованием HTTP-связывания для публикации этой HTML-страницы.

Листинг 8. Еще одно обновление файла helloworldws.composite
                
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"
    xmlns:tuscany="http://tuscany.apache.org/xmlns/sca/1.0"
    targetNamespace="http://helloworld"
    xmlns:hw="http://helloworld"
    name="helloworldws">
   
<service name="HelloWorldService" promote="HelloWorldServiceComponent/HelloWorldService">
     <interface.wsdl interface="http://helloworld#wsdl.interface(HelloWorld)" />
     <binding.ws uri="http://localhost:8085/HelloWorldService"/>
</service> 


<service name="HelloWorldService" promote="HelloWorldServiceComponent/HelloWorldService">
     <interface.java interface="helloworld.HelloWorldService"/>
     <tuscany:binding.jsonrpc/>
</service>     

<component name="HelloWorldServiceComponent">
    <implementation.java class="helloworld.HelloWorldImpl"/>
</component>

<component name="example">
                    <tuscany:implementation.resource location="web"/>
                    <service name="Resource">
                        <tuscany:binding.http/>
                    </service>
                </component>

   
</composite>

Новое определение компонента публикует директорию ресурсов "web", используя HTTP-связывание.

Запустите ant или mvn для сборки проекта и затем снова введите ant run для запуска примера. Вы должны увидеть следующее:

Листинг 9. Запуск сервера сервиса Hello World с добавленным HTTP-связыванием
                
Buildfile: build.xml

run:
     [java] Dec 10, 2007 9:06:38 AM org.apache.tuscany.sca.http.jetty.JettyServer 
            addServletMapping
    [java] INFO: Added Servlet mapping: http://localhost:8085/HelloWorldService
     [java] Dec 10, 2007 9:06:38 AM org.apache.tuscany.sca.http.jetty.JettyServer 
            addServletMapping
    [java] INFO: Added Servlet mapping: http://localhost:8080/HelloWorldService
     [java] Dec 10, 2007 9:06:38 AM org.apache.tuscany.sca.http.jetty.JettyServer 
            addServletMapping
    [java] INFO: Added Servlet mapping: http://localhost:8080/SCADomain/scaDomain.js
     [java] Dec 10, 2007 9:06:38 AM org.apache.tuscany.sca.http.jetty.JettyServer 
            addServletMapping
    [java] INFO: Added Servlet mapping: http://localhost:8080/example/*
     [java] HelloWorld server started (press enter to shutdown)

Как видите, у нас публикуются наш SOAP-сервис, JSON-RPC-сервис и вспомогательный JavaScript, а так же сервлет, обеспечивающий отображение нашего только что добавленного ресурса на http://localhost:8080/example/. Теперь мы можем подключиться в браузере к http://localhost:8080/example/HelloWorldJSONRPC.html и увидеть наш замечательный сервис в действии.


Рис. 1. Сервис Hello World, доступный через JSON-RPC

Заключение

В данной статье вы увидели, как использовать имеющийся SCA-сервис в виде SOAP Web-сервиса и расширить его так, чтобы опубликовать его с использованием JSON-RPC. Все это было сделано без малейшего изменения исходных кодов, реализующих сам сервис. Надеюсь, приведенный пример показал мощь архитектуры SCA, помогающей повысить расширяемость ваших SOA-приложений. Компоновка сервисов в SCA может использовать любые связывания, доступные в реализации SCA. По появления новых технологий будут также реализовываться новые связывания и реализации, которые могут легко встраиваться в существующую SCA-инфраструктуру.

E-mail this page