Narzędzia i aplikacje Java EE Usługi sieciowe Paweł Czarnul pczarnul@eti.pg.gda.pl Niniejsze opracowanie wprowadza w technologię usług sieciowych i implementację usługi na platformie Java EE (JAX-WS) z wykorzystaniem serwera GlassFish jak również klienta usługi sieciowej w postaci aplikacji Java. Technologia usług sieciowych (ang. Web Services) pozwala na implementację przetwarzania w architekturze SOA (Service Oriented Architecture). Architektura ta wyróżnia pojęcie luźno powiązanych usług, które mogą być dostarczane przez niezależnych dostawców i integrowane ze sobą. Zdalne wołanie usługi wiąże się z kilkoma problemami, m.in. koniecznością znajomości usług, które realizują daną funkcję (np. rezerwacja biletów lotniczych), a następnie lokalizacji usługi jak również technicznych aspektów wywołania usługi sieciowej takich jak nazwa metody lub metod do rezerwacji, wymagane parametry do ww. metod. Problemy te rozwiązuje się w następujący sposób. Schemat wywołania usługi sieciowej od momentu publikacji wygląda następująco: klient 2. Pobierz listę usług np. realizujących daną funkcję Rejestr UDDI 3. Pobranie szczegółów technicznych o usłudze + wywołanie usługi i pobranie wyników 1. Publikacja informacji O usłudze w rejestrze UDDI usługa 1. Dostawca usługi (po wdrożeniu samej usługi na wybranym serwerze) publikuje informacje o usłudze jak również o sobie w rejestrze UDDI będącym odpowiednikiem książki telefonicznej dla usług. 2. Klient przeszukuje rejestr UDDI w poszukiwaniu usług, które realizują zadaną funkcję (np. rezerwację biletów lotniczych) 3. Po pobraniu informacji o usłudze (lub usługach) klient może przystąpić do wywołania usługi. W tym celu, klient musi znać szczegóły wywołania usługi sieciowej, w tym listę
metod dostępnych do wywołania w ramach usługi jak również ich szczegóły takie jak argumenty wejściowe metod i ich typy oraz typ zwracany. Te informacje można pobrać z opisu technicznego usługi sieciowej, który udostępniany jest w formie opisu WSDL (ang. Web Service Description Language) z serwera, na którym usługa została wdrożona. Z opisu WSDL klient może wygenerować pewien kod pomocniczy po stronie klienta (tzw. stub), który wykona zdalne wywołanie usługi. Kod klienta wywołuje w tej sytuacji metodę na stubie co powoduje zdalne wywołanie usługi i zwrócenie wyników. System, na którym działa usługa jak i klient mogą być zupełnie niezależne, podobnie jak języki programowania, w których zostały zaimplementowane. Jest to możliwe dzięki uniwersalnemu opisowi usługi w postaci WSDL jak również standardom formatowania i przesyłania danych pomiędzy klientem a usługą. W tym celu wykorzystuje się formatowanie danych w formacie SOAP (wykorzystujący XML). Tak reprezentowane są dane wejściowe przesyłane od klienta do usługi i wyniki od usługi do klienta. Daje to dużą uniwersalność, wiąże się jednak ze sporymi narzutami (XML) w porównaniu do innych technologii i w związku z tym mniejszą wydajnością. W ramach przykładu, zaprezentowane zostanie wdrożenie usługi sieciowej na serwerze GlassFish oraz kod klienta, który wywołuje daną usługę (JAX-WS). Przykład zostanie zaprezentowany za pomocą środowiska Netbeans 6.9.1, które wymaga Java SDK w wersji 6. Instalacja Java SDK polega na rozpakowaniu paczki z dystrybucją do dowolnego katalogu, ustawienie zmiennej JAVA_HOME na ten katalog i dodanie ścieżki $JAVA_HOME/bin do zmiennej PATH (Linux). Warto dodać te ustawienia do pliku.bashrc np. w następujący sposób: export JAVA_HOME=/home/netbeans/jdk1.6.0_22 export PATH=$JAVA_HOME/bin:$PATH Instalacja środowiska Netbeans 6.9.1 jest równie prosta i wymaga realizowania instrukcji podanych podczas instalacji. Usługa sieciowa może zostać wdrożona na dwa sposoby za pomocą aplikacji Web Application kategorii Java Web lub też modułu EJB z kategorii Java EE. 1. Wdrożenie usługi sieciowej w ramach Web Application kategorii Java Web. Z menu wybierz Choose File -> New Project. Wybierz Java Web oraz Web Application. Nazwij aplikację np. RunTaskWSApplication1 Następnie należy wybrać serwer i wersję Java EE oraz kliknąć Finish. Po kliknięciu na daną aplikację w drzewie plików (zakładka Projects) należy kliknąć na główny węzeł aplikacji prawym przyciskiem myszy i wybrać New -> Web Service. Nazwij usługę sieciową np. RunTaskWS i zdefiniuj nazwę pakietu np. runtask. Wybierz opcję Implement Web Service as a Stateless Session Bean i zakończ.
Następnie w zakładce Projects znajdź zdefiniowaną usługę sieciową, kliknij na nią prawym przyciskiem i dodaj metodę, którą będzie można wywołać w ramach usługi sieciowej wybierz opcję Add operation. Zdefiniuj nazwę jako RunTask, argumenty wejściowe jako: String taskname oraz typ zwracany jako int. Usługa będzie wywoływała zadane polecenie na serwerze, na którym została wdrożona i zwracała klientowi kod operacji. Następnie w edytorze kodu uzupełnij kod metody RunTask w następujący sposób: package runtask; import javax.jws.webmethod; import javax.jws.webparam; import javax.jws.webservice; import javax.ejb.stateless; import java.io.*; * * @author netbeans @WebService() @Stateless() public class RunTaskWS { * Web service operation @WebMethod(operationName = "RunTask") public int RunTask(@WebParam(name = "taskname") String taskname) { //TODO write your implementation code here: try { Process p = Runtime.getRuntime().exec(taskname); catch (IOException e1) { System.err.println(e1); // return 0; Po skompilowaniu kodu ( Clean and Build klikając prawym przyciskiem myszy na głównym węźle aplikacji) wybieramy Deploy wdrożenie na serwerze. W konsoli serwera GlassFish powinniśmy zobaczyć lokalizację wdrożonej usługi. W tym przypadku usługa dostępna jest pod adresem: http://localhost:8080/runtaskwsservice/runtaskws
Wpisując w przeglądarce adres: http://localhost:8080/runtaskwsservice/runtaskws?tester uzyskamy możliwość zdefiniowania argumentu wejściowego i wywołanie usługi z przeglądarki. Wpisanie argumentu emacs spowoduje uruchomienie tej aplikacji po wywołaniu usługi sieciowej jeśli oczywiście emacs został zainstalowany na serwerze, na którym wdrożona została usługa. Interfejs graficzny wywołania wygląda następująco: zaś wynik:
Można również zobaczyć żądanie SOAP przesyłane od klienta do usługi jak również zwracany wynik: 2. W podobny sposób można wdrożyć usługę na serwerze wybierając EJB Module z kategorii Java EE przy tworzeniu aplikacji. Definiujemy nazwę modułu jako np.:
RunTaskEJBModule1, zaś w nim analogicznie jak poprzednio usługę sieciową. Kod analogicznej usługi sieciowej może wyglądać następująco: package runtask; import javax.jws.webmethod; import javax.jws.webparam; import javax.jws.webservice; import javax.ejb.stateless; import java.io.*; * * @author netbeans @WebService() @Stateless() public class RunTaskService1 { * Web service operation @WebMethod(operationName = "RunTask") public int RunTask(@WebParam(name = "taskname") String taskname) { //TODO write your implementation code here: try { Process p = Runtime.getRuntime().exec(taskname); catch (IOException e1) { System.err.println(e1); // return 0; W sposób analogiczny możemy przetestować działanie usługi za pomocą przeglądarki wpisując adres pokazany w konsoli serwera GlassFish w tym przypadku: http://localhost:8080/runtaskservice1service/runtaskservice1?tester Możemy teraz stworzyć niezależną aplikację klienta (w języku Java), która wywoła kod żądanej usługi. Można to zrobić w ww. środowisku w następujący sposób. Należy wybrać Choose File -> New Project, a następnie Java Application z kategorii Java. Należy zdefiniować nazwę aplikacji np. RunTaskClientApplication1.
Klikając prawym przyciskiem myszy na głównym węźle aplikacji klienta wybieramy New-> Web Service Client. Wybieramy metodę usługi, którą chcemy wywołać (Browse). Następnie wystarczy uzupełnić kod klienta (klasa Main). Po przeciągnięciu metody usług sieciowej do metody main klasy Main generowany zostaje kod: private static int runtask(java.lang.string taskname) { runtask.runtaskservice1service service = new runtask.runtaskservice1service(); runtask.runtaskservice1 port = service.getruntaskservice1port(); return port.runtask(taskname); Następnie można wywołać usługę sieciową z metody main dodając wywołanie: runtask("emacs"); Po skompilowaniu i uruchomieniu aplikacji powinniśmy zobaczyć okno aplikacji emacs uruchomionej po wywołaniu usługi.