8. Wersja 4 – architektura klient/serwer w ramach architektury usług internetowych
W tej nowej wersji aplikacja [Pam] będzie działać w trybie klient/serwer w architekturze usług internetowych. Przyjrzyjmy się ponownie architekturze poprzedniej aplikacji:
![]() |
Powyżej warstwa komunikacyjna [C, RMI, S] umożliwiała przejrzystą komunikację między klientem [ui] a warstwą zdalną [metier]. Zastosujemy podobną architekturę, w której warstwa komunikacyjna [C, RMI, S] zostanie zastąpiona warstwą [C, HTTP / SOAP, S]:
![]() |
Protokół HTTP / SOAP ma tę zaletę w porównaniu z poprzednim protokołem RMI / EJB, że jest wieloplatformowy. Dzięki temu usługa internetowa może być napisana w języku Java i wdrożona na serwerze Glassfish, podczas gdy klientem może być klient typu .NET lub PHP.
Opracujemy tę architekturę w trzech różnych trybach:
- serwis internetowy będzie obsługiwany przez EJB [Metier]
- usługa internetowa będzie świadczona przez aplikację internetową wykorzystującą EJB i [Metier]
- usługa internetowa będzie świadczona przez aplikację internetową wykorzystującą Spring
Usługę internetową można zaimplementować na różne sposoby na serwerze Java EE:
- za pomocą klasy opatrzonej adnotacją @WebService, która działa w kontenerze internetowym
![]() |
- poprzez obiekt EJB opatrzony adnotacją @WebService, który działa w kontenerze EJB
![]() |
Zaczniemy od tej ostatniej architektury.
8.1. Usługa internetowa zaimplementowana przez EJB
8.1.1. Część serwerowa
8.1.1.1. Projekt NetBeans
Zacznijmy od utworzenia nowego projektu Maven, będącego kopią projektu EJB [mv-pam-ejb-metier-dao-jpa-eclipselink]:
![]() |
O następującej architekturze:
![]() |
warstwa [metier] będzie usługą internetową, z którą łączy się warstwa [ui]. Ta klasa nie musi implementować żadnego interfejsu. To właśnie adnotacje przekształcają POJO (zwykły obiekt Java) w usługę internetową. Klasa [Metier], która implementuje powyższą warstwę [metier], jest przekształcana w następujący sposób:
package metier;
...
@WebService
@Stateless()
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class Metier implements IMetierLocal,IMetierRemote {
// odwołania do warstw [DAO]
@EJB
private ICotisationDaoLocal cotisationDao = null;
@EJB
private IEmployeDaoLocal employeDao=null;
@EJB
private IIndemniteDaoLocal indemniteDao=null;
// pobieranie listy płac
@WebMethod
public FeuilleSalaire calculerFeuilleSalaire(String SS,
...
}
// lista pracowników
@WebMethod
public List<Employe> findAllEmployes() {
...
}
// ważne – brak metod getter i setter dla EJB
}
- w wierszu 4 adnotacja @WebService sprawia, że klasa [Metier] staje się usługą internetową. Usługa internetowa udostępnia metody swoim klientom. Muszą one być opatrzone atrybutem @WebMethod.
- wiersze 19 i 25: obie metody klasy [Metier] stają się metodami serwisu internetowego.
- wiersz 29: ważne jest, aby usunąć metody getter i setter, w przeciwnym razie zostaną one udostępnione w usłudze internetowej, co spowoduje błędy bezpieczeństwa.
Dodanie tych adnotacji jest wykrywane przez NetBeans, który następnie zmienia charakter projektu:
![]() |
W [1] w projekcie pojawiła się struktura drzewa [Web Services]. Znajduje się w niej usługa internetowa Metier wraz z jej dwiema metodami. Aplikację serwerową można wdrożyć jako [2]. Serwer MySQL musi być uruchomiony, a jego baza danych [dbpam_eclipselink] musi istnieć i być wypełniona. Być może konieczne będzie wcześniej usunięcie plików [3] i EJB z projektu kliencko-serwerowego EJB, który był omawiany wcześniej, aby uniknąć konfliktów nazw. W rzeczywistości nasz nowy projekt zawiera te same elementy EJB, co poprzedni projekt.
![]() |
W [1] widzimy naszą aplikację serveur wdrożoną na serwerze Glassfish. Po wdrożeniu usługi internetowej można ją przetestować:
![]() |
- w pliku [1], w bieżącym projekcie, testujemy usługę internetową [Metier]
- usługa internetowa jest dostępna poprzez różne adresy URL. Adresy URL i [2] umożliwiają przetestowanie usługi internetowej
- w [3], a link w pliku XML definiuje usługę internetową. Klienci serwisu internetowego muszą znać identyfikator URL tego pliku. Na jego podstawie generowana jest warstwa kliencka (stuby) serwisu internetowego.
- w pliku [4,5] znajduje się formularz umożliwiający testowanie metod udostępnianych przez usługę internetową. Są one przedstawione wraz z parametrami, które użytkownik może zdefiniować.
Na przykład przetestujmy metodę [findAllEmployes], która nie wymaga żadnych parametrów:
![]() |
Powyżej testujemy tę metodę. Otrzymujemy wówczas poniższą odpowiedź (fragment). Znajdujemy w niej rzeczywiście obu pracowników wraz z ich dodatkami. Zachęcamy czytelnika do przetestowania w ten sam sposób metody [4], przekazując jej trzy wymagane parametry.

8.1.2. Strona kliencka
![]() |
8.1.2.1. Projekt NetBeans po stronie klienta console
Teraz tworzymy projekt Java typu [Java Application] dla części client aplikacji. Nie udało się (czerwiec 2012 r.) utworzyć projektu Maven dla tego klienta. Pojawia się błąd, który wydaje się być znany w sieci, ale pozostaje nierozwiązany.
![]() | ![]() |
Po utworzeniu projektu wskazujemy, że będzie on klientem serwisu internetowego, który właśnie wdrożyliśmy na serwerze Glassfish:
![]() |
- w [2] wybieramy nowy projekt i klikamy przycisk [New File]
- w [3] wskazujemy, że chcemy utworzyć klienta usługi internetowej
![]() |
- za pomocą [4], wskazujemy projekt NetBeans usługi internetowej
- w oknie [5] wyświetlona jest lista wszystkich projektów posiadających gałąź [Web Services], w tym przypadku jest to wyłącznie projekt [mv-pam-ws-metier-dao-eclipselink].
- Jeden projekt może wdrażać wiele usług internetowych. W [6] wybieramy usługę internetową, z którą chcemy się połączyć.
![]() |
- W [7] wyświetlana jest definicja usługi internetowej URL. Ta definicja URL jest wykorzystywana przez narzędzia programowe generujące warstwę kliencką, która będzie współpracować z usługą internetową.
![]() |
- Warstwa kliencka [C] [1], która zostanie wygenerowana, składa się z zestawu klas Java, które zostaną umieszczone w tym samym pakiecie. Nazwa tego pakietu jest ustalona na [8].
- Po zakończeniu pracy kreatora tworzenia klienta serwisu internetowego poprzez kliknięcie przycisku [Finish] tworzona jest powyższa warstwa [C].
Znajduje to odzwierciedlenie w szeregu zmian w projekcie:
- W powyższym [10] pojawia się drzewo [Generated Sources], które zawiera klasy warstwy [C], umożliwiające klientowi [3] komunikację z usługą internetową. Warstwa ta umożliwia klientowi [3] komunikację z warstwą [metier] i [4] tak, jakby była ona lokalna, a nie zdalna.
- W [11] pojawia się drzewo [Web Service References], które zawiera listę usług internetowych, dla których wygenerowano warstwę kliencką.
Należy zauważyć, że w wygenerowanej warstwie [C] [10] znajdują się klasy, które zostały wdrożone po stronie serwera: Indemnite, Cotisation, Employe, FeuilleSalaire, ElementsSalaire, Metier. Metier to usługa internetowa, a pozostałe klasy są klasami niezbędnymi dla tej usługi. Można z ciekawością zajrzeć do ich kodu. Zauważymy, że definicja klas, które po utworzeniu instancji reprezentują obiekty przetwarzane przez usługę, składa się z definicji pól klasy i ich metod dostępu, a także z dodania adnotacji umożliwiających serializację klasy do strumienia XML. Klasa Metier stała się interfejsem zawierającym dwie metody, które zostały opatrzone adnotacją @WebMethod. Każda z nich generuje dwie klasy, na przykład [CalculerFeuilleSalaire.java] i [CalculerFeuilleSalaireResponse.java], gdzie jedna hermetyzuje wywołanie metody, a druga jej wynik. Wreszcie klasa MetierService umożliwia klientowi uzyskanie odwołania do zdalnej usługi biznesowej:
Metoda getMetierPort w wierszu 2 pozwala uzyskać odwołanie do zdalnej usługi internetowej Metier.
8.1.2.2. Klient konsolowy serwisu internetowego Metier
Pozostaje nam tylko napisać klienta usługi internetowej Metier. Kopiujemy klasę [MainRemote] z projektu [mv-pam-client-metier-dao-jpa-eclipselink], który był klientem serwera EJB, do nowego projektu.
![]() |
- na [1], czyli klasę klienta serwisu internetowego. Klasa [MainRemote] zawiera błędy. Aby je skorygować, należy najpierw usunąć wszystkie istniejące instrukcje [import] z tej klasy, a następnie wygenerować je ponownie za pomocą opcji [Fix Imports]. W rzeczywistości niektóre klasy wykorzystywane przez klasę [MainRemote] należą teraz do wygenerowanego pakietu [client].
- W [3] fragment kodu, w którym instancjonowana jest warstwa [metier], to [3]. Odwołuje się ona do kodu JNDI w celu uzyskania odwołania do zdalnego obiektu EJB.
Modyfikujemy kod w następujący sposób:
- kod JNDI zostaje usunięty
- ponieważ klasa [PamException] nie istnieje po stronie klienta, usuwamy powiązany obiekt catch, aby zachować jedynie obiekt catch w klasie nadrzędnej [Exception].
![]() |
- w [4] pozostaje nam jeszcze uzyskać odwołanie do zdalnej usługi internetowej [Metier], aby móc wywołać jej metodę [calculerFeuilleSalaire].
- W [5] za pomocą myszki przeciągamy (drag) metodę [calculerFeuilleSalaire] z serwisu internetowego [Metier], aby ją upuścić (drop) w [4]. Wygenerowany zostaje kod [6]. Ten ogólny kod może być następnie dostosowany przez programistę.
![]() |
- w wierszu 112 widać, że [calculerFeuilleSalaire] jest metodą klasy [client.Metier] (wiersz 111). Teraz, gdy wiemy już, jak uzyskać warstwę [metier], poprzedni kod można przepisać w następujący sposób:
W wierszu 7 pobierane jest odwołanie do serwisu internetowego Metier. Po wykonaniu tej czynności kod klasy pozostaje bez zmian, z wyjątkiem wiersza 10, gdzie obsługiwany jest nie wyjątek typu [Exception], lecz bardziej ogólny typ Throwable, klasy nadrzędnej klasy Exception. W przypadku wystąpienia wyjątku wyświetlamy wszystkie jego przyczyny zagnieżdżone, aż do przyczyny pierwotnej.
Jesteśmy gotowi do testów:
- upewnić się, że uruchomiono SGBD i MySQL5, oraz że baza dbpam_eclipselink została utworzona i zainicjowana
- upewnić się, że usługa internetowa została wdrożona na serwerze Glassfish
- skompilować klienta (Clean and Build)
- skonfigurować uruchamianie klienta
![]() |
- uruchomić klienta
W konsoli pojawiają się następujące wyniki:
Przy następującej konfiguracji:

otrzymujemy następujące wyniki:
Należy zauważyć, że podczas gdy usługa internetowa [Metier] wysyła wyjątek typu [PamException], wyjątek odbierany przez klienta jest typu [SOAPFaultException]. Nawet w łańcuchu wyjątków nie pojawia się typ [PamException].
8.1.3. Klient Swing usługi internetowej Metier
Zadanie: przenieść klienta Swing z projektu [mv-pam-client-ejb-metier-dao-jpa-eclipselink] do nowego projektu, tak aby również on był klientem serwisu internetowego wdrożonego na serwerze Glassfish.
8.2. Usługa internetowa zaimplementowana przez aplikację internetową
Przechodzimy teraz do następującej architektury:
![]() |
Usługa internetowa jest obsługiwana przez aplikację internetową działającą w kontenerze internetowym serwera Glassfish. Usługa ta będzie opierać się na aplikacji EJB [Metier], która z kolei została wdrożona w kontenerze EJB3.
8.2.1. Część serwerowa
Tworzymy aplikację internetową:
![]() |
- w [1], tworzymy nowy projekt
- w [2]; ten projekt jest typu [Web Application]
- w [3] nadajemy mu nazwę [mv-pam-ws-ejb-metier-dao-eclipselink]
![]() |
- w [4] wybieramy wersję Java EE 6
- w [6] – utworzony projekt
Na poniższym schemacie utworzona aplikacja internetowa będzie działać w kontenerze internetowym. Będzie ona korzystać z EJB [Metier], który z kolei zostanie wdrożony w kontenerze EJB serwera.
![]() |
Aby utworzona aplikacja internetowa miała dostęp do klas powiązanych z EJB i [Metier], dodajemy do bibliotek aplikacji internetowej [mv-pam-ws-ejb-metier-dao-eclipselink], zależność od serwera EJB [mv-pam-ejb-metier-dao-eclipselink], który został już omówiony.
![]() |
- w [1] dodajemy projekt do zależności projektu internetowego,
- w [2] wybieramy projekt [mv-pam-ejb-metier-dao-eclipselink],
- w [3] typ zależności to ejb,
- w [4] zakres zależności to provided, co oznacza, że zostanie ona dostarczona przez środowisko uruchomieniowe,
- w [5] zależność została dodana.
Aby utworzyć tę samą usługę internetową, co poprzednio, musimy:
- utworzyć klasę oznaczoną tagiem @Webservice
- z dwiema metodami calculerFeuilleSalaire i findAllEmployes oznaczonymi tagiem @WebMethod
Tworzymy klasę [PamWsEjbMetier] w pakiecie [pam.ws]:
![]() |
![]() |
Klasa [PamWsEjbMetier] ma następującą postać:
- wiersze 7–10: klasa importuje klasy z modułów EJB i [pam-serveurws-metier-dao-jpa-eclipselink], których projekt Maven został dodany do zależności projektu.
- wiersz 12: klasa ta jest usługą internetową
- wiersz 13: implementuje ona interfejs IMetier zdefiniowany w module EJB
- wiersze 18–19: metoda calculerFeuilleSalaire jest udostępniona jako metoda serwisu internetowego
- wiersze 23–24: metoda findAllEmployes jest udostępniona jako metoda serwisu internetowego
- wiersze 15–16: lokalny interfejs EJB [Metier] jest wstawiany do pola w wierszu 16. Korzystamy z interfejsu lokalnego, ponieważ aplikacja internetowa i moduł EJB działają w tym samym JVM.
- wiersze 20 i 25: metody calculerFeuilleSalaire i findAllEmployes przekazują swoje przetwarzanie metodom o tej samej nazwie z klasy EJB [Metier]. Klasa ta służy zatem wyłącznie do udostępniania klientom zdalnym metod z klas EJB i [Metier] jako metod serwisu internetowego.
W NetBeans aplikacja internetowa jest rozpoznawana jako udostępniająca usługę internetową:
![]() |
Aby wdrożyć usługę internetową na serwerze GlassFish, musimy wdrożyć zarówno:
- moduł internetowy w kontenerze internetowym serwera
- moduł EJB w kontenerze EJB serwera
W tym celu musimy utworzyć aplikację typu [Enterprise Application], która wdroży oba moduły jednocześnie. Aby to zrobić, oba projekty muszą zostać załadowane do środowiska NetBeans [2].
Po wykonaniu tej czynności tworzymy nowy projekt o nazwie [3].
![]() |
- w [4] wybieramy projekt typu [Enterprise Application].
- w [5] nadajemy projektowi nazwę
![]() |
- w [6] konfigurujemy projekt. Wersja Javy dla EE to Java EE 6. Projekt korporacyjny można utworzyć z dwoma modułami: modułem EJB i modułem internetowym. W tym przypadku projekt korporacyjny będzie zawierał moduł internetowy oraz moduł EJB, które zostały już utworzone i załadowane do środowiska NetBeans. Nie wymagamy więc tworzenia nowych modułów.
- W [7] znajduje się utworzony w ten sposób projekt korporacyjny [mv-pam-webapp-ear]. Jednocześnie utworzono inny projekt Maven o nazwie [mv-pam-webapp]. Nie będziemy się nim zajmować.
- W projekcie [8] dodajemy zależności do projektu korporacyjnego
![]() |
- w projekcie [9] dodajemy projekt internetowy typu WAR,
- w [10] dodajemy projekt EJB typu ejb,
![]() |
- w pliku [11] dodajemy projekt korporacyjny wraz z jego dwiema zależnościami.
Kompilujemy projekt korporacyjny za pomocą polecenia „Clean and Build”. Jesteśmy już prawie gotowi do wdrożenia go na serwerze Glassfish. Wcześniej może być konieczne wyładowanie aplikacji już załadowanych na serwer, aby uniknąć ewentualnych konfliktów nazw EJB i [11]:
![]() |
Serwer MySQL musi być uruchomiony, a baza danych [dbpam_eclipselink] dostępna i wypełniona. Po wykonaniu tych czynności można wdrożyć aplikację korporacyjną [12]. W [13] widać, że została ona pomyślnie wdrożona na serwerze Glassfish.
Możemy przetestować właśnie wdrożoną usługę internetową:
![]() |
- w [1], prosimy o przetestowanie usługi internetowej [PamWsEjbMetier]
- na [2], czyli stronę testową. Przeprowadzenie testów pozostawiamy czytelnikowi.
8.2.2. Część kliencka
Zadanie: postępując zgodnie z procedurą opisaną w paragrafie 8.1.2.1, należy stworzyć klienta konsolowego dla powyższej usługi internetowej.
8.3. Usługa internetowa zaimplementowana przy użyciu Spring i Tomcat
Przechodzimy teraz do następującej architektury:
![]() |
Usługa internetowa jest realizowana przez aplikację internetową działającą w kontenerze internetowym serwera Tomcat. Architektura aplikacji będzie wyglądać następująco:
![]() |
Będziemy opierać się na projekcie [mv-pam-spring-hibernate] stworzonym w punkcie 5.11:
![]() |
8.3.1. Część serwerowa
Tworzymy aplikację internetową typu Maven o nazwie [mv-pam-ws-spring-tomcat] [1]:
![]() |
Modyfikujemy plik [pom.xml], dodając do niego następujące zależności [2]:
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mv-pam-spring-hibernate</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Apache CXF zależności -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<version>2.2.12</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<version>2.2.12</version>
</dependency>
</dependencies>
- wiersze 3–7: zależność od projektu [spring-pam-jpa-hibernate],
- wiersze 8–17: zależności od frameworka Apache CXF i [http://cxf.apache.org/]. Ułatwia on tworzenie usług internetowych.
Ten plik [pom.xml] wprowadza wiele zależności [2].
Wróćmy do architektury aplikacji:
![]() |
Wywołania serwisu internetowego, który zamierzamy zbudować, są obsługiwane przez serwlet z frameworka CXF. Znajduje to odzwierciedlenie w pliku [WEB-INF / web.xml] w następujący sposób:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>mv-pam-ws-spring-tomcat</display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Konfiguracja CXF -->
<servlet>
<servlet-name>CXFServlet</servlet-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>/ws/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
- Framework CXF jest zależny od Springa. Wiersze 4–6: zadeklarowano słuchacz. Odpowiednia klasa zostanie załadowana wraz z aplikacją internetową. Będzie ona korzystać z pliku konfiguracyjnego Springa [WEB-INF / applicationContext.xml]:
![]() |
- wiersze 8–12: serwlet CXF, który będzie obsługiwał wywołania do serwisu internetowego, który zamierzamy utworzyć,
- wiersze 13–16: żądania URL obsługiwane przez serwlet CXF będą miały postać /ws/*. Pozostałe nie będą obsługiwane przez CXF.
Aby zdefiniować serwis internetowy, definiujemy interfejs i jego implementację:
![]() |
Interfejs [IWsMetier] będzie wyglądał następująco:
package pam.ws;
import javax.jws.WebService;
import metier.IMetier;
@WebService
public interface IWsMetier extends IMetier{
}
- wiersz 7: interfejs [IWsMetier] wywodzi się z interfejsu [IMetier] z warstwy [métier] projektu [mv-pam-spring-hibernate],
- wiersz 6: interfejs [IWsMetier] jest interfejsem usługi internetowej.
Klasa implementująca ten interfejs to:
package pam.ws;
import java.util.List;
import javax.jws.WebMethod;
import javax.jws.WebService;
import jpa.Employe;
import metier.FeuilleSalaire;
import metier.IMetier;
@WebService
public class PamWsMetier implements IWsMetier {
// warstwa biznesowa
private IMetier metier;
// konstruktor
public PamWsMetier(){
}
@WebMethod
public FeuilleSalaire calculerFeuilleSalaire(String SS, double nbHeuresTravaillees, int nbJoursTravailles) {
return metier.calculerFeuilleSalaire(SS, nbHeuresTravaillees, nbJoursTravailles);
}
@WebMethod
public List<Employe> findAllEmployes() {
return metier.findAllEmployes();
}
// metody pobierające i ustawiające
public void setMetier(IMetier metier) {
this.metier = metier;
}
}
- wiersz 11: klasa [PamWsMetier] implementuje wcześniej zdefiniowany interfejs,
- wiersz 10: definiuje klasę jako usługę internetową,
- wiersz 14: warstwa [métier] zostanie wstrzyknięta przez Spring,
- wiersze 21, 26: adnotacja @WebMethod sprawia, że metoda staje się metodą udostępnianą przez usługę internetową,
- wiersze 23, 28: metody są zaimplementowane przy użyciu warstwy [métier].
Pozostaje nam zdefiniować zawartość pliku konfiguracyjnego Springa [applicationContext.xml]:
![]() |
Jego zawartość jest następująca:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<!-- Apache CXF -->
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<!-- warstwy dolne -->
<import resource="classpath:spring-config-metier-dao.xml" />
<!-- usługa internetowa -->
<bean id="wsMetier" class="pam.ws.PamWsMetier">
<property name="metier" ref="metier"/>
</bean>
<jaxws:endpoint id="wsmetier"
implementor="#wsMetier"
address="/metier">
</jaxws:endpoint>
</beans>
- wiersze 13–15: importujemy pliki konfiguracyjne Apache’a CXF. Są one wyszukiwane w pliku Classpath projektu (atrybut classpath:),
- wiersze 4, 9, 10: deklarowane są przestrzenie nazw specyficzne dla Apache'a CXF,
- wiersz 18: importowany jest plik konfiguracyjny Spring z projektu [mv-pam-spring-hibernate],
- wiersze 21–23: definiują bean serwisu internetowego wraz z jego zależnością od warstwy [métier] (wiersz 22),
- wiersze 24–27: definiują sam serwis internetowy,
- wiersz 25: bean Spring implementujący usługę internetową to ten zdefiniowany w wierszu 21;
- wiersz 26: definiuje ścieżkę URL, pod którą usługa internetowa będzie dostępna, w tym przypadku /metier. W połączeniu z formatem, jaki muszą mieć adresy URL przetwarzane przez serwer Apache CXF (patrz plik web.xml), ten adres URL zmienia się na /ws/metier.
Nasz projekt jest gotowy do uruchomienia. Uruchamiamy go (Run) i wywołujemy adres URL [http://localhost:8080/mv-pam-ws-spring-tomcat/ws] w przeglądarce:

Strona zawiera listę wszystkich wdrożonych usług internetowych. W tym przypadku jest tylko jedna. Klikamy link WSDL:
![]() |
Wyświetlony tekst [1] pochodzi z pliku XML, który określa funkcjonalność usługi internetowej, sposób jej wywołania oraz rodzaje wysyłanych odpowiedzi. Warto zwrócić uwagę na identyfikatory URL, [2] oraz WSDL zawarte w tym pliku. Wszyscy klienci serwisu internetowego muszą je znać.
8.3.2. Część kliencka
Zadanie: postępując zgodnie z procedurą opisaną w paragrafie 8.1.2.1, należy stworzyć klienta konsolowego dla powyższej usługi internetowej.
Uwaga: aby wskazać identyfikator URL pliku WSDL usługi internetowej, należy postępować w następujący sposób:
![]() |
W polu [3] należy wpisać wartość URL, zapisaną wcześniej w polu [2].












































