#22.1 — Web Services (SOAP)

By 9 April 2015 Kurs Javy

Dzisi­aj kon­tynu­ac­ja lekcji o Web Ser­vices — poz­namy bliżej tech­nol­gię SOAP oraz sposób, w jaki może­my z niej korzystać.

Ta lekc­ja omaw­ia tylko jed­no z pode­jść do tworzenia ser­wisów SOAPowych, tzw. Code-first approach. W tym pode­jś­ciu najpierw tworzymy kod (mówiąc dokład­niej, inter­fe­js w języku pro­gramowa­nia) i na tej pod­staw­ie pozwalamy bib­liotekom samodziel­nie wygen­erować pli­ki WSDL i wszys­tkie inne potrzeb­ne ele­men­ty. To pode­jś­cie jest prost­sze i moż­na je wyko­rzys­tać, jeśli tworzymy nowe API lub inte­gru­je­my tylko poje­dyncze sys­te­my. Powo­dem jest to, że każ­da zmi­ana w naszych klasach potenc­jal­nie wpły­wa na zmi­anę definicji Web Ser­vice (czyli pliku WSDL) przez co klien­ci, którzy uży­wa­ją naszego ser­wisu mogą przes­tać działać.

Drugie pode­jś­cie, to con­tract-first, w którym to najpierw mamy kon­trakt (np. plik WSDL albo plik XSD opisu­ją­cy wszys­tkie ele­men­ty) i na tej pod­staw­ie generu­je­my kod. Takie pode­jś­cie jest lep­sze np. kiedy nasz sys­tem ma zastąpić ist­nieją­cy już sys­tem w sposób nieza­uważal­ny dla jego użytkown­ików — pode­jś­cie con­tract-first gwaran­tu­je, że z punk­tu widzenia użytkown­ików Web­Ser­vice będzie wyglą­dał dokład­nie tak, jak tego oczeku­je­my. Jest to jed­nak bardziej prob­lematy­czne w imple­men­tacji i wyma­ga więk­szej wiedzy, dlat­ego w tej lekcji skupimy się jedynie na pier­wszym pode­jś­ciu dla zrozu­mienia pod­sta­wowych konceptów.

Lekcja

W tej częś­ci lekcji będziemy korzys­tali z bib­liote­ki o nazwie CXF. Bib­liote­ka ta wewnętrznie korzys­ta ze Springa, także jej inte­grac­ja z ist­niejącą aplikacją webową nie stanowi prob­le­mu. Jest to jeden z najpop­u­larniejszych frame­worków, który pozwala nie tylko udostęp­ni­ać ser­wisy (pro­dukować), ale także z nich korzys­tać (kon­sumować). Aby dodać bib­liotekę CXF do pro­jek­tu, doda­je­my następu­jące dependency:

<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxws</artifactId>
    <version>3.0.4</version>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http</artifactId>
    <version>3.0.4</version>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-transports-http-jetty</artifactId>
    <version>3.0.4</version>
</dependency>

Ter­az może­my już przys­tąpić do imple­men­tacji naszego serwisu.

Wystawiamy web service

Zmiany w web.xml

Przede wszys­tkim musimy dokon­ać paru zmi­an w pliku web.xml, a dokład­niej dodać servlet, który poz­woli CXF obsługi­wać wywoła­nia SOAPowe nieza­leżnie od naszego Dis­patch­erServlet. W tym celu do pliku web.xml doda­je­my następu­ją­cy fragment:

<servlet>
    <servlet-name>CXFServlet</servlet-name>
    <display-name>CXF Servlet</display-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <load-on-startup>1</load-on-startup> 
</servlet>

<servlet-mapping>
    <servlet-name>CXFServlet</servlet-name>
    <url-pattern>/api/soap/*</url-pattern>
</servlet-mapping>

Zwróć uwagę, na mapowanie (tag <servlet-map­ping>)! Tutaj musimy podać wzór adresu, pod jakim będziemy udostęp­niali nasze web ser­vices. Jeśli wybierzesz inny adres, pamię­taj aby zak­tu­al­i­zować go także w tym miejscu.

Dodajemy klasę

Ter­az zajmiemy się samą imple­men­tacją. Ser­wisy webowe imple­men­tu­je­my podob­nie jak nor­malne ser­wisy, jedyne co się zmiena to adno­tac­je, których uży­wamy. Dla przykładu napisze­my prosty ser­wis, który zawsze odpowia­da ‘pong’ na każde zapy­tanie. Pami­etaj, że taki ser­wis też jest beanem Spring’a, więc możesz uży­wać wszys­t­kich jego dobrodziejstw, włącznie z @Autowired. Poniżej mamy dwie klasy:

package pl.kobietydokodu;

import javax.jws.WebService;
import javax.jws.WebMethod;

@WebService
public interface PongServiceInterface {
    @WebMethod(operationName="ping")
    public String ping();
}

 

package pl.kobietydokodu;

import javax.jws.WebService; 

@WebService(endpointInterface="pl.kobietydokodu.PongServiceInterface", serviceName="PongService")
public class PongServiceImpl implements PongServiceInterface {
    @Override
    public String ping() {
        return "pong";
    }
}

Pier­wsza z nich to inter­fe­js, który określa, jak metody będą widoczne dla klien­ta (tzn. pod jaką nazwą). Dru­ga klasa to imple­men­tac­ja tego inter­fe­j­su, czyli konkret­na funkcjon­al­ność w Javie, która real­izu­je naszą logikę. Do kom­ple­tu potrze­bu­je­my tylko zmi­any w pliku rootContext.xml, doda­jąc nasz web service:

<jaxws:endpoint id="PongService" implementor="pl.kobietydokodu.PongServiceImpl" address="/api/soap/pong"/>

Zwróć uwagę, że adres (atry­but address) pasu­je do wzor­ca, który zapisal­iśmy w pliku web.xml w poprzed­nim kroku! Imple­men­tor to peł­na nazwa kwal­i­fikowana (czyli nazwa paki­etu + nawa klasy) naszej implementacji.

Pamię­taj też, aby dodać name­space jaxws (http://cxf.apache.org/jaxws -> http://cxf.apache.org/schemas/jaxws.xsd) do pliku XML!

I koniec! Tyle wystar­czy, żeby nasz kod stał się ser­wisem webowym :)

Zobaczmy ter­az, jak utworzyć klien­ta naszego serwisu.

Korzystamy z web service

Korzys­tanie z Web­Ser­vice jest równie proste, co jego tworze­nie. Zakłada­jąc, że mamy dostęp do klasy inter­fe­j­su, w pliku web­Con­text wystar­czy dodać następu­ją­cy zapis:

<jaxws:client id="pongClient" serviceClass="pl.kobietydokodu.PongServiceInterface" address="http://localhost:8080/api/soap/pong" />

W dowol­nym miejs­cu kodu może­my wtedy sko­rzys­tać z funkcji Autowire:

@Autowired
PongServiceInterface pongService;

Aby móc korzys­tać z naszego web ser­vice. Oczy­wiś­cie w deklaracji musimy podać właś­ci­wy adres (praw­dopodob­nie nie będzie to localhost).

Podsumowanie

W tej lekcji nauczyłąś się tworzyć i uży­wać ser­wisy typu REST oraz SOAP. Wiedza ta oczy­wiś­cie nie pokry­wa wszys­t­kich obszarów dzi­ała­nia web ser­vices, ale wystar­czy, żebyś samodziel­nie szukała i zdoby­wała dal­szą wiedzę w zależnoś­ci od potrzeb. Ser­wisy webowe to bard­zo potężne narzędzie, które zna­j­du­je zas­tosowanie w wielu dziedz­i­nach i z pewnoś­cią spotkasz je w swo­jej kari­erze bard­zo szybko.

Zadanie

Zmody­fikuj pro­gram, który już napisałaś tak, doda­jąc do niego API SOAPowe. Powin­no one być dostęp­ne pod adresem /api/soap i ofer­ować takie same funkcjon­al­noś­ci, jak API stwor­zone w częś­ci o RESTach.

Licencja Creative Commons

Jeśli uważasz powyższą lekcję za przy­dat­ną, mamy małą prośbę: pol­ub nasz fan­page. Dzię­ki temu będziesz zawsze na bieżą­co z nowy­mi treś­ci­a­mi na blogu ( i oczy­wiś­cie, z nowy­mi częś­ci­a­mi kur­su Javy). Dzięki!