Tworzenie usługi sieciowej z JAX-WS, Apache Geronimo 2 i NetBeans 6
Z Jacek Laskowski - Wiki Projektanta Java EE
W ostatnim artykule dotyczącym tworzenia usług sieciowych z wykorzystaniem JAX-WS - Tworzenie usługi sieciowej z JAX-WS korzystałem z pomocy serwera aplikacji GlassFish 2 oraz narzędzi Apache Maven 2 i Eclipse 3.3. W przykładzie użyłem obowiązkowych adnotacji @WebService oraz @WebMethod, odpowiednio do określenia klasy jako usługi sieciowej oraz metod usługi. Tym razem skorzystam ze wsparcia NetBeans 6 do utworzenia usługi sieciowej, którą następnie uruchomię na wersji rozwojowej serwera Apache Geronimo 2.1. Ciekawostką Geronimo będzie możliwość uruchomienia usługi w ramach aplikacji internetowej bez deskryptora web.xml. Na zakończenie utworzę klienta usługi jako samodzielną aplikację.
Spis treści |
Oprogramowanie
Środowisko składa się z następujących narzędzi:
- Apache Geronimo 2.1 (wersja rozwojowa z Jetty 6)
- NetBeans IDE 6.0 RC1
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.
Kompletne projekty katalog-jaxws-geronimo oraz katalog-jaxws-geronimo-klient do zaimportowania do NetBeans 6 dostępne są do pobrania jako katalog-jaxws-geronimo.zip.
Utworzenie usługi Katalog w NetBeans
Utworzenie projektu aplikacji internetowej - katalog-jaxws-geronimo
Rozpoczynamy od utworzenia projektu aplikacji internetowej katalog-jaxws-geronimo. Korzystamy z kombinacji klawiszy Ctrl+Shift+N, gdzie wybieramy Web > Web Application.
Wciskamy przycisk Next >.
W okienku dialogowym New Web Application w polu Project Name wpisujemy katalog-jaxws-geronimo i wybieramy miejsce utworzenia aplikacji - pole Project Location, np. C:
Wciskamy przycisk Finish.
Klasa usługi sieciowej Katalog - pl.jaceklaskowski.katalog.ws.KatalogWS
Przechodzimy do utworzenia usługi sieciowej Katalog. Mając zaznaczony nowoutworzony projekt katalog-jaxws-geronimo wciskamy Ctrl+N, gdzie wybieramy Web Services > Web Service.
Wciskamy przycisk Next >.
W oknie dialogowym New Web Service podajemy następujące parametry:
- Web Service Name: KatalogWS
- Package: pl.jaceklaskowski.katalog.ws
Zatwierdzamy przyciskiem Finish.
Dodajemy nową metodę usługi KatalogWS wciskając przycisk Add Operation...
W oknie dialogowym Add Operation... podajemy następujące parametry metody sieciowej:
- Name: iloscPozycji
- Return type: int
oraz w zakładce Parameters po wciśnięciu przycisku Add:
- Name: nazwaKatalogu
Zatwierdzamy przyciskiem OK.
Nasza usługa wygląda następująco w NetBeans w trybie Design.
Zmieniamy tryb prezentacji na Source (lewy górny róg edytora usługi) i zmieniamy źródło usługi na następujące:
package pl.jaceklaskowski.katalog.ws;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
@WebService(serviceName = "Katalog")
public class KatalogWS {
@WebMethod(operationName = "iloscPozycji")
public int iloscPozycji(
@WebParam(name = "nazwaKatalogu") String nazwaKatalogu) {
return nazwaKatalogu == null ? null : nazwaKatalogu.length();
}
@PostConstruct
void init() {
Logger.getLogger("katalog").info("Usluga sieciowa Katalog utworzona");
}
@PreDestroy
void destroy() {
Logger.getLogger("katalog").info("Usluga sieciowa Katalog niszczona");
}
}
W ten sposób zmieniamy nazwę usługi na Katalog poprzez skorzystanie z atrybutu serviceName adnotacji @WebService. Dodaliśmy również dwie metody zwrotne - pierwsza metoda init() z adnotacją @PostConstruct wykonywana po uruchomieniu usługi przez serwer aplikacyjny a przed obsługą pierwszego żądania klienta oraz druga destroy() z adnotacją @PreDestroy wykonywaną na moment przed zniszczeniem usługi przez serwer (np. podczas jego zatrzymania).
Zapisujemy zmiany wciskając Ctrl+S.
Usunięcie deskryptora aplikacji internetowej - web.xml
Usuwamy deskryptor aplikacji internetowej web.xml z Web Pages > WEB-INF.
Opcjonalnie możemy również usunąć stronę index.jsp, bądź zmodyfikować tak, aby przekierowywała na adres usługi sieciowej Katalog.
<jsp:forward page="Katalog" />
Utworzenie planu wdrożenia dla Geronimo - geronimo-web.xml
W katalogu Web Pages > WEB-INF tworzymy plik geronimo-web.xml. Jest to plik definiujący nazwę dla naszej aplikacji, która upraszcza późniejsze nią zarządzanie z poziomu Geronimo. Dodatkowo jest to sposób na przypisanie nazwy kontekstu aplikacji na /katalog (w przeciwnym przypadku byłaby katalog-jaxws-geronimo - nazwa odpowiadająca nazwie pliku war bez rozszerzenia).
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1">
<dep:environment xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2">
<dep:moduleId>
<dep:groupId>pl.jaceklaskowski.katalog</dep:groupId>
<dep:artifactId>katalog-webservice</dep:artifactId>
<dep:version>1.0</dep:version>
<dep:type>war</dep:type>
</dep:moduleId>
</dep:environment>
<context-root>/katalog</context-root>
</web-app>
Uruchomienie usługi Katalog na Geronimo
Na razie nie istnieje mechanizm w NetBeans, za pomocą którego możnaby uruchomić aplikację webową bezpośrednio w Geronimo. Posiłkujemy się obejściem, które polega na zbudowaniu aplikacji w NetBeans i skorzystanie z konsoli Geronimo bądź polecenia deploy z poziomu linii poleceń do jej wdrożenia (instalacji).
Skorzystamy z polecenia deploy.
Uruchomienie Geronimo
Uruchomienie aplikacji webowej zaczynamy od jej wdrożenia na serwerze Geronimo. Uruchamiamy Geronimo poleceniem ./bin/geronimo.sh run -vv. Parametr -vv (veryverbose) instruuje Geronimo, aby wyświetlał komunikaty niższego poziomu, które są niezwykle przydatne podczas tworzenia aplikacji. Zalecane jest, aby nie stosować tego parametru podczas uruchomienia produkcyjnego, właśnie ze względu na ilość wypisywanych komunikatów.
Przechodzimy do katalogu Geronimo i wydajemy polecenie ./bin/geronimo.sh run -vv (na systemie Windows będzie to odpowiednio geronimo.bat).
jlaskowski@dev /cygdrive/c/geronimo $ ./bin/geronimo.sh run -vv Using GERONIMO_BASE: c:\geronimo Using GERONIMO_HOME: c:\geronimo Using GERONIMO_TMPDIR: c:\geronimo\var\temp Using JRE_HOME: c:\apps\java5\jre 15:57:09,796 DEBUG [BasicKernel] Starting boot 15:57:09,968 DEBUG [GBeanInstanceState] GBeanInstanceState for: geronimo/boot/none/car?role=kernel State changed from stopped to starting 15:57:09,968 DEBUG [GBeanInstanceState] GBeanInstanceState for: geronimo/boot/none/car?role=kernel State changed from starting to running 15:57:09,968 DEBUG [BasicKernel] Booted 15:57:10,031 DEBUG [AbstractRepository] Repository root is C:\geronimo\repository ... 15:57:50,562 INFO [startup] Deployed Application(path=C:\.m2\org\apache\geronimo\applications\geronimo-mejb\2.1-SNAPSHOT\geronimo-mejb-2.1-SNAPSHOT.jar) Geronimo startup complete
Konsola administracyjna znajduje się domyślnie pod adresem http://localhost:8080/console. Można z niej również skorzystać do instalacji.
Zbudowanie aplikacji internetowej w NetBeans - katalog-jaxws-geronimo.war
Z poziomu NetBeans wydajemy polecenie Clean and Build.
W ten sposób, w katalogu C:\katalog-jaxws-geronimo\dist NetBeans umieści naszą aplikację - katalog-jaxws-geronimo.war.
init: deps-clean: do-clean: check-clean: clean: init: deps-module-jar: deps-ear-jar: deps-jar: Created dir: C:\katalog-jaxws-geronimo\build\web\WEB-INF\classes Created dir: C:\katalog-jaxws-geronimo\build\web\META-INF Copying 1 file to C:\katalog-jaxws-geronimo\build\web\META-INF Copying 3 files to C:\katalog-jaxws-geronimo\build\web Copied 1 empty directory to 1 empty directory under C:\katalog-jaxws-geronimo\build\web library-inclusion-in-archive: library-inclusion-in-manifest: Compiling 1 source file to C:\katalog-jaxws-geronimo\build\web\WEB-INF\classes compile: compile-jsps: Created dir: C:\katalog-jaxws-geronimo\dist Building jar: C:\katalog-jaxws-geronimo\dist\katalog-jaxws-geronimo.war do-dist: dist: BUILD SUCCESSFUL (total time: 0 seconds)
Wdrożenie aplikacji webowej z usługą sieciową Katalog
Do wdrożenia aplikacji internetowej skorzystamy z polecenia deploy. Przechodzimy do katalogu domowego Geronimo i wydajemy polecenie ./bin/deploy.sh -u system -p manager deploy "C:\katalog-jaxws-geronimo\dist\katalog-jaxws-geronimo.war"
$ ./bin/deploy.sh -u system -p manager deploy "C:\katalog-jaxws-geronimo\dist\katalog-jaxws-geronimo.war"
Using GERONIMO_BASE: c:\geronimo
Using GERONIMO_HOME: c:\geronimo
Using GERONIMO_TMPDIR: c:\geronimo\var\temp
Using JRE_HOME: c:\apps\java5\jre
Deployed pl.jaceklaskowski.katalog/katalog-webservice/1.0/war @
/katalog
Podczas rozmieszczenia aplikacji na konsoli Geronimo pojawią się następujące komunikaty:
16:13:11,093 INFO [JAXWSServiceBuilder] Configuring JAX-WS Web Service: pl.jaceklaskowski.katalog.ws.KatalogWS at /katalog/Katalog
16:13:11,453 INFO [BusApplicationContext] Refreshing org.apache.cxf.bus.spring.BusApplicationContext@a92a55: display name
[org.apache.cxf.bus.spring.BusApplicationContext@a92a55]; startup date [Sun Nov 18 16:13:11 CET 2007]; root of context hierarchy
16:13:11,546 INFO [XmlBeanDefinitionReader] Loading XML bean definitions from class path resource [META-INF/cxf/cxf.xml]
16:13:12,031 INFO [XmlBeanDefinitionReader] Loading XML bean definitions from class path resource [META-INF/cxf/cxf-extension-geronimo.xml]
16:13:12,078 INFO [DefaultListableBeanFactory] Overriding bean definition for bean 'org.apache.cxf.resource.ResourceManager':
replacing [Root bean: class [org.apache.cxf.bus.resource.ResourceManagerImpl];
scope=singleton; abstract=false; lazyInit=false; autowireCandidate=true; autowireMode=0; dependencyCheck=0; factoryBeanName=null; factoryMethodName=null; initMethod
Name=null; destroyMethodName=null; defined in class path resource [META-INF/cxf/cxf.xml]]
with [Root bean: class [org.apache.geronimo.cxf.ResourceManager]; scope=singleton; abstract=false; lazyInit=false;
autowireCandidate=true; autowireMode=0; dependencyCheck=0; factoryBeanName=null; factoryMethodName=null; initMethodName=null;
destroyMethodName=null; defined in class path resource [META-INF/cxf/cxf-extension-geronimo.xml]]
16:13:12,078 INFO [XmlBeanDefinitionReader] Loading XML bean definitions from class path resource [META-INF/cxf/cxf-extension-soap.xml]
16:13:12,109 INFO [XmlBeanDefinitionReader] Loading XML bean definitions from class path resource [META-INF/cxf/cxf-extension-xml.xml]
16:13:12,171 INFO [XmlBeanDefinitionReader] Loading XML bean definitions from class path resource [META-INF/cxf/cxf-extension-http.xml]
16:13:12,203 INFO [BusApplicationContext] Bean factory for application context [org.apache.cxf.bus.spring.BusApplicationContext@a92a55]:
org.springframework.beans.factory.support.DefaultListableBeanFactory@87fa6d
16:13:12,328 INFO [BusApplicationContext] Bean 'org.apache.cxf.bus.spring.Jsr250BeanPostProcessor'
is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
16:13:12,328 INFO [BusApplicationContext] Bean 'org.apache.cxf.bus.spring.BusExtensionPostProcessor'
is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
16:13:12,328 INFO [DefaultListableBeanFactory] Pre-instantiating singletons in
org.springframework.beans.factory.support.DefaultListableBeanFactory@87fa6d: defining beans [...]; root of factory hierarchy
2007-11-18 16:13:13 org.apache.cxf.service.factory.ReflectionServiceFactoryBean buildServiceFromClass
INFO: Creating Service {http://ws.katalog.jaceklaskowski.pl/}Katalog from class pl.jaceklaskowski.katalog.ws.KatalogWS
2007-11-18 16:13:14 pl.jaceklaskowski.katalog.ws.KatalogWS init
INFO: Usluga sieciowa Katalog utworzona
Uwagę należy skupić na dwóch komunikatach. Pierwszy z nich wskazuje na adres naszej usługi sieciowej:
16:13:11,093 INFO [JAXWSServiceBuilder] Configuring JAX-WS Web Service: pl.jaceklaskowski.katalog.ws.KatalogWS at /katalog/Katalog
W tym przypadku będzie to http://localhost:8080/katalog/Katalog oraz komunikat po uruchomieniu metody zwrotnej @PostCreate.
INFO: Usluga sieciowa Katalog utworzona
Oba komunikaty gwarantują poprawne uruchomienie usługi sieciowej.
Wejście na adres usługi http://localhost:8080/katalog/Katalog spowoduje wyświetlenie następującego komunikatu:
Utworzenie klienta usługi sieciowej - Klient
Utworzenie projektu klienta - katalog-jaxws-geronimo-klient
Tworzymy projekt klienta wciskając Ctrl+Shift+N. Z okienka dialogowego New Project wybieramy Java > Java Application.
Wciskamy przycisk Next >.
W oknie dialogowym New Java Application wpisujemy następujące dane:
- Project Name: katalog-jaxws-geronimo-klient
- Create Main Class: pl.jaceklaskowski.katalog.Klient
Wciskamy przycisk Finish.
Utworzenie referencji usługi sieciowej
Wciskamy Ctrl+N i z okna dialogowego New File wybieramy Web Services > Web Service Client.
Wciskamy przycisk Next >.
Zaznaczamy opcję WSDL URL, gdzie wpisujemy adres pliku WSDL dla naszej usługi Katalog na Geronimo - http://localhost:8080/katalog/Katalog?wsdl. Z menu Package wybieramy pakiet pl.jaceklaskowski.katalog.
Zatwierdzamy przyciskiem Finish.
Poprawne wykonanie jest reprezentowane przez nowy węzeł w NetBeans - Web Service References.
Dzięki tej funkcjonalności możemy skorzystać z menu Web Service Client Resources > Call Web Service Operation... podczas edycji źródła klasy pl.jaceklaskowski.katalog.Klient. Więcej o tym w artykule Getting Started with JAX-WS Web Service Clients in NetBeans IDE 6.0 lub End-to-End Web Service Creation and Consumption in NetBeans IDE 6.0.
Klasa klienta usługi - pl.jaceklaskowski.katalog.Klient
Ostatecznie klasa klienta Klient powinna wyglądać następująco:
package pl.jaceklaskowski.katalog;
public class Klient {
public static void main(String[] args) {
try {
Katalog service = new Katalog();
KatalogWS port = service.getKatalogWSPort();
String nazwaKatalogu = "NazwaPewnegoKatalogu";
if (args.length > 0) {
nazwaKatalogu = args[0];
}
int result = port.iloscPozycji(nazwaKatalogu);
System.out.println("Wynik = " + result);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Uruchomienie klienta
Wykonanie klienta poprzez wciśnięcie F6 kończy się komunikatami:
init: deps-jar: wsimport-init: wsimport-client-check-Katalog: wsimport-client-Katalog: wsimport-client-generate: wsimport-client-compile: Compiling 1 source file to C:\katalog-jaxws-geronimo-klient\build\classes compile: run: Wynik = 20 BUILD SUCCESSFUL (total time: 2 seconds)
, gdzie linia Wynik = 20 jest poprawnym wykonaniem usługi.

