SCAlanie z JAX-WS

Z Jacek Laskowski - Wiki Projektanta Java EE

Ostatnie dwa artykuły o SCA - SCAlenie (kompozyt) z Apache Tuscany i Apache Maven oraz SCA z językami skryptowymi w wykonaniu Apache Tuscany, Jetty i Maven 2 - dotyczyły łączenia usług, które działały w ramach pojedyńczej wirtualnej maszyny Java (JVM). Rozproszenie usług było pozorne i często spotykałem się z uwagami, że nie prezentują niczego nowatorskiego, czego nie możnaby osiągnąć korzystając z tradycyjnych metod integracji. Artykuły skupiały się raczej na prostocie tworzenia usług korzystając z SCA oraz języków skryptowych niż na prostocie integracji usług rozproszonych.

W tym artykule wyjdziemy poza ramy pojedyńczej wirtualnej maszyny i faktycznie dotkniemy kwestii integracji usług rozproszonych. Zestawimy środowisko z dwoma serwerami aplikacyjnymi Jetty oraz GlassFish, w którym uruchomimy SCAlenie na jednym serwerze, składające się z usługi PolishEnglishDictionaryService będącej usługą sieciową (ang. web service) uruchomioną na drugim. Istotą artykułu będzie zaprezentowanie deklaratywnego konstruowania SCAlenia poprzez definiowanie elementów składowych w deskryptorze XML. Cel osiągniemy korzystając również z artykułu Tworzenie usługi sieciowej z JAX-WS. Na ich podstawie utworzone zostanie SCAlenie z wykorzystaniem mechanizmu składania usług rozproszonych opartych o JAX-WS w celu udostępnienia kolejnej, bardziej specjalizowanej funkcjonalności.

Wersje oprogramowania w środowisku uruchomieniowym:

Zakłada się, że powyższe oprogramowanie jest zainstalowane i działa poprawnie. Instalacja oprogramowania sprowadza się do pobrania i rozpakowania paczek w wybranym katalogu.

Kompletny projekt jest dostępny jako sca-dictionary-jaxws.zip.

Spis treści

Utworzenie projektu aplikacji internetowej - sca-dictionary-jaxws

W poprzednich artykułach korzystaliśmy z pomocy Apache Maven 2 (m2) do tworzenia struktury projektu aplikacji. Tym razem skorzystamy z już istniejącego projektu, który był stworzony w artykule SCA z językami skryptowymi w wykonaniu Apache Tuscany, Jetty i Maven 2 i zmodyfikujemy go odpowiednio. Tym samym artykuł będzie kontynuacją poprzedniego, przez co zostanie zademonstrowany jeszcze jeden aspekt tworzenia aplikacji - stopniowy rozwój przez dodawanie bardziej specjalizowanych funkcjonalności.

Pobieramy projekt aplikacji stworzony w artykule SCA z językami skryptowymi w wykonaniu Apache Tuscany, Jetty i Maven 2 - sca-dictionary-web.zip. Paczkę rozpakowujemy do wybranego przez siebie katalogu, np. C:\.

Zmieniamy nazwę projektu na sca-dictionary-jaxws.

$ mv sca-dictionary-web sca-dictionary-jaxws

Przechodzimy do katalogu sca-dictionary-jaxws.

$ cd sca-dictionary-jaxws

Kolejne polecenia wydawane będą właśnie z tego katalogu, który reprezentuje nasz projekt SCAlenia w aplikacji internetowej.

Import projektu do zintegrowanego środowiska programistycznego - Eclipse IDE (opcjonalnie)

Wykonujemy polecenie mvn eclipse:eclipse, aby utworzyć pliku projektu do importu projektu do Eclipse IDE. W zależności od wybranego graficznego środowiska programistycznego (IDE) polecenie może nieznacznie się różnić. W przypadku NetBeans IDE 6.0M9 nie jest w ogóle konieczne, gdyż NetBeans IDE wspiera projekty zarządzane przez m2.

$ mvn eclipse:eclipse
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'eclipse'.
[INFO] ----------------------------------------------------------------------------
[INFO] Building SCAlenie Dictionary w Aplikacji Internetowej
[INFO]    task-segment: [eclipse:eclipse]
[INFO] ----------------------------------------------------------------------------
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4 seconds
[INFO] Finished at: Tue Jun 26 20:05:14 CEST 2007
[INFO] Final Memory: 6M/254M
[INFO] ------------------------------------------------------------------------

Komunikat BUILD SUCCESSFUL wskazuje na poprawnie wykonane polecenie. Uruchamiamy Eclipse IDE i importujemy projekt (File > Import > General > Existing Projects into Workspace).

UWAGA: Może się zdarzyć, że po imporcie pojawią się komunikaty błędu - Unbound classpath variable: 'M2_REPO/junit/junit/4.2/junit-4.2.jar' in project sca-dictionary-jaxws - co oznacza brak definicji zmiennej M2_REPO w wybranej przestrzeni roboczej. Naprawiamy błąd poprzez Window > Preferences... > Java > Build Path > Classpath Variables > New.... Dodajemy M2_REPO ze wskazaniem na lokalne repozytorium M2, potwierdzamy ponowne przebudowanie projektu i voila - projekt jest czysty, bez jakichkolwiek komunikatów ostrzegawczych, gotowy do dalszego rozwoju.

Modyfikacja konfiguracji projektu - pom.xml

Głównym elementem projektu zarządzanego przez m2 jest deskryptor projektu - pom.xml - znajdujący się w katalogu głównym projektu. W nim definiujemy zależnosci projektowe. Jedną z zależności są biblioteki, z których będzie korzystał projekt.

Na potrzeby tego artykułu konieczne będzie dodanie biblioteki udostępniającej możliwość budowania SCAlenia przy pomocy zdalnych usług sieciowych - tuscany-binding-ws-axis2.

<dependency>
  <groupId>org.apache.tuscany.sca</groupId>
  <artifactId>tuscany-binding-ws-axis2</artifactId>
  <version>${tuscany.version}</version>
  <scope>runtime</scope>
</dependency>

Uruchamiając 2 serwery jednocześnie, co będzie miało miejsce w naszym artykule, konieczne będzie zagwarantowanie, że żaden z serwerów nie współdzieli tego samego portu. Dodajemy do pom.xml możliwość uruchomienia Jetty na porcie innym niż domyślny - 8080, który jest również domyślnym portem dla Glassfish.

<plugins>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
      <source>1.5</source>
      <target>1.5</target>
    </configuration>
  </plugin>
  <plugin>
    <groupId>org.mortbay.jetty</groupId>
    <artifactId>maven-jetty-plugin</artifactId>
    <version>6.1.3</version>
    <configuration>
      <connectors>
        <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
          <port>${jetty.port}</port>
        </connector>
      </connectors>
    </configuration>
  </plugin>
</plugins>

Wywołanie mvn z parametrem jetty.port będzie równoznaczne z uruchomieniem Jetty na podanym porcie.

Ostatecznie plik pom.xml powinien wyglądać następujaco:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>pl.jaceklaskowski.sca.dictionary</groupId>
  <artifactId>sca-dictionary-jaxws</artifactId>
  <packaging>war</packaging>
  <version>1.0</version>
  <name>SCAlenie Dictionary w Aplikacji Internetowej</name>
  <url>http://www.JacekLaskowski.pl</url>
  <properties>
    <jetty.port>8080</jetty.port>
    <tuscany.version>1.0-incubating-SNAPSHOT</tuscany.version>
  </properties>
  <build>
    <finalName>${artifactId}</finalName>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>maven-jetty-plugin</artifactId>
        <version>6.1.3</version>
        <configuration>
          <connectors>
            <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
              <port>${jetty.port}</port>
            </connector>
          </connectors>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <repositories>
    <repository>
      <id>apache.snapshot</id>
      <url>http://people.apache.org/repo/m2-snapshot-repository</url>
    </repository>
  </repositories>
  <dependencies>
    <dependency>
      <groupId>org.apache.tuscany.sca</groupId>
      <artifactId>tuscany-host-webapp</artifactId>
      <version>${tuscany.version}</version>
    </dependency>
    <dependency>
      <groupId>org.apache.tuscany.sca</groupId>
      <artifactId>tuscany-implementation-java-runtime</artifactId>
      <version>${tuscany.version}</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.tuscany.sca</groupId>
      <artifactId>tuscany-implementation-script</artifactId>
      <version>${tuscany.version}</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.tuscany.sca</groupId>
      <artifactId>tuscany-binding-ws-axis2</artifactId>
      <version>${tuscany.version}</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.2</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

Na koniec weryfikujemy poprawną konfigurację projektu przez wydanie polecenia mvn clean jetty:run-exploded -Djetty.port=9090, które uruchomi poprzednio stworzoną aplikację w środowisku Jetty nasłuchującego na porcie 9090. W tak skonfigurowanym projekcie, adres aplikacji będzie http://localhost:9090/sca-dictionary-jaxws/ (w stosunku do macierzystego projektu, który zmodyfikowaliśmy, zmieniła się nazwa projektu, a więc i kontekst aplikacji oraz port, na którym nasłuchuje serwer).

$ mvn clean jetty:run-exploded -Djetty.port=9090
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'jetty'.
[INFO] ----------------------------------------------------------------------------
[INFO] Building SCAlenie Dictionary w Aplikacji Internetowej
[INFO]    task-segment: [clean, jetty:run-exploded]
[INFO] ----------------------------------------------------------------------------
...
[INFO] [jetty:run-exploded]
[INFO] Configuring Jetty for project: SCAlenie Dictionary w Aplikacji Internetowej
2007-06-26 20:12:39.093::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog
[INFO] Context path = /sca-dictionary-jaxws
[INFO] Tmp directory = c:\sca-dictionary-jaxws\target\work
[INFO] Web defaults =  jetty default
[INFO] Web overrides =  none
[INFO] Starting jetty 6.1.3 ...
2007-06-26 20:12:39.187::INFO:  jetty-6.1.3
2007-06-26 20:12:39.359::INFO:  No Transaction manager found - if your webapp requires one, please configure one.
2007-06-26 20:12:40.843::INFO:  Started SelectChannelConnector @ 0.0.0.0:9090
[INFO] Started Jetty Server

Zatrzymujemy serwer kombinacją klawiszy Ctrl-C.

2007-06-26 20:15:54.531::INFO:  Shutdown hook executing
[INFO] 2007-06-26 20:15:54.640::INFO:  Shutdown hook completeJetty server exiting.

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3 minutes 30 seconds
[INFO] Finished at: Tue Jun 26 20:15:54 CEST 2007
[INFO] Final Memory: 13M/254M
[INFO] ------------------------------------------------------------------------

Utworzenie usługi PolishEnglishDictionaryService z JAX-WS

W projekcie macierzystym, usługa PolishEnglishDictionaryService była napisana w Javie i jej integracja ze SCAleniem odbywała się poprzez mechanizmy języka. Tym razem, usługa jest zdalną usługą sieciową, która jest niedostępna lokalnie. Komunikacja z usługą sieciową będzie zlecona środowisku SCA - Apache Tuscany.

Rozpoczynamy od usunięcia implementacji usługi - klasy PolishEnglishDictionaryServiceImpl, gdyż wywołanie usługi sprowadza się do zdalnego wywołania usługi sieciowej PolishEnglishDictionaryService opisanej przez WSDL. Usuwamy plik PolishEnglishDictionaryServiceImpl.java z katalogu src/main/java/pl/jaceklaskowski/sca/dictionary. Nie jest to konieczny krok, jednakże porządkuje projekt.

Modyfikacja interfejsu usługi PolishEnglishDictionaryService

W projekcie macierzystym usługa PolishEnglishDictionaryService była zbudowana przy pomocy konstrukcji języka Java - interfejs oraz klasa będąca implementacją interfejsu. Żadna z konstrukcji nie była specyficzna dla SCA. Tym razem konieczne będzie określenie roli interfejsu przy konstrukcji SCAlenia tak, aby traktowany był on jako część integracji usługi zdalnej. Skorzystamy z adnotacji @Remotable oraz @Service w interfejsie PolishEnglishDictionaryService.

Plik PolishEnglishDictionaryService.java w katalogu src/main/java/pl/jaceklaskowski/sca/dictionary powinien wyglądać następująco:

package pl.jaceklaskowski.sca.dictionary;

import org.osoa.sca.annotations.Remotable;
import org.osoa.sca.annotations.Service;

@Remotable
@Service
public interface PolishEnglishDictionaryService {
    String translate(String word);
}

Deskryptor SCAlenia - Dictionary.composite

Modyfikujemy deskryptor SCAlenia - Dictionary.composite - o nową definicję usługi PolishEnglishDictionaryService, która jest usługą sieciową opisaną przez plik WSDL.

<reference name="PolishEnglishDictionaryServiceComponent" promote="DictionaryServiceComponent/polishEnglishDictionaryService">
  <interface.java interface="pl.jaceklaskowski.sca.dictionary.PolishEnglishDictionaryService" />
  <binding.ws
    wsdlElement="http://dictionary.jaxws.jaceklaskowski.pl/#wsdl.port(PolishEnglishDictionaryService/PolishEnglishDictionaryPort)" />
</reference>

Jak można zauważyć, w tym przykładzie korzystamy z elementu reference zamiast component do definicji zależności. Wykorzystanie elementów reference oraz component może być traktowane zamiennie i jedynie ich położenie nakłada obowiązek korzystania z pewnych atrybutów, które określają ich przynależność w konfiguracji SCAlenia. Porównanie definicji zależności SCAlenia za pomocą reference oraz component pozostawiamy jako zadanie domowe.

Wykorzystanie elementu reference znosi konieczność korzystania z elementu reference do definicji zależności od PolishEnglishDictionaryServiceComponent w ramach definicji komponentu DictionaryServiceComponent, więc go usuwamy.

<component name="DictionaryServiceComponent">
  <implementation.java class="pl.jaceklaskowski.sca.dictionary.DictionaryServiceImpl" />
  <reference name="englishPolishDictionaryService" target="EnglishPolishDictionaryServiceComponent" />
  <reference name="germanPolishDictionaryService" target="GermanPolishDictionaryServiceComponent" />
</component>

Ostatecznie deskryptor SCAlenia powinien wyglądać następująco:

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

<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" name="Dictionary">

  <component name="DictionaryServiceComponent">
    <implementation.java class="pl.jaceklaskowski.sca.dictionary.DictionaryServiceImpl" />
    <reference name="englishPolishDictionaryService" target="EnglishPolishDictionaryServiceComponent" />
    <reference name="germanPolishDictionaryService" target="GermanPolishDictionaryServiceComponent" />
  </component>

  <reference name="PolishEnglishDictionaryServiceComponent" promote="DictionaryServiceComponent/polishEnglishDictionaryService">
    <interface.java interface="pl.jaceklaskowski.sca.dictionary.PolishEnglishDictionaryService" />
    <binding.ws
      wsdlElement="http://dictionary.jaxws.jaceklaskowski.pl/#wsdl.port(PolishEnglishDictionaryService/PolishEnglishDictionaryPort)" />
  </reference>

  <component name="EnglishPolishDictionaryServiceComponent">
    <implementation.java class="pl.jaceklaskowski.sca.dictionary.EnglishPolishDictionaryServiceImpl" />
  </component>

  <component name="GermanPolishDictionaryServiceComponent">
    <implementation.script script="pl/jaceklaskowski/sca/dictionary/groovy/GermanPolishDictionaryServiceImpl.groovy"/>
  </component>

</composite>

Plik Dictionary.composite znajduje się w katalogu src/main/resources.

Uruchomienie SCAlenia

Uruchomienie usługi sieciowej

Rozpoczynamy od uruchomienia usługi sieciowej PolishEnglishDictionaryService, która jest zarządzana przez serwer aplikacyjny Glassfish (zakłada się tym samym, że usługa została już zainstalowana na serwerze - kroki uruchomieniowe opisane są w artykule Tworzenie usługi sieciowej z JAX-WS).

W zależności od konfiguracji serwera będziemy zmuszeni do przejścia do katalogu domowego serwera GlassFish lub po prostu wykonania polecenia asadmin.bat z parametrami, jeśli katalog skryptów jest w zmiennej PATH.

$ asadmin.bat start-domain domain1
Starting Domain domain1, please wait.
Log redirected to c:\apps\glassfish\domains\domain1\logs\server.log.
Redirecting output to C:/apps/glassfish/domains/domain1/logs/server.log
Domain domain1 is ready to receive client requests. Additional services are being started in background.
Domain [domain1] is running [Sun Java System Application Server 9.1 (build b50f-beta3)] with its configuration and logs at: [c:\apps\glassfish\domains].
Admin Console is available at [http://localhost:4848].
Use the same port [4848] for "asadmin" commands.
User web applications are available at these URLs:
[http://localhost:8080 https://localhost:8181 ].
Following web-contexts are available:
[/web1  /__wstx-services ].
Standard JMX Clients (like JConsole) can connect to JMXServiceURL:
[service:jmx:rmi:///jndi/rmi://dev:8686/jmxrmi] for domain management purposes.
Domain listens on at least following ports for connections:
[8080 8181 4848 3700 3820 3920 8686 ].
Domain does not support application server clusters and other standalone instances.

Pobranie deskryptora usługi sieciowej - WSDL

Niezbędnym elementem konstruowania SCAlenia korzystającego z usługi zdalnej jest pobranie pliku WSDL. Za pomocą WSDL środowisko uruchomieniowe rozpozna sposób komunikacji z usługą.

Otwieramy konsolę GlassFish dostępną pod adresem http://localhost:4848. Wybieramy węzeł Web Services, gdzie wybieramy węzeł PolishEnglishDictionary.

Grafika:jaxws-dictionary-konsola-glassfish-webservices.png

Pobieramy plik WSDL, który dostępny jest w menu View WSDL i zapisujemy w podkatalogu projektu - src/main/resources/wsdl jako PolishEnglishDictionaryService.wsdl (nazwa pliku nie ma znaczenia dla Apache Tuscany, a jedynie rozszerzenie .wsdl).

Uruchomienie aplikacji internetowej

Uruchomienie aplikacji internetowej, której częścią jest SCAlenie, które z kolei korzysta z usługi zdalnej, sprowadza się do uruchomienia serwera Jetty za pomocą m2.

$ mvn clean jetty:run-exploded -Djetty.port=9090
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'jetty'.
[INFO] ----------------------------------------------------------------------------
[INFO] Building SCAlenie Dictionary w Aplikacji Internetowej
[INFO]    task-segment: [clean, jetty:run-exploded]
[INFO] ----------------------------------------------------------------------------
...
[INFO] [jetty:run-exploded]
[INFO] Configuring Jetty for project: SCAlenie Dictionary w Aplikacji Internetowej
2007-06-26 20:40:54.593::INFO:  Logging to STDERR via org.mortbay.log.StdErrLog
[INFO] Context path = /sca-dictionary-jaxws
[INFO] Tmp directory = c:\sca-dictionary-jaxws\target\work
[INFO] Web defaults =  jetty default
[INFO] Web overrides =  none
[INFO] Starting jetty 6.1.3 ...
2007-06-26 20:40:54.687::INFO:  jetty-6.1.3
2007-06-26 20:40:55.375::INFO:  No Transaction manager found - if your webapp requires one, please configure one.
log4j:WARN No appenders could be found for logger (org.apache.axiom.om.util.StAXUtils).
log4j:WARN Please initialize the log4j system properly.
2007-06-26 20:40:57.375::INFO:  Started SelectChannelConnector @ 0.0.0.0:9090
[INFO] Started Jetty Server

Otwieramy przeglądarkę i wskazujemy na adres http://localhost:9090/sca-dictionary-jaxws/.

Grafika:sca-dictionary-jaxws-runout.PNG

Uruchomienie strony startowej aplikacji internetowej uruchomiło SCAlenie, które z kolei wywołało usługę zdalną uruchomioną na serwerze GlassFish. Jedyny krok związany z faktycznym programowaniem był związany z określeniem interfejsu usługi. Dostarczenie implementacji przekazaliśmy do Tuscany.

Zamknięcie serwera Jetty to wciśnięcie kombinacji klawiszy Ctrl-C, podczas gdy zatrzymanie GlassFisha to wywołanie polecenie asadmin z parametrami stop-domain domain1 (ponownie prostota wykonania polecenia zależy od konfiguracji środowiska).

Dobrym przykładem na weryfikację poprawnej integracji SCAlenia z usługą sieciową jest wyłączenie serwera GlassFish. Kiedy usługa sieciowa nie jest dostępna, innymi słowy, kiedy serwer GlassFish, na którym pracuje usługa, nie jest uruchomiony, pojawi się poniższy wyjątek.

2007-06-26 20:45:13.265:/sca-dictionary-jaxws:WARN:  exception initializing SCADomain
org.osoa.sca.ServiceRuntimeException: org.apache.tuscany.sca.contribution.service.ContributionRuntimeException: java.net.ConnectException: Connection refused: connect
        at org.apache.tuscany.sca.host.embedded.SCADomain.createNewInstance(SCADomain.java:263)
        at org.apache.tuscany.sca.host.embedded.SCADomain.newInstance(SCADomain.java:81)
        at org.apache.tuscany.sca.webapp.SCADomainHelper.initSCADomain(SCADomainHelper.java:63)
        at org.apache.tuscany.sca.webapp.TuscanyContextListener.contextInitialized(TuscanyContextListener.java:37)
        at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:530)
        at org.mortbay.jetty.servlet.Context.startContext(Context.java:135)
        at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1218)
        at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:500)
        at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448)
        at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
        at org.mortbay.jetty.handler.HandlerCollection.doStart(HandlerCollection.java:147)
        at org.mortbay.jetty.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:161)
        at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
        at org.mortbay.jetty.handler.HandlerCollection.doStart(HandlerCollection.java:147)
        at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
        at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:117)
        at org.mortbay.jetty.Server.doStart(Server.java:210)
        at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
        at org.mortbay.jetty.plugin.Jetty6PluginServer.start(Jetty6PluginServer.java:134)
        at org.mortbay.jetty.plugin.AbstractJettyMojo.startJetty(AbstractJettyMojo.java:341)
        at org.mortbay.jetty.plugin.AbstractJettyMojo.execute(AbstractJettyMojo.java:286)
        at org.mortbay.jetty.plugin.Jetty6RunWarExploded.execute(Jetty6RunWarExploded.java:163)
        at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:443)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:539)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeStandaloneGoal(DefaultLifecycleExecutor.java:493)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:463)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:311)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:278)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:143)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:334)
        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:125)
        at org.apache.maven.cli.MavenCli.main(MavenCli.java:280)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:585)
        at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
        at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
        at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
        at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
Caused by: org.apache.tuscany.sca.contribution.service.ContributionRuntimeException: java.net.ConnectException: Connection refused: connect
        at org.apache.tuscany.sca.interfacedef.wsdl.xml.WSDLDocumentProcessor$WSDLLocatorImpl.getImportInputSource(WSDLDocumentProcessor.java:88)
        at com.ibm.wsdl.xml.WSDLReaderImpl.parseSchema(Unknown Source)
        at com.ibm.wsdl.xml.WSDLReaderImpl.parseSchema(Unknown Source)
        at com.ibm.wsdl.xml.WSDLReaderImpl.parseTypes(Unknown Source)
        at com.ibm.wsdl.xml.WSDLReaderImpl.parseDefinitions(Unknown Source)
        at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
        at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
        at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
        at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
        at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
        at org.apache.tuscany.sca.interfacedef.wsdl.xml.WSDLDocumentProcessor.read(WSDLDocumentProcessor.java:141)
        at org.apache.tuscany.sca.interfacedef.wsdl.xml.WSDLDocumentProcessor.read(WSDLDocumentProcessor.java:52)
        at org.apache.tuscany.sca.contribution.processor.ExtensibleURLArtifactProcessor.read(ExtensibleURLArtifactProcessor.java:63)
        at org.apache.tuscany.sca.contribution.service.impl.ContributionServiceImpl.processReadPhase(ContributionServiceImpl.java:301)
        at org.apache.tuscany.sca.contribution.service.impl.ContributionServiceImpl.addContribution(ContributionServiceImpl.java:251)
        at org.apache.tuscany.sca.contribution.service.impl.ContributionServiceImpl.contribute(ContributionServiceImpl.java:119)
        at org.apache.tuscany.sca.host.embedded.impl.DefaultSCADomain.<init>(DefaultSCADomain.java:104)
        at org.apache.tuscany.sca.host.embedded.SCADomain.createNewInstance(SCADomain.java:229)
        ... 39 more
Caused by: java.net.ConnectException: Connection refused: connect
        at java.net.PlainSocketImpl.socketConnect(Native Method)
        at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
        at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
        at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
        at java.net.Socket.connect(Socket.java:519)
        at java.net.Socket.connect(Socket.java:469)
        at sun.net.NetworkClient.doConnect(NetworkClient.java:157)
        at sun.net.www.http.HttpClient.openServer(HttpClient.java:382)
        at sun.net.www.http.HttpClient.openServer(HttpClient.java:509)
        at sun.net.www.http.HttpClient.<init>(HttpClient.java:231)
        at sun.net.www.http.HttpClient.New(HttpClient.java:304)
        at sun.net.www.http.HttpClient.New(HttpClient.java:316)
        at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:817)
        at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:769)
        at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:694)
        at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:938)
        at java.net.URL.openStream(URL.java:1007)
        at org.apache.tuscany.sca.interfacedef.wsdl.xml.WSDLDocumentProcessor$WSDLLocatorImpl.getImportInputSource(WSDLDocumentProcessor.java:86)
        ... 56 more

Brak pliku WSDL (plik z rozszerzeniem .wsdl), który definiuje zdalną usługę, wiąże się z poniższym komunikatem błędu.

2007-06-26 20:47:32.203:/sca-dictionary-jaxws:WARN:  exception initializing SCADomain
org.osoa.sca.ServiceRuntimeException: org.osoa.sca.ServiceRuntimeException: org.apache.tuscany.sca.core.runtime.ActivationException: java.lang.NullPointerException
        at org.apache.tuscany.sca.host.embedded.SCADomain.createNewInstance(SCADomain.java:263)
        at org.apache.tuscany.sca.host.embedded.SCADomain.newInstance(SCADomain.java:81)
        at org.apache.tuscany.sca.webapp.SCADomainHelper.initSCADomain(SCADomainHelper.java:63)
        at org.apache.tuscany.sca.webapp.TuscanyContextListener.contextInitialized(TuscanyContextListener.java:37)
        at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:530)
        at org.mortbay.jetty.servlet.Context.startContext(Context.java:135)
        at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1218)
        at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:500)
        at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448)
        at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
        at org.mortbay.jetty.handler.HandlerCollection.doStart(HandlerCollection.java:147)
        at org.mortbay.jetty.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:161)
        at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
        at org.mortbay.jetty.handler.HandlerCollection.doStart(HandlerCollection.java:147)
        at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
        at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:117)
        at org.mortbay.jetty.Server.doStart(Server.java:210)
        at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
        at org.mortbay.jetty.plugin.Jetty6PluginServer.start(Jetty6PluginServer.java:134)
        at org.mortbay.jetty.plugin.AbstractJettyMojo.startJetty(AbstractJettyMojo.java:341)
        at org.mortbay.jetty.plugin.AbstractJettyMojo.execute(AbstractJettyMojo.java:286)
        at org.mortbay.jetty.plugin.Jetty6RunWarExploded.execute(Jetty6RunWarExploded.java:163)
        at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:443)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:539)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeStandaloneGoal(DefaultLifecycleExecutor.java:493)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:463)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:311)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:278)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:143)
        at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:334)
        at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:125)
        at org.apache.maven.cli.MavenCli.main(MavenCli.java:280)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:585)
        at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
        at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
        at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
        at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
Caused by: org.osoa.sca.ServiceRuntimeException: org.apache.tuscany.sca.core.runtime.ActivationException: java.lang.NullPointerException
        at org.apache.tuscany.sca.host.embedded.impl.DefaultSCADomain.<init>(DefaultSCADomain.java:148)
        at org.apache.tuscany.sca.host.embedded.SCADomain.createNewInstance(SCADomain.java:229)
        ... 39 more
Caused by: org.apache.tuscany.sca.core.runtime.ActivationException: java.lang.NullPointerException
        at org.apache.tuscany.sca.core.runtime.CompositeActivatorImpl.activate(CompositeActivatorImpl.java:602)
        at org.apache.tuscany.sca.host.embedded.impl.DefaultSCADomain.<init>(DefaultSCADomain.java:145)
        ... 40 more
Caused by: java.lang.NullPointerException
        at org.apache.tuscany.sca.binding.axis2.Axis2ReferenceBindingProvider.createServiceClient(Axis2ReferenceBindingProvider.java:128)
        at org.apache.tuscany.sca.binding.axis2.Axis2ReferenceBindingProvider.initServiceClient(Axis2ReferenceBindingProvider.java:104)
        at org.apache.tuscany.sca.binding.axis2.Axis2ReferenceBindingProvider.<init>(Axis2ReferenceBindingProvider.java:76)
        at org.apache.tuscany.sca.binding.axis2.Axis2BindingProviderFactory.createReferenceBindingProvider(Axis2BindingProviderFactory.java:48)
        at org.apache.tuscany.sca.binding.axis2.Axis2BindingProviderFactory.createReferenceBindingProvider(Axis2BindingProviderFactory.java:37)
        at org.apache.tuscany.sca.core.runtime.CompositeActivatorImpl.configureComposite(CompositeActivatorImpl.java:129)
        at org.apache.tuscany.sca.core.runtime.CompositeActivatorImpl.activate(CompositeActivatorImpl.java:599)
        ... 41 more

Na uwagę zasługuje prostota konstruowania SCAlenia przy pomocy różnych technologii. W poprzednich artykułach mieliśmy możliwość skorzystania z języka silnie-typowanego Java i języka skryptowego Groovy, a tym razem skorzystaliśmy z integracji opartej o usługę zdalną zbudowaną za pomocą JAX-WS. Jakby tego było mało - wciąż nie wyczerpaliśmy możliwości oferowanych nam przez specyfikację SCA w wykonaniu Apache Tuscany. Więcej informacji znajduje się na stronach Service Component Architecture Specifications. Polecam!

Osobiste