Uvod u Apache CXF

1. Pregled

Apache CXF je JAX-WS potpuno sukladan okvir.

Pored značajki definiranih JAX-WS standardima, Apache CXF pruža mogućnost pretvorbe između WSDL i Java klasa, API-je koji se koriste za manipulaciju sirovim XML porukama, podršku za JAX-RS, integraciju s Spring Frameworkom itd.

Ovaj je vodič prvi iz serije o Apache CXF-u, koji uvodi osnovne karakteristike okvira. U izvornom kodu koristi samo JAX-WS standardne API-je, dok još uvijek koristi prednosti Apache CXF-a iza kulisa, poput automatski generiranih WSDL metapodataka i zadane konfiguracije CXF-a.

2. Ovisnosti Mavena

Ključna ovisnost potrebna za upotrebu Apache CXF je org.apache.cxf: cxf - rt - frontend -jaxws. Ovo pruža JAX-WS implementaciju koja zamjenjuje ugrađenu JDK:

 org.apache.cxf cxf-rt-frontend-jaxws 3.1.6 

Primijetite da ovaj artefakt sadrži datoteku s imenom javax.xml.ws.spi.Provider unutar META-INF / usluge imenik. Java VM pregledava prvi redak ove datoteke kako bi odredio implementaciju JAX-WS koju će koristiti. U ovom slučaju, sadržaj retka je org.apache.cxf.jaxws.spi.ProviderImpl, pozivajući se na implementaciju koju nudi Apache CXF.

U ovom uputstvu ne koristimo spremnik servleta za objavljivanje usluge, stoga je potrebna druga ovisnost kako bismo pružili potrebne definicije Java tipa:

 org.apache.cxf cxf-rt-transports-http-jetty 3.1.6 

Pogledajte najnovije verzije ovih ovisnosti cxf-rt-frontend-jaxws i cxf-rt-transports-http-jetty u središnjem spremištu Maven.

3. Krajnja točka web usluge

Krenimo od klase implementacije koja se koristi za konfiguriranje krajnje točke usluge:

@WebService (endpointInterface = "com.baeldung.cxf.introduction.Baeldung") javna klasa BaeldungImpl implementira Baeldung {private map students = new LinkedHashMap (); javni String pozdrav (naziv niza) {return "Hello" + ime; } javni String helloStudent (student student) {students.put (students.size () + 1, student); return "Hello" + student.getName (); } javna karta getStudents () {povratak učenika; }}

Najvažnija stvar koju ovdje treba primijetiti je prisutnost krajnja točkaInterface atribut u @WebService bilješka. Ovaj atribut ukazuje na sučelje koje definira apstraktni ugovor za web uslugu.

Sve potpise metode deklarirane u sučelju krajnje točke treba implementirati, ali nije potrebno implementirati sučelje.

Ovdje BaeldungImpl klasa implementacije još uvijek implementira sljedeće sučelje krajnje točke kako bi bilo jasno da su sve deklarirane metode sučelja implementirane, ali to nije obavezno:

@WebService javno sučelje Baeldung {javni String pozdrav (naziv niza); javni String helloStudent (student student); @XmlJavaTypeAdapter (StudentMapAdapter.class) javna karta getStudents (); }

Prema zadanim postavkama Apache CXF koristi JAXB kao svoju arhitekturu vezivanja podataka. Međutim, budući da JAXB ne podržava izravno vezanje a Karta, koji se vraća iz getStudents metoda, potreban nam je adapter za pretvorbu Karta na Java klasu koju JAXB može koristiti.

Pored toga, kako bismo odvojili elemente ugovora od njihove provedbe, definiramo Student kao sučelje, a JAXB također ne podržava izravno sučelja, pa nam je potreban još jedan adapter da bismo to riješili. Zapravo, radi praktičnosti, možemo izjaviti Student kao razred. Korištenje ove vrste kao sučelja samo je još jedna demonstracija korištenja klasa prilagodbe.

Ispravljači su prikazani u odjeljku odmah ispod.

4. Prilagođeni adapteri

Ovaj odjeljak ilustrira način korištenja klasa prilagodbe za podršku vezivanja Java sučelja i a Karta koristeći JAXB.

4.1. Adapter za sučelje

Ovo je način na koji Student sučelje je definirano:

@XmlJavaTypeAdapter (StudentAdapter.class) javno sučelje Student {public String getName (); }

Ovo sučelje deklarira samo jednu metodu koja vraća a Niz i precizira StudentAdapter kao klasa prilagodbe kako bi se preslikala na i iz tipa koji može primijeniti JAXB vezivanje.

The StudentAdapter razred definiran je kako slijedi:

javna klasa StudentAdapter proširuje XmlAdapter {javni studentImpl maršal (student student) baca iznimku {if (student instanceof StudentImpl) {return (StudentImpl) student; } vrati novi StudentImpl (student.getName ()); } javni student Unmarshal (StudentImpl student) baca iznimku {return student; }}

Klasa prilagodbe mora implementirati XmlAdapter sučelje i osigurati implementaciju za maršal i nemaršal metode. The maršal metoda pretvara vezani tip (Student, sučelje koje JAXB ne može izravno obraditi) u vrstu vrijednosti (StudentImpl, klasa betona koju JAXB može obraditi). The nemaršal metoda radi stvari obrnuto.

Ovdje je StudentImpl definicija razreda:

@XmlType (name = "Student") javna klasa StudentImpl implementira Student {private String name; // konstruktori, getter i setter}

4.2. Karta Adapter

The getStudents metoda Baeldung sučelje krajnje točke vraća a Karta i označava klasu prilagodbe za pretvorbu datoteke Karta na tip s kojim može rukovati JAXB. Slično kao StudentAdapter klase, ovaj razred prilagodbe mora implementirati maršal i nemaršal metode XmlAdapter sučelje:

javna klasa StudentMapAdapter proširuje XmlAdapter {javni studentMap maršal (Map boundMap) baca izuzetak {StudentMap valueMap = new StudentMap (); za (Map.Entry boundEntry: boundMap.entrySet ()) {StudentMap.StudentEntry valueEntry = novi StudentMap.StudentEntry (); valueEntry.setStudent (boundEntry.getValue ()); valueEntry.setId (boundEntry.getKey ()); valueMap.getEntries (). add (valueEntry); } return valueMap; } javna karta unmarshal (StudentMap valueMap) baca izuzetak {Map boundMap = new LinkedHashMap (); za (StudentMap.StudentEntry studentEntry: valueMap.getEntries ()) {boundMap.put (studentEntry.getId (), studentEntry.getStudent ()); } return boundMap; }}

The StudentMapAdapter zemljovidi razreda Karta do i od Studentska karta vrsta vrijednosti s definicijom kako slijedi:

@XmlType (name = "StudentMap") javna klasa StudentMap {privatni unosi na popisu = novi ArrayList (); @XmlElement (nillable = false, name = "entry") javni popis getEntries () {return entries; } @XmlType (name = "StudentEntry") javna statička klasa StudentEntry {private Integer id; privatni student Student; // geteri i postavljači}}

5. Raspoređivanje

5.1. Poslužitelj Definicija

Da bismo implementirali gore spomenutu web uslugu, poslužit ćemo se standardnim API-jem JAX-WS. Budući da koristimo Apache CXF, okvir čini neki dodatni posao, npr. generiranje i objavljivanje WSDL sheme. Evo kako je definiran poslužitelj usluge:

javna klasa poslužitelj {javna statička void glavna (String args []) baca InterruptedException {BaeldungImpl implementator = novi BaeldungImpl (); Adresa niza = "// localhost: 8080 / baeldung"; Krajnja točka.publish (adresa, implementator); Navoj.spavanje (60 * 1000); System.exit (0); }}

Nakon što je poslužitelj neko vrijeme aktivan radi olakšavanja testiranja, treba ga isključiti da bi se oslobodili sistemski resursi. Možete navesti bilo koje trajanje rada za poslužitelj na temelju vaših potreba dodavanjem a dugo argument za Konac.spavati metoda.

5.2. Uvođenje sustava Poslužitelj

U ovom uputstvu koristimo org.codehaus.mojo: exec -maven-plugin dodatak za instanciju poslužitelja prikazanog gore i kontrolu njegovog životnog ciklusa. To je deklarirano u Maven POM datoteci kako slijedi:

 org.codehaus.mojo exec-maven-plugin com.baeldung.cxf.introduction.Server 

The mainClass Konfiguracija se odnosi na Poslužitelj klasa u kojoj je objavljena krajnja točka web usluge. Nakon pokretanja Java Cilj ovog dodatka možemo provjeriti WSDL shemu koju automatski generira Apache CXF pristupanjem URL-u // localhost: 8080 / baeldung? wsdl.

6. Ispitni slučajevi

Ovaj odjeljak vodi vas kroz korake za pisanje testnih slučajeva koji se koriste za provjeru web usluge koju smo prije stvorili.

Napominjemo da moramo izvršiti exec: java cilj pokrenuti poslužitelj web usluga prije pokretanja bilo kojeg testa.

6.1. Priprema

Prvi korak je deklariranje nekoliko polja za testnu klasu:

javna klasa StudentTest {private static QName SERVICE_NAME = new QName ("// uvod.cxf.baeldung.com/", "Baeldung"); privatni statički QName PORT_NAME = novo QName ("// uvod.cxf.baeldung.com/", "BaeldungPort"); usluga privatne usluge; privatni Baeldung baeldungProxy; privatno BaeldungImpl baeldungImpl; // ostale deklaracije}

Sljedeći blok inicijalizatora koristi se za pokretanje datoteke servis polje javax.xml.ws.Service upišite prije pokretanja bilo kojeg testa:

{service = Service.create (SERVICE_NAME); String endpointAddress = "// localhost: 8080 / baeldung"; service.addPort (PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress); }

Nakon dodavanja ovisnosti JUnit u POM datoteku, možemo koristiti @Prije napomena kao u donjem isječku koda. Ova se metoda izvodi prije svakog testa za ponovnu instancu Baeldung polja:

@Prije javne praznine reinstantiateBaeldungInstance () {baeldungImpl = novo BaeldungImpl (); baeldungProxy = service.getPort (PORT_NAME, Baeldung.class); }

The baeldungProxy varijabla je proxy za krajnju točku web usluge, dok baeldungImpl je samo jednostavan Java objekt. Ovaj se objekt koristi za usporedbu rezultata pozivanja metoda udaljene krajnje točke kroz proxy s pozivima lokalnih metoda.

Imajte na umu da a QName instanca se prepoznaje iz dva dijela: URI prostora prostora i lokalni dio. Ako je PORT_NAME argument, QName vrsta, od Usluga.getPort metoda izostavljena, Apache CXF će pretpostaviti da je URI prostora prostora argumenata naziv paketa sučelja krajnje točke obrnutim redoslijedom, a njegov lokalni dio naziv sučelja dodan s Luka, što je potpuno ista vrijednost od PORT_NAME. Stoga u ovom uputstvu ovaj argument možemo izostaviti.

6.2. Provedba testa

Prvi testni slučaj koji ilustriramo u ovom pododjeljku je provjera valjanosti odgovora vraćenog iz udaljenog poziva na zdravo metoda na krajnjoj točki usluge:

@Test public void whenUsingHelloMethod_thenCorrect () {String endpointResponse = baeldungProxy.hello ("Baeldung"); Niz localResponse = baeldungImpl.hello ("Baeldung"); assertEquals (localResponse, endpointResponse); }

Jasno je da metoda udaljene krajnje točke vraća isti odgovor kao i lokalna metoda, što znači da web usluga radi kako se očekivalo.

Sljedeći test pokazuje primjenu zdravoStudentu metoda:

@Test public void whenUsingHelloStudentMethod_thenCorrect () {Student student = new StudentImpl ("John Doe"); String endpointResponse = baeldungProxy.helloStudent (student); Niz localResponse = baeldungImpl.helloStudent (student); assertEquals (localResponse, endpointResponse); }

U ovom slučaju, klijent predaje a Student usprotivi se krajnjoj točki i zauzvrat primi poruku koja sadrži ime učenika. Kao i prethodni testni slučaj, i odgovori s udaljenih i lokalnih poziva isti su.

Posljednji test koji smo ovdje prikazali je složeniji. Kako je definirano klasom implementacije krajnje točke usluge, svaki put kada klijent pozove zdravoStudentu metoda na krajnjoj točki, poslani Student objekt će biti pohranjen u predmemoriju. Ova se predmemorija može dohvatiti pozivom getStudents metoda na krajnjoj točki. Sljedeći testni slučaj potvrđuje taj sadržaj studenti predmemorija predstavlja ono što je klijent poslao web usluzi:

@Test public void usingGetStudentsMethod_thenCorrect () {Student student1 = new StudentImpl ("Adam"); baeldungProxy.helloStudent (student1); Student student2 = new StudentImpl ("Eve"); baeldungProxy.helloStudent (student2); Mapa učenika = baeldungProxy.getStudents (); assertEquals ("Adam", students.get (1) .getName ()); assertEquals ("Eve", students.get (2) .getName ()); }

7. Zaključak

Ovaj je vodič predstavio Apache CXF, moćan okvir za rad s web uslugama u Javi. Fokusirao se na primjenu okvira kao standardne implementacije JAX-WS, dok je i dalje koristio specifične mogućnosti okvira u vrijeme izvođenja.

Implementacija svih ovih primjera i isječaka koda može se naći u projektu GitHub.