Autor wpisu: Splatch, dodany: 23.07.2008 08:27, tagi:
Od jakiegoś czasu w pracy do tworzenia usług sieciowych korzystam z Apache CXF. Jako że biblioteka jest stosunkowo nowa i nie najlepiej udokumentowana postanowiłem przedstawić na blogu jak wygląda proces tworzenia.
CXF jest połączeniem kilku bibliotek - YOKO, Celtixa oraz XFire. Każda z nich wcześniej realizowała pewien fragment obecnej funkcjonalności CXF - YOKO obsługuje Corbę a XFire usługi sieciowe. Obecne CXF jest gotowy do używania "produkcyjnego", ponieważ niedawno wyszedł z fazy inkubacji. :)
Architektura
CXF ma dosyć elastyczną budowę. Zgodnie z dokumentacją można wyróżnić najważniejsze składowe:
- Bus, jest trzonem architektury CXF w którym definiuje i konfiguruje się rozszerzenia.
- Messaging & Interceptors, zapewniają niskopoziomowy dostęp do komunikatów oraz warstwę na której jest oparta większość funkcjonalności.
- Front ends, frontendy są interfejsami programistycznymi do tworzenia usług (np. JAX-WS).
- Services, usługi zapewniają model wraz z opisem
- Bidings, element ten jest odpowiedzialny za obsługę konkretnego protokołu (SOAP, REST, Corba etc).
- Transports, warstwa abstrakcji ułatwiająca zmianę sposobu transportu do/z usług.
Markieting :)
CXF oferuje infrastrukturę konieczną do budowania usług, z najważniejszy zalet można wymienić:
- Wsparcie dla różnych protokołów.
- Obsługa standardów WS-*, tj. WS-Addressing, WS-Security, WS-ReliableMessaging, oraz WS-Policy.
- Obsługa wielu transportów.
- Dołączane data-bindingi (np JAXB, Aegis).
- Jasny podział front endów takich jak JAX-WS od najważniejszego kodu.
- Wysoka wydajność.
- Możliwość osadzania w różnych środowiskach.
Z dodatkowych zalet, mogę dodać - bardzo łatwą integrację ze Springiem.
Pierwsza usługa
Do budowania projektów będziemy używać Mavena. Implementowana usługa będzie oparta o frontend JAX-WS z ręcznie pisanym deskryptorem usługi (WSDL first). Jakkolwiek w bardzo prosty sposób można odwrócić kolejność i przy pomocy pluginu CXF do Mavena wygenerować deskryptor.
Struktura projektów będzie następująca:
- parent Rodzic projektu ze zdefiniowanymi wersjami bibliotek i raportami.
- contract Definicje używane zarówno przez klienta jak i serwer - WSDL oraz konfiguracja pluginu CXF.
- client Prosta biblioteka kliencka oparta o mechanizmy CXFa (JaxWSProxyFactoryBean).
- server Przykładowa implementacja usługi z bardzo prostym wykorzystaniem Springa.
- webapp Konfiguracja transporty CXF - w tym konkretnym przypadku servletu CXF.
Parent
Poniżej znajduje się deskryptor projektu, który jest używany do budowania całości.
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- Informacja dla Mavena -->
<modelVersion>4.0.0</modelVersion>
<!-- Identyfikacja projektu -->
<groupId>org.code-house.cxf</groupId>
<artifactId>parent</artifactId>
<name>Code House.Org - CXF</name>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<description>Rodzic projektu, zawiera wszystkie moduly.</description>
<!-- Składowe projektu -->
<modules>
<module>cxf-client</module>
<module>cxf-contract</module>
<module>cxf-server</module>
<module>cxf-webapp</module>
</modules>
<!-- Definicje zmiennych dostępne również w modułach -->
<properties>
<code-house.cxf.version>2.1.1</code-house.cxf.version>
<code-house.jaxb.version>2.1.3</code-house.jaxb.version>
<code-house.spring.version>2.5.4</code-house.spring.version>
</properties>
<build>
<plugins>
<!-- Konfiguracja kompilatora -->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
<reporting>
<!--Wycięte :) -->
</reporting>
<!-- Predefiniowane wersje bibliotek -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>${code-house.cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>${code-house.cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>${code-house.cxf.version}</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>${code-house.jaxb.version}</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.1</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Contract
Zgodnie z tym, co napisałem wcześniej - przyjąłem podejście, że WSDL jest pisany ręcznie, głównie dlatego że dla większych projektów można w prosty sposób narzucić jakąś organizację i podział plików, z których są następnie generowane źródła. Najistotniejsza wstawka, która powinna znaleźć się w pomie:
<!-- Generowanie kodu z deskryptora WSDL -->
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<executions>
<execution>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${basedir}/target/jaxws</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>
${basedir}/src/main/resources/maven.wsdl
</wsdl>
<extraargs>
<extraarg>-quiet</extraarg>
</extraargs>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
Po dodaniu tej wstawki do sekcji build/plugins możemy przejść do tworzenia deskryptora usługi. W moim przypadku przyjąłem następujący podział:
Kanał ATOM

Wszyscy cieszą się z Firefoxa 3, a deweloperzy ciągną się za włosy… dlaczego plugin
Źródło -
Źródło