<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Splatch's devblog &#187; CXF</title>
	<atom:link href="http://blog.dywicki.pl/category/apache/cxf/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.dywicki.pl</link>
	<description>Pragmatyzm kontrolowany</description>
	<lastBuildDate>Fri, 05 Jun 2009 14:30:15 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Budowanie klienta usługi sieciowej w oparciu o Apache CXF</title>
		<link>http://blog.dywicki.pl/2008/09/03/budowanie-klienta-uslugi-sieciowej-w-oparciu-o-apache-cxf/</link>
		<comments>http://blog.dywicki.pl/2008/09/03/budowanie-klienta-uslugi-sieciowej-w-oparciu-o-apache-cxf/#comments</comments>
		<pubDate>Wed, 03 Sep 2008 07:28:27 +0000</pubDate>
		<dc:creator>Łukasz Dywicki</dc:creator>
				<category><![CDATA[CXF]]></category>
		<category><![CDATA[Framework]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blog.dywicki.pl/?p=223</guid>
		<description><![CDATA[W nawiązaniu do poprzedniej noty o CXFie, którą napisałem jakiś czas temu, gonię aby uzupełnić brak konfiguracji klienta. Sam proces jest bardzo zbliżony do tworzenia klienta w oparciu o XFire. Nie jest wymagana duża ilość kodu Javy, a w zasadzie tylko dwa pliki XML (client.xml, myservice.xml).
Pierwszy z nich odpowiada za wczytanie wymaganych rozszerzeń CXFa oraz [...]]]></description>
			<content:encoded><![CDATA[<p>W nawiązaniu do <a href="http://blog.dywicki.pl/2008/07/23/budowanie-uslugi-sieciowej-w-oparciu-o-apache-cxf/">poprzedniej noty o CXFie</a>, którą napisałem jakiś czas temu, gonię aby uzupełnić brak konfiguracji klienta. Sam proces jest bardzo zbliżony do tworzenia klienta w oparciu o XFire. Nie jest wymagana duża ilość kodu Javy, a w zasadzie tylko dwa pliki <acronym title="eXtensible Markup Language">XML</acronym> (client.xml, <em>myservice.xml</em>).</p>
<p>Pierwszy z nich odpowiada za wczytanie wymaganych rozszerzeń CXFa oraz definicję bazowej konfiguracji fabryki z interceptorami. W interceptorach możemy skonfigurować logowanie, obsługę załączników czy standardów WS-Security etc. Wszystkie te ustawienia będą dziedziczone, a fabryki docelowych usług będą dodawać tylko adres, do odpytywania. Na koniec bean klienta będzie miał określony <strong>autowire</strong> by nie przekazywać mu wszystkich własności.<br />
<span id="more-223"></span></p>
<p>Oto najważniejsze wstawki kodu oraz ich opis:</p>
<pre class="brush: xml;">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot;&gt;
    &lt;parent&gt;
        &lt;groupId&gt;org.code-house.cxf&lt;/groupId&gt;
        &lt;artifactId&gt;parent&lt;/artifactId&gt;
        &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
    &lt;/parent&gt;

    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
    &lt;groupId&gt;org.code-house.cxf&lt;/groupId&gt;
    &lt;artifactId&gt;client&lt;/artifactId&gt;
    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;

    &lt;name&gt;Code House.Org - CXF - Client&lt;/name&gt;

    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;log4j&lt;/groupId&gt;
            &lt;artifactId&gt;log4j&lt;/artifactId&gt;
            &lt;version&gt;1.2.12&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.code-house.cxf&lt;/groupId&gt;
            &lt;artifactId&gt;contract&lt;/artifactId&gt;
            &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
            &lt;artifactId&gt;cxf-rt-frontend-jaxws&lt;/artifactId&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
            &lt;artifactId&gt;cxf-rt-transports-http&lt;/artifactId&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
            &lt;artifactId&gt;cxf-rt-transports-http-jetty&lt;/artifactId&gt;
            &lt;version&gt;${code-house.cxf.version}&lt;/version&gt;
        &lt;/dependency&gt;

        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework&lt;/groupId&gt;
            &lt;artifactId&gt;spring-core&lt;/artifactId&gt;
            &lt;version&gt;${code-house.spring.version}&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework&lt;/groupId&gt;
            &lt;artifactId&gt;spring-test&lt;/artifactId&gt;
            &lt;version&gt;${code-house.spring.version}&lt;/version&gt;
            &lt;scope&gt;test&lt;/scope&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;

    &lt;dependencyManagement&gt;
        &lt;dependencies&gt;
            &lt;dependency&gt;
                &lt;groupId&gt;org.springframework&lt;/groupId&gt;
                &lt;artifactId&gt;spring-beans&lt;/artifactId&gt;
                &lt;version&gt;${code-house.spring.version}&lt;/version&gt;
            &lt;/dependency&gt;
            &lt;dependency&gt;
                &lt;groupId&gt;org.springframework&lt;/groupId&gt;
                &lt;artifactId&gt;spring-core&lt;/artifactId&gt;
                &lt;version&gt;${code-house.spring.version}&lt;/version&gt;
            &lt;/dependency&gt;
            &lt;dependency&gt;
                &lt;groupId&gt;org.springframework&lt;/groupId&gt;
                &lt;artifactId&gt;spring-context&lt;/artifactId&gt;
                &lt;version&gt;${code-house.spring.version}&lt;/version&gt;
            &lt;/dependency&gt;
        &lt;/dependencies&gt;
    &lt;/dependencyManagement&gt;

&lt;/project&gt;</pre>
<p>Deskryptor nie jest zbyt złożony, istotny jest tylko kawałek z kontraktem, który jak wskazuje nazwa jest definicją używanych typów:</p>
<pre class="brush: xml;">&lt;dependency&gt;
    &lt;groupId&gt;org.code-house.cxf&lt;/groupId&gt;
    &lt;artifactId&gt;contract&lt;/artifactId&gt;
    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
&lt;/dependency&gt;</pre>
<p>Teraz kolej na jedyną wstawkę Javy, która się pojawia w projekcie. Jest to zwykły bean, który będzie miał później wstrzykiwane obiekty pośredniczące w wywoływaniu usług.</p>
<pre class="brush: java;">package org.code_house.cxf.client;

import org.code_house.services.maven.MavenArtifactType;

/**
 * Klient usług Code-House.
 *
 * @author Łukasz Dywicki &lt;a href=&quot;splatch@code-house.org&quot;&gt;email&lt;/a&gt;
 *
 * $Id$
 */
public class Client {

    /**
     * Usługa do obsługi wyszukiwania artefaktów Mavena.
     */
    private MavenArtifactType maven;

    /**
     * Pobranie wartości pola maven.
     *
     * @return Wartość maven.
     */
    public MavenArtifactType getMaven() {
        return maven;
    }

    /**
     * Ustawienie wartości pola maven.
     *
     * @param maven Nowa wartość pola maven.
     */
    public void setMaven(MavenArtifactType maven) {
        this.maven = maven;
    }
}</pre>
<p>Resztę magii załatwia Spring:</p>
<pre class="brush: xml;">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xmlns:context=&quot;http://www.springframework.org/schema/context&quot;
    xsi:schemaLocation=&quot;
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
    &quot;&gt;
    &lt;!--  Konfiguracja placeholderów (znaczy wstawek ${}) --&gt;
    &lt;context:property-placeholder location=&quot;classpath:client.properties&quot; /&gt;

    &lt;!-- Importy rzeczy koniecznych do pracy CXF --&gt;
    &lt;import resource=&quot;classpath:META-INF/cxf/cxf.xml&quot; /&gt;
    &lt;import resource=&quot;classpath:META-INF/cxf/cxf-extension-soap.xml&quot; /&gt;
    &lt;import resource=&quot;classpath:META-INF/cxf/cxf-extension-http-jetty.xml&quot; /&gt;

    &lt;!-- Konfiguracja poszczególnych usług wstrzykiwanych do klienta --&gt;
    &lt;import resource=&quot;classpath:services/*.xml&quot; /&gt;

    &lt;!-- Bean zawierający referencje do wygenerowanych klientów usług --&gt;
    &lt;bean id=&quot;client&quot; class=&quot;org.code_.housecxf.client.Client&quot; autowire=&quot;autodetect&quot; /&gt;

    &lt;!-- Bazowa konfiguracja fabryk - obiektów tworzących stuby klientów w runtime --&gt;
    &lt;bean id=&quot;baseClientFactory&quot; abstract=&quot;true&quot;
        class=&quot;org.apache.cxf.jaxws.JaxWsProxyFactoryBean&quot;&gt;
       &lt;property name=&quot;username&quot; value=&quot;${org.code_house.cxf.user}&quot; /&gt;
        &lt;property name=&quot;password&quot; value=&quot;${org.code_house.cxf.password}&quot; /&gt;
        &lt;property name=&quot;inInterceptors&quot;&gt;
            &lt;list&gt;
                &lt;ref bean=&quot;logIn&quot; /&gt;
            &lt;/list&gt;
        &lt;/property&gt;
        &lt;property name=&quot;outInterceptors&quot;&gt;
            &lt;list&gt;
                &lt;ref bean=&quot;logOut&quot; /&gt;
            &lt;/list&gt;
        &lt;/property&gt;
    &lt;/bean&gt;

    &lt;!-- Loggery dla CXF --&gt;
    &lt;bean id=&quot;logIn&quot; class=&quot;org.apache.cxf.interceptor.LoggingInInterceptor&quot; /&gt;
    &lt;bean id=&quot;logOut&quot; class=&quot;org.apache.cxf.interceptor.LoggingOutInterceptor&quot; /&gt;

&lt;/beans&gt;</pre>
<p>Zgodnie ze wstawką w linii 20 konieczna jest jeszcze konfiguracja usługi. Sztuczka polega na użyciu części konfiguracji zdefiniowanej wcześniej &#8211; baseClientFactory.</p>
<pre class="brush: xml;">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
    &quot;&gt;

    &lt;!-- Konfiguracja stuba dla usługi wyszukiwania artefaktów --&gt;
    &lt;bean id=&quot;mavenService&quot; class=&quot;org.code_house.services.maven.MavenArtifactType&quot;
        factory-bean=&quot;mavenServiceFactory&quot; factory-method=&quot;create&quot; /&gt;

    &lt;!-- Fabryka usługi wyszukującej --&gt;
    &lt;bean id=&quot;mavenServiceFactory&quot; parent=&quot;baseClientFactory&quot;&gt;
        &lt;!-- jedyne parametry jakich potrzebujemy --&gt;
        &lt;property name=&quot;serviceClass&quot;
            value=&quot;org.code_house.services.maven.MavenArtifactType&quot; /&gt;
        &lt;property name=&quot;address&quot; value=&quot;${org.code_house.cxf.service.maven}&quot; /&gt;
    &lt;/bean&gt;

&lt;/beans&gt;</pre>
<p>Ustawienia, które mogą ulec zmianie, to znaczy użytkownik, hasło oraz adres usługi są wyodrębnione do pliku client.properties:</p>
<p># Placeholdery dla kontekstow springa<br />
# Adresy uslug<br />
server.port = 8080<br />
host = localhost<br />
org.code_house.cxf.service.maven http://${host}:${server.port}/webapp/services/maven</p>
<p># Autoryzacja<br />
org.code_house.cxf.user<br />
org.code_house.cxf.password</p>
<p>No i na koniec opcjonalny test, który odpytuje usługę:</p>
<pre class="brush: java;">
package org.code_house.cxf.client;
import org.code_house.services.maven.definition.ArtifactInfo;
import org.code_house.services.maven.types.FindArtifactRequest;
import org.code_house.services.maven.types.FindArtifactRespose;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;

/**
 * Proste wywołanie klasy klienta.
 *
 * @author Łukasz Dywicki &lt;a href=&quot;ldywicki@pocztowy.pl&quot;&gt;email&lt;/a&gt;
 *
 * $Id$
 */
public class MainTest extends AbstractDependencyInjectionSpringContextTests {

    /**
     * Wstrzyknięty klient.
     */
    private Client client;

    @Override
    protected String[] getConfigLocations() {
        return new String[] {&quot;classpath:client.xml&quot;};
    }

    public void testOne() {
        FindArtifactRequest request = new FindArtifactRequest();
        ArtifactInfo artifact = new ArtifactInfo();
        artifact.setGroupId(&quot;org.code_house.cxf&quot;);
        artifact.setArtifactId(&quot;contract&quot;);
        request.setQuery(artifact);

        FindArtifactRespose respose = client.getMaven().findArtifact(request);
        System.out.println(respose.getDownloadURL());
    }

    /**
     * Ustawienie wartości pola client.
     *
     * @param client Nowa wartość pola client.
     */
    public void setClient(Client client) {
        this.client = client;
    }

}</pre>
<p>To by było na tyle. Cały działający kod projektu jest już zamieszczony przy <a href="http://blog.dywicki.pl/2008/07/23/budowanie-uslugi-sieciowej-w-oparciu-o-apache-cxf/">poprzedniej nocie</a>, paczka ze wszystkimi listingami <a href="http://media.dywicki.pl/blog/cxf/cxf.zip">gotowa do pobrania</a>.</p>
<p>Teraz chyba pora zacząć opisywać mechanizmy Springa. :)</p>]]></content:encoded>
			<wfw:commentRss>http://blog.dywicki.pl/2008/09/03/budowanie-klienta-uslugi-sieciowej-w-oparciu-o-apache-cxf/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Budowanie usługi sieciowej w oparciu o Apache CXF</title>
		<link>http://blog.dywicki.pl/2008/07/23/budowanie-uslugi-sieciowej-w-oparciu-o-apache-cxf/</link>
		<comments>http://blog.dywicki.pl/2008/07/23/budowanie-uslugi-sieciowej-w-oparciu-o-apache-cxf/#comments</comments>
		<pubDate>Wed, 23 Jul 2008 06:27:55 +0000</pubDate>
		<dc:creator>Łukasz Dywicki</dc:creator>
				<category><![CDATA[CXF]]></category>
		<category><![CDATA[JAXB]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://blog.dywicki.pl/?p=219</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>Od jakiegoś czasu w pracy do tworzenia usług sieciowych korzystam z <a href="http://cxf.apache.org">Apache CXF</a>. Jako że biblioteka jest stosunkowo nowa i nie najlepiej udokumentowana postanowiłem przedstawić na blogu jak wygląda proces tworzenia.</p>
<p>CXF jest połączeniem kilku bibliotek - <a href="http://cwiki.apache.org/YOKO/">YOKO</a>, <a href="http://celtix.objectweb.org/">Celtixa</a> oraz <a href="http://xfire.codehaus.org/">XFire</a>. 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. :)<br />
<span id="more-219"></span></p>
<h3>Architektura</h3>
<p>CXF ma dosyć elastyczną budowę. Zgodnie z <a href="http://cwiki.apache.org/CXF20DOC/cxf-architecture.html">dokumentacją</a> można wyróżnić najważniejsze składowe:</p>
<ul>
<li><b>Bus</b>, jest trzonem architektury CXF w którym definiuje i konfiguruje się rozszerzenia.</li>
<li><b>Messaging &#038; Interceptors</b>, zapewniają niskopoziomowy dostęp do komunikatów oraz warstwę na której jest oparta większość funkcjonalności.</li>
<li><b>Front ends</b>, frontendy są interfejsami programistycznymi do tworzenia usług (np. JAX-WS).</li>
<li><b>Services</b>, usługi zapewniają model wraz z opisem</li>
<li><b>Bidings</b>, element ten jest odpowiedzialny za obsługę konkretnego protokołu (<acronym title="Simple Object Access Protocol">SOAP</acronym>, REST, Corba etc).</li>
<li><b>Transports</b>, warstwa abstrakcji ułatwiająca zmianę sposobu transportu do/z usług.</li>
</ul>
<h3>Markieting :)</h3>
<p>CXF oferuje infrastrukturę konieczną do budowania usług, z najważniejszy zalet można wymienić:</p>
<ul>
<li>Wsparcie dla różnych protokołów.</li>
<li>Obsługa standardów WS-*, tj. WS-Addressing, WS-Security, WS-ReliableMessaging, oraz WS-Policy.</li>
<li>Obsługa wielu transportów.</li>
<li>Dołączane data-bindingi (np JAXB, Aegis).</li>
<li>Jasny podział front endów takich jak JAX-WS od najważniejszego kodu.</li>
<li>Wysoka wydajność.</li>
<li>Możliwość osadzania w różnych środowiskach.</li>
</ul>
<p>Z dodatkowych zalet, mogę dodać - bardzo łatwą integrację ze Springiem.</p>
<h2>Pierwsza usługa</h2>
<p>Do budowania projektów będziemy używać <a href="http://maven.apache.org">Mavena</a>. Implementowana usługa będzie oparta o frontend JAX-WS z ręcznie pisanym deskryptorem usługi (<acronym title="Web Services Description Language">WSDL</acronym> first). Jakkolwiek w bardzo prosty sposób można odwrócić kolejność i przy pomocy pluginu CXF do Mavena wygenerować deskryptor.</p>
<p>Struktura projektów będzie następująca:</p>
<ul>
<li>parent<br />
         Rodzic projektu ze zdefiniowanymi wersjami bibliotek i raportami.
    </li>
<ul>
<li>contract<br />
             Definicje używane zarówno przez klienta jak i serwer - <acronym title="Web Services Description Language">WSDL</acronym> oraz konfiguracja pluginu CXF.</li>
<li>client<br />
             Prosta biblioteka kliencka oparta o mechanizmy CXFa (JaxWSProxyFactoryBean).</li>
<li>server<br />
             Przykładowa implementacja usługi z bardzo prostym wykorzystaniem Springa.</li>
<li>webapp<br />
            Konfiguracja transporty CXF - w tym konkretnym przypadku servletu CXF.</li>
</ul>
</ul>
<h2>Parent</h2>
<p>Poniżej znajduje się deskryptor projektu, który jest używany do budowania całości.</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;project xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&gt;

    &lt;!-- Informacja dla Mavena --&gt;
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;

    &lt;!-- Identyfikacja projektu --&gt;
    &lt;groupId&gt;org.code-house.cxf&lt;/groupId&gt;
    &lt;artifactId&gt;parent&lt;/artifactId&gt;
    &lt;name&gt;Code House.Org - CXF&lt;/name&gt;
    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
    &lt;packaging&gt;pom&lt;/packaging&gt;

    &lt;description&gt;Rodzic projektu, zawiera wszystkie moduly.&lt;/description&gt;

    &lt;!-- Składowe projektu --&gt;
    &lt;modules&gt;
        &lt;module&gt;cxf-client&lt;/module&gt;
        &lt;module&gt;cxf-contract&lt;/module&gt;
        &lt;module&gt;cxf-server&lt;/module&gt;
        &lt;module&gt;cxf-webapp&lt;/module&gt;
    &lt;/modules&gt;

    &lt;!-- Definicje zmiennych dostępne również w modułach --&gt;
    &lt;properties&gt;
        &lt;code-house.cxf.version&gt;2.1.1&lt;/code-house.cxf.version&gt;
        &lt;code-house.jaxb.version&gt;2.1.3&lt;/code-house.jaxb.version&gt;
        &lt;code-house.spring.version&gt;2.5.4&lt;/code-house.spring.version&gt;
    &lt;/properties&gt;

    &lt;build&gt;
        &lt;plugins&gt;
            &lt;!-- Konfiguracja kompilatora --&gt;
            &lt;plugin&gt;
                &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
                &lt;configuration&gt;
                    &lt;source&gt;1.5&lt;/source&gt;
                    &lt;target&gt;1.5&lt;/target&gt;
                &lt;/configuration&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;

    &lt;reporting&gt;
    &lt;!--Wycięte :) --&gt;
    &lt;/reporting&gt;

    &lt;!-- Predefiniowane wersje bibliotek --&gt;
    &lt;dependencyManagement&gt;
        &lt;dependencies&gt;
            &lt;dependency&gt;
                &lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
                &lt;artifactId&gt;cxf-rt-frontend-jaxws&lt;/artifactId&gt;
                &lt;version&gt;${code-house.cxf.version}&lt;/version&gt;
            &lt;/dependency&gt;
            &lt;dependency&gt;
                &lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
                &lt;artifactId&gt;cxf-rt-transports-http&lt;/artifactId&gt;
                &lt;version&gt;${code-house.cxf.version}&lt;/version&gt;
            &lt;/dependency&gt;
            &lt;dependency&gt;
                &lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
                &lt;artifactId&gt;cxf-rt-transports-http-jetty&lt;/artifactId&gt;
                &lt;version&gt;${code-house.cxf.version}&lt;/version&gt;
            &lt;/dependency&gt;
            &lt;dependency&gt;
                &lt;groupId&gt;com.sun.xml.bind&lt;/groupId&gt;
                &lt;artifactId&gt;jaxb-impl&lt;/artifactId&gt;
                &lt;version&gt;${code-house.jaxb.version}&lt;/version&gt;
            &lt;/dependency&gt;
            &lt;dependency&gt;
                &lt;groupId&gt;javax.xml.bind&lt;/groupId&gt;
                &lt;artifactId&gt;jaxb-api&lt;/artifactId&gt;
                &lt;version&gt;2.1&lt;/version&gt;
            &lt;/dependency&gt;
        &lt;/dependencies&gt;
    &lt;/dependencyManagement&gt;

&lt;/project&gt;
</pre>
<h2>Contract</h2>
<p>Zgodnie z tym, co napisałem wcześniej - przyjąłem podejście, że <acronym title="Web Services Description Language">WSDL</acronym> 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.<br />
Najistotniejsza wstawka, która powinna znaleźć się w pomie:</p>
<pre class="brush: xml;">
&lt;!-- Generowanie kodu z deskryptora <acronym title="Web Services Description Language">WSDL</acronym> --&gt;
&lt;plugin&gt;
    &lt;groupId&gt;org.apache.cxf&lt;/groupId&gt;
    &lt;artifactId&gt;cxf-codegen-plugin&lt;/artifactId&gt;
    &lt;executions&gt;
        &lt;execution&gt;
            &lt;phase&gt;generate-sources&lt;/phase&gt;
            &lt;configuration&gt;
                &lt;sourceRoot&gt;${basedir}/target/jaxws&lt;/sourceRoot&gt;
                &lt;wsdlOptions&gt;
                    &lt;wsdlOption&gt;
                        &lt;wsdl&gt;
                            ${basedir}/src/main/resources/maven.wsdl
                        &lt;/wsdl&gt;
                        &lt;extraargs&gt;
                            &lt;extraarg&gt;-quiet&lt;/extraarg&gt;
                        &lt;/extraargs&gt;
                    &lt;/wsdlOption&gt;
                &lt;/wsdlOptions&gt;
            &lt;/configuration&gt;
            &lt;goals&gt;
                &lt;goal&gt;wsdl2java&lt;/goal&gt;
            &lt;/goals&gt;
        &lt;/execution&gt;
    &lt;/executions&gt;
&lt;/plugin&gt;
</pre>
<p>Po dodaniu tej wstawki do sekcji <b>build/plugins</b> możemy przejść do tworzenia deskryptora usługi. W moim przypadku przyjąłem następujący podział:</p>
<ol>
<li>maven.wsdl - definicje metod oraz komunikatów w rozumieniu <acronym title="Web Services Description Language">WSDL</acronym> (messages). Można z powodzeniem wyłączyć z tego pliku same koperty i pozostawić metody a to co potrzebne włączyć dyrektywą <b>wsdl:import</b>.</li>
<li>types.xsd - typy używane do komunikacji - zazwyczaj pary request+response używane bezpośrednio w definiowaniu elementów <b>wsdl:part</b>.</li>
<li>definition.xsd - definicje typów złożonych, niezależnych od usług, tj. opis domain-modelu z którym usługa pracuje.</li>
</ol>
<p>Każdy z tych plików ma inną przestrzeń nazw.</p>
<h3>maven.wsdl</h3>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;wsdl:definitions xmlns:soap=&quot;http://schemas.xmlsoap.org/wsdl/soap/&quot;
    xmlns:tns=&quot;http://code-house.org/services/maven&quot;
    xmlns:types=&quot;http://code-house.org/services/maven/types&quot;
    xmlns:wsdl=&quot;http://schemas.xmlsoap.org/wsdl/&quot;
    xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot;
    targetNamespace=&quot;http://code-house.org/services/maven&quot;
    name=&quot;MavenServices&quot;
    &gt;

    &lt;wsdl:types&gt;
        &lt;xsd:schema targetNamespace=&quot;http://code-house.org/services/maven/types&quot;&gt;
            &lt;xsd:include schemaLocation=&quot;types.xsd&quot; /&gt;
        &lt;/xsd:schema&gt;
    &lt;/wsdl:types&gt;

    &lt;wsdl:message name=&quot;findArtifactRequest&quot;&gt;
        &lt;wsdl:part name=&quot;request&quot; type=&quot;types:FindArtifactRequest&quot; /&gt;
    &lt;/wsdl:message&gt;
    &lt;wsdl:message name=&quot;findArtifactResponse&quot;&gt;
        &lt;wsdl:part name=&quot;response&quot; type=&quot;types:FindArtifactRespose&quot; /&gt;
    &lt;/wsdl:message&gt;

    &lt;wsdl:portType name=&quot;MavenArtifactType&quot;&gt;
        &lt;wsdl:operation name=&quot;findArtifact&quot;&gt;
            &lt;wsdl:input message=&quot;tns:findArtifactRequest&quot; /&gt;
            &lt;wsdl:output message=&quot;tns:findArtifactResponse&quot; /&gt;
        &lt;/wsdl:operation&gt;
    &lt;/wsdl:portType&gt;

    &lt;wsdl:binding name=&quot;MavenArtifactSOAP&quot; type=&quot;tns:MavenArtifactType&quot;&gt;
        &lt;soap:binding style=&quot;document&quot; transport=&quot;http://schemas.xmlsoap.org/soap/http&quot; /&gt;
        &lt;wsdl:operation name=&quot;findArtifact&quot;&gt;
            &lt;wsdl:input&gt;
                &lt;soap:body use=&quot;literal&quot; /&gt;
            &lt;/wsdl:input&gt;
            &lt;wsdl:output&gt;
                &lt;soap:body use=&quot;literal&quot; /&gt;
            &lt;/wsdl:output&gt;
        &lt;/wsdl:operation&gt;
    &lt;/wsdl:binding&gt;

    &lt;wsdl:service name=&quot;MavenServices&quot;&gt;
        &lt;wsdl:port binding=&quot;tns:MavenArtifactSOAP&quot; name=&quot;Maven Services&quot;&gt;
            &lt;soap:address location=&quot;http://localhost:8080/webapp/services/maven&quot; /&gt;
        &lt;/wsdl:port&gt;
    &lt;/wsdl:service&gt;
&lt;/wsdl:definitions&gt;
</pre>
<h3>types.xsd</h3>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;schema xmlns=&quot;http://www.w3.org/2001/XMLSchema&quot;
    targetNamespace=&quot;http://code-house.org/services/maven/types&quot;
    xmlns:tns=&quot;http://code-house.org/services/maven/types&quot;
    xmlns:def=&quot;http://code-house.org/services/maven/definition&quot;
    elementFormDefault=&quot;qualified&quot;&gt;

    &lt;import schemaLocation=&quot;definition.xsd&quot;
        namespace=&quot;http://code-house.org/services/maven/definition&quot; /&gt;

    &lt;complexType name=&quot;FindArtifactRequest&quot;&gt;
        &lt;sequence&gt;
            &lt;element name=&quot;query&quot; type=&quot;def:ArtifactInfo&quot; /&gt;
        &lt;/sequence&gt;
    &lt;/complexType&gt;

    &lt;complexType name=&quot;FindArtifactRespose&quot;&gt;
        &lt;sequence&gt;
            &lt;element name=&quot;downloadURL&quot; type=&quot;anyURI&quot; /&gt;
        &lt;/sequence&gt;
    &lt;/complexType&gt;

&lt;/schema&gt;
</pre>
<h3>definition.xsd</h3>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;schema xmlns=&quot;http://www.w3.org/2001/XMLSchema&quot;
    targetNamespace=&quot;http://code-house.org/services/maven/definition&quot;
    xmlns:tns=&quot;http://code-house.org/services/maven/definition&quot;
    elementFormDefault=&quot;qualified&quot;&gt;

    &lt;complexType name=&quot;ArtifactInfo&quot;&gt;
        &lt;sequence&gt;
            &lt;element name=&quot;groupId&quot; type=&quot;string&quot; /&gt;
            &lt;element name=&quot;artifactId&quot; type=&quot;string&quot; /&gt;
            &lt;element name=&quot;version&quot; type=&quot;string&quot; minOccurs=&quot;0&quot; /&gt;
            &lt;element name=&quot;classifier&quot; type=&quot;tns:Classifier&quot; minOccurs=&quot;0&quot; /&gt;
            &lt;element name=&quot;packaging&quot; type=&quot;tns:Packaging&quot; minOccurs=&quot;0&quot; /&gt;
            &lt;element name=&quot;type&quot; type=&quot;tns:Type&quot; minOccurs=&quot;0&quot; /&gt;
        &lt;/sequence&gt;
    &lt;/complexType&gt;

    &lt;simpleType name=&quot;Type&quot;&gt;
        &lt;restriction base=&quot;string&quot;&gt;
            &lt;enumeration value=&quot;dll&quot; /&gt;
            &lt;enumeration value=&quot;so&quot; /&gt;
        &lt;/restriction&gt;
    &lt;/simpleType&gt;

    &lt;simpleType name=&quot;Classifier&quot;&gt;
        &lt;restriction base=&quot;string&quot;&gt;
            &lt;enumeration value=&quot;sources&quot; /&gt;
            &lt;enumeration value=&quot;javadoc&quot; /&gt;
            &lt;enumeration value=&quot;resources&quot; /&gt;
        &lt;/restriction&gt;
    &lt;/simpleType&gt;

    &lt;simpleType name=&quot;Packaging&quot;&gt;
        &lt;restriction base=&quot;string&quot;&gt;
            &lt;enumeration value=&quot;pom&quot; /&gt;
            &lt;enumeration value=&quot;jar&quot; /&gt;
            &lt;enumeration value=&quot;war&quot; /&gt;
            &lt;enumeration value=&quot;bundle&quot; /&gt;
        &lt;/restriction&gt;
    &lt;/simpleType&gt;

&lt;/schema&gt;
</pre>
<p>Po odpaleniu polecenia <b>mvn:install</b> powinniśmy otrzymać w konsoli fragment podobny do tego:</p>
<pre class="brush: plain;">
[INFO] [cxf-codegen:wsdl2java {execution: default}]
</pre>
<p>Jest to informacja, że plugin CXF został poprawnie skonfigurowany i uruchomiony.</p>
<h2>Serwer</h2>
<p>Sercem naszej usługi jest oczywiście jej implementacja dlatego też nie możemy obejść się bez niej. :) Projekt ten ma tylko dwie zależności - <b>contract</b> oraz artefakt <b>cxf-rt-frontend-jaxws</b>.</p>
<p>Konfiguracja serwera odbywa się w oparciu o springa:</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
    xmlns:jaxws=&quot;http://cxf.apache.org/jaxws&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://cxf.apache.org/jaxws
        http://cxf.apache.org/schemas/jaxws.xsd
    &quot;&gt;

    &lt;!-- Dodatkowy bean zawierający właściwą implementację logiki związanej z wyszukiwaniem --&gt;
    &lt;bean id=&quot;service&quot; class=&quot;org.code_house.services.maven.DummyMavenSearchServiceImpl&quot; /&gt;

    &lt;!-- Bean będący implementacją usługi jako takiej - obsługujący wejście/wyjście --&gt;
    &lt;bean id=&quot;mavenService&quot; class=&quot;org.code_house.services.maven.MavenArtifactTypeImpl&quot;&gt;
        &lt;property name=&quot;service&quot; ref=&quot;service&quot; /&gt;
    &lt;/bean&gt;

    &lt;!-- Konfiguracja endpointu CXFa --&gt;
    &lt;jaxws:endpoint address=&quot;maven&quot; id=&quot;jaxwsMavenService&quot; implementor=&quot;#mavenService&quot; /&gt;

&lt;/beans&gt;
</pre>
<p>Serwer zawiera w zasadzie niewiele kodu, oto i on:</p>
<pre class="brush: java;">
package org.code_house.services.maven;

import java.net.URISyntaxException;

import javax.jws.WebService;

import org.code_house.services.maven.definition.ArtifactInfo;
import org.code_house.services.maven.types.FindArtifactRequest;
import org.code_house.services.maven.types.FindArtifactRespose;

/**
  * Implementacja usługi.
  */
@WebService(serviceName = &quot;MavenService&quot;,
    endpointInterface = &quot;org.code_house.services.maven.MavenArtifactType&quot;,
    targetNamespace = &quot;http://code-house.org/services/maven&quot;
)
public class MavenArtifactTypeImpl implements MavenArtifactType {

    /**
      * Bean zawierający implementację logiki biznesowej.
      */
    private MavenSearchService service;

    public FindArtifactRespose findArtifact(FindArtifactRequest request) {
        ArtifactInfo info = request.getQuery(); // pobranie struktury przekazanej od klienta

        // sformuowanie odpowiedzi
        FindArtifactRespose response = new FindArtifactRespose();
        try {
            response.setDownloadURL(service.find(info).toURI().toString());
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
        return response;
    }

    /**
     * Ustawienie wartości pola service.
     *
     * @param service Nowa wartość pola service.
     */
    public void setService(MavenSearchService service) {
        this.service = service;
    }
}
</pre>
<p>Dodatkowy kod, który nie jest konieczny do implementacji usługi to definicja interfejsu <b>MavenSearchService</b>. Dzięki zastosowaniu takiego rozwiązania można w prostszy sposób testować działanie usługi poprzez przekazywanie jej mocka stworzonego np. przy pomocy <a href="http://easymock.org">easy mocka</a>. Kod takiego testu pominąłem ze względu na to, że notka i tak już jest za długa w tym momencie a jesteśmy ledwo w połowie drogi. :)</p>
<p>Przykładowa implementacja wcześniej wspomnianego intefejsu nie zawiera żadnej logiki i zawsze zwraca tą samą wartość.</p>
<pre class="brush: java;">
package org.code_house.services.maven;

import java.net.MalformedURLException;
import java.net.URL;

import org.code_house.services.maven.definition.ArtifactInfo;

// Najprostsza implementacja tylko po to żeby sprawdzić działanie usługi
public class DummyMavenSearchServiceImpl implements MavenSearchService {

    public <acronym title="Uniform Resource Locator">URL</acronym> find(ArtifactInfo info) {
        try {
            return new <acronym title="Uniform Resource Locator">URL</acronym>(&quot;http://repo1.maven.org/maven2/org/apache/apache/4/apache-4.pom&quot;);
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }
    }

}
</pre>
<p>Zanim odpalimy serwer konieczna będzie jeszcze jedna rzecz - konfiguracja transporu, w naszym przypadku servletu CXF.</p>
<h2>Webapp</h2>
<p>Webapp posiada bezpośrednie zależności do 2 artefaktów CXFa: <b>cxf-rt-transports-http</b> oraz <b>cxf-rt-bindings-http</b>. Druga jest opcjonalna, bez niej CXF nie będzie wyświetlał dostępnych usług w postaci tabelki html.</p>
<p>Przydatna może być wtyczka jetty (sekcja <b>build/plugins</b>), która pozwala na uruchomienie aplikacji bez konieczności instalowania kontenera servletów:</p>
<pre class="brush: xml;">
&lt;plugin&gt;
    &lt;groupId&gt;org.mortbay.jetty&lt;/groupId&gt;
    &lt;artifactId&gt;maven-jetty-plugin&lt;/artifactId&gt;
    &lt;version&gt;6.1.11&lt;/version&gt;
    &lt;configuration&gt;
        &lt;scanIntervalSeconds&gt;10&lt;/scanIntervalSeconds&gt;
        &lt;connectors&gt;
            &lt;connector implementation=&quot;org.mortbay.jetty.nio.SelectChannelConnector&quot;&gt;
                &lt;port&gt;8080&lt;/port&gt;
                &lt;maxIdleTime&gt;60000&lt;/maxIdleTime&gt;
            &lt;/connector&gt;
        &lt;/connectors&gt;
    &lt;/configuration&gt;
&lt;/plugin&gt;
</pre>
<p>Ostatnia zależność odnosi się do implementacji usługi - czyli naszego artefaktu <b>server</b>. Najistotniejsze elementy konfiguracji webappa to web.xml oraz cxf-beans.xml.</p>
<h3>web.xml</h3>
<p>Warto zauważyć w poniższym listingu fajną możliwość, którą daje nam Spring w postaci wildcardów określających położenie konfiguracji - w tym przypadku <b>classpath:/module/*-context.xml</b>. Oznacza to, że Spring przeskanuje wszystkie biblioteki od których zależy projekt i dołączy ich konfigurację do głownej, dzięki czemu będziemy mogli uzyskać bardziej modułową i elastyczną budowę aplikacji. Może <a href="http://www.springframework.org/osgi">Dynamic Modules</a> to nie jest ale na codzień w zupełności wystarcza :).</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;web-app id=&quot;ocs&quot; version=&quot;2.5&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xmlns=&quot;http://java.sun.com/xml/ns/javaee&quot;
    xmlns:web=&quot;http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&quot;
    xsi:schemaLocation=&quot;
        http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&quot;
    &gt;

    &lt;!-- Informacje nazewnicze dla kontenera --&gt;
    &lt;display-name&gt;Maven Search Services :: Webapp&lt;/display-name&gt;
    &lt;description&gt;Frontend indeksera.&lt;/description&gt;

    &lt;!-- Lokalizacje plików konfiguracyjnych --&gt;
    &lt;context-param&gt;
        &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
        &lt;param-value&gt;
            &lt;!-- Konfiguracja zabezpieczeń opartych o spring secuirty --&gt;
            /WEB-INF/security.xml
            &lt;!-- Konfiguracja CXF --&gt;
            /WEB-INF/cxf-beans.xml
            &lt;!-- Konfiguracja kontekstu --&gt;
            /WEB-INF/applicationContext.xml
            &lt;!-- Wczytanie konfiguracji modułów --&gt;
            classpath:/module/*-context.xml
        &lt;/param-value&gt;
    &lt;/context-param&gt;

    &lt;!-- Servlet obsługujący usługi sieciowe --&gt;
    &lt;servlet&gt;
        &lt;servlet-name&gt;CXFServlet&lt;/servlet-name&gt;
        &lt;servlet-class&gt;org.apache.cxf.transport.servlet.CXFServlet&lt;/servlet-class&gt;
        &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
    &lt;/servlet&gt;

    &lt;!-- Mapowanie adresu usług sieciowych --&gt;
    &lt;servlet-mapping&gt;
        &lt;servlet-name&gt;CXFServlet&lt;/servlet-name&gt;
        &lt;url-pattern&gt;/services/*&lt;/url-pattern&gt;
    &lt;/servlet-mapping&gt;

    &lt;!-- Inicjowanie kontekstu springa --&gt;
    &lt;listener&gt;
        &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
    &lt;/listener&gt;

&lt;/web-app&gt;
</pre>
<h3>cxf-beans.xml</h3>
<p>Plik ten zawiera definicje konfiguracyjne CXFa. W poniższej formie włączana jest tylko część modułów CXF w celu zmniejszenia użycia zasobów.</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;beans xmlns=&quot;http://www.springframework.org/schema/beans&quot;
    xmlns:cxf=&quot;http://cxf.apache.org/core&quot;
    xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    xsi:schemaLocation=&quot;
        http://cxf.apache.org/core
        http://cxf.apache.org/schemas/core.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
    &quot;&gt;

    &lt;!-- Moduły CXF-a --&gt;
    &lt;import resource=&quot;classpath:META-INF/cxf/cxf.xml&quot;/&gt;
    &lt;import resource=&quot;classpath:META-INF/cxf/cxf-extension-soap.xml&quot;/&gt;
    &lt;import resource=&quot;classpath:META-INF/cxf/cxf-extension-http-binding.xml&quot;/&gt;
    &lt;import resource=&quot;classpath:META-INF/cxf/cxf-servlet.xml&quot;/&gt;

&lt;/beans&gt;
</pre>
<p>Pozostałe pliki konfiguracyjne są praktycznie puste, ponieważ tyczą się obszarów niezwiązanych z tematem tego wpisu. Po tym wszystkim możemy uruchomić naszą aplikację poleceniem <b>mvn jetty:run</b>. Po wejściu na adres http://localhost:8080/webapp/services naszym oczom powinna ukazać się lista podobna do poniższej:<br />
<img src="http://blog.dywicki.pl/wp-content/uploads/2008/07/services.jpg" alt="services" title="services" /><br />
Nie wiem niestety dlaczego CXF generuje zły adres usługi (pomijający mapowanie servletu) oraz ma problemy z wystawieniem WSDLa. Jakkolwiek i bez tego wszystko działa poprawnie - znaczy wywoływanie usług rzecz jasna. :)</p>
<p><a href="http://blog.dywicki.pl/wp-content/uploads/2008/07/soap-ui.jpg" style="text-decoration: none" rel="lightbox"><img src="http://blog.dywicki.pl/wp-content/uploads/2008/07/soap-ui-300x182.jpg" alt="soap-ui" title="soap-ui" width="300" height="182" align="right" /></a> W tym momencie możemy uruchomić <a href="http://www.soapui.org/">Soap UI</a> i wykonać jedyną dostępną metodę - findArtifact.</p>
<h2>Client</h2>
<p>Ostatnim z elementów, który pozostał do omówienia jest klient. Niestety z racji na to, że ta nota już się wystarczająco rozrosła zrobię to w kolejnym wpisie. Mam nadzieję, że nota ta nieco ułatwi przyszłym użytkownikom CXFa jego poznanie. :) Dla tych, którym nie chce się wpisywać tego wszystkiego w edytorze <a href="http://media.dywicki.pl/blog/cxf/cxf.zip">zamieszczam źródła</a> razem z działającym klientem. Projekty nie są nadzwyczajnie dopieszczone, ale w zupełności wystarczą do startu. Znajduje się też tam w pełni działający klient stworzonej usługi. Pozdrawiam i życzę miłej zabawy!</p>]]></content:encoded>
			<wfw:commentRss>http://blog.dywicki.pl/2008/07/23/budowanie-uslugi-sieciowej-w-oparciu-o-apache-cxf/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>
