Úvod do Apache CXF

1. Prehľad

Apache CXF je plne kompatibilný rámec JAX-WS.

Okrem funkcií definovaných štandardmi JAX-WS poskytuje Apache CXF schopnosť konverzie medzi triedami WSDL a Java, API používané na manipuláciu s nespracovanými správami XML, podporu JAX-RS, integráciu s Spring Framework atď.

Tento tutoriál je prvý zo série o Apache CXF, ktorý predstavuje základné vlastnosti rámca. V zdrojovom kóde používa iba štandardné API JAX-WS, zatiaľ čo v zákulisí stále využíva výhody Apache CXF, ako sú napríklad automaticky generované metadáta WSDL a predvolená konfigurácia CXF.

2. Maven závislosti

Kľúčová závislosť potrebná na použitie Apache CXF je org.apache.cxf: cxf - rt - frontend -jaxws. Toto poskytuje implementáciu JAX-WS, ktorá nahradí vstavanú JDK:

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

Všimnite si, že tento artefakt obsahuje súbor s názvom javax.xml.ws.spi.Poskytovateľ vnútri META-INF / služby adresár. Java VM sa pozerá na prvý riadok tohto súboru, aby určilo implementáciu JAX-WS, ktorú má využiť. V takom prípade je obsah riadku org.apache.cxf.jaxws.spi.ProviderImpl, s odkazom na implementáciu, ktorú poskytuje Apache CXF.

V tomto výučbe nepoužívame na zverejnenie služby kontajner servletu, preto je na zaistenie potrebných definícií typov Java nutná iná závislosť:

 org.apache.cxf cxf-rt-transporty-http-mólo 3.1.6 

Najnovšie verzie týchto závislostí nájdete na serveri cxf-rt-frontend-jaxws a cxf-rt-transporty-http-mólo v centrálnom úložisku Maven.

3. Koncový bod webovej služby

Začnime s triedou implementácie použitou na konfiguráciu koncového bodu služby:

@WebService (endpointInterface = "com.baeldung.cxf.introduction.Baeldung") verejná trieda BaeldungImpl implementuje Baeldung {private Map students = new LinkedHashMap (); public String ahoj (názov reťazca) {návrat "Hello" + meno; } public String helloStudent (Student student) {students.put (students.size () + 1, student); návrat "Hello" + student.getName (); } verejná mapa getStudents () {návrat študenti; }}

Najdôležitejšou vecou, ​​ktorú si tu treba všimnúť, je prítomnosť endpointInterface atribút v @Webová služba anotácia. Tento atribút poukazuje na rozhranie definujúce abstraktnú zmluvu pre webovú službu.

Je potrebné implementovať všetky podpisy metód deklarované v rozhraní koncového bodu, implementácia rozhrania sa však nevyžaduje.

Tu BaeldungImpl trieda implementácie stále implementuje nasledujúce rozhranie koncového bodu, aby bolo zrejmé, že boli deklarované všetky deklarované metódy rozhrania, je to však voliteľné:

@WebService verejné rozhranie Baeldung {public String ahoj (názov reťazca); public String helloStudent (študent); @XmlJavaTypeAdapter (StudentMapAdapter.class) verejná mapa getStudents (); }

V predvolenom nastavení používa Apache CXF ako architektúru viazania údajov JAXB. Pretože však JAXB priamo nepodporuje viazanie a Mapa, ktorý sa vracia z getStudents metóda, potrebujeme adaptér na prevod Mapa do triedy Java, ktorú môže JAXB používať.

Okrem toho definujeme, aby sme oddelili zmluvné prvky od ich implementácie Študent ako rozhranie a JAXB tiež priamo nepodporuje rozhrania, preto potrebujeme ešte jeden adaptér, aby sme sa s tým vyrovnali. V skutočnosti môžeme pre pohodlie vyhlásiť Študent ako trieda. Použitie tohto typu ako rozhrania je iba jednou ďalšou ukážkou používania adaptačných tried.

Adaptéry sú demonštrované v nasledujúcej časti.

4. Vlastné adaptéry

Táto časť ilustruje spôsob použitia adaptačných tried na podporu väzby rozhrania Java a Mapa pomocou JAXB.

4.1. Adaptér rozhrania

Takto Študent rozhranie je definované:

@XmlJavaTypeAdapter (StudentAdapter.class) verejné rozhranie Student {public String getName (); }

Toto rozhranie deklaruje iba jednu metódu vracajúcu a String a upresňuje StudentAdapter ako adaptačná trieda na mapovanie do a z typu, ktorý dokáže použiť väzbu JAXB.

The StudentAdapter trieda je definovaná takto:

public class StudentAdapter extends XmlAdapter {public StudentImpl marshal (Student student) throws Exception {if (student instanceof StudentImpl) {return (StudentImpl) student; } vrátiť nový StudentImpl (student.getName ()); } public Unmarshal Student (StudentImpl student) hodí Exception {return student; }}

Trieda adaptácie musí implementovať XmlAdapter rozhranie a zabezpečiť implementáciu maršal a nemaršal metódy. The maršal metóda transformuje viazaný typ (Študent, rozhranie, ktoré JAXB nedokáže priamo spracovať) do typu hodnoty (StudentImpl, konkrétna trieda, ktorú môže spracovať JAXB). The nemaršal metóda robí veci naopak.

Tu je StudentImpl definícia triedy:

@XmlType (name = "Študent") verejná trieda StudentImpl implementuje Student {private String name; // konštruktory, getter a setter}

4.2. Mapa Adaptér

The getStudents metóda Baeldung rozhranie koncového bodu vráti a Mapa a označuje adaptačnú triedu na prevod súboru Mapa na typ, ktorý dokáže spracovať JAXB. Podobne ako v StudentAdapter triedy, túto adaptačnú triedu musí implementovať maršal a nemaršal metódy XmlAdapter rozhranie:

verejná trieda StudentMapAdapter rozširuje XmlAdapter {public StudentMap marshal (Map boundMap) throws Exception {StudentMap valueMap = new StudentMap (); pre (Map.Entry boundEntry: boundMap.entrySet ()) {StudentMap.StudentEntry valueEntry = nový StudentMap.StudentEntry (); valueEntry.setStudent (boundEntry.getValue ()); valueEntry.setId (boundEntry.getKey ()); valueMap.getEntries (). add (valueEntry); } return valueMap; } public Map unmarshal (StudentMap valueMap) vyvolá Výnimku {Map boundMap = new LinkedHashMap (); pre (StudentMap.StudentEntry studentEntry: valueMap.getEntries ()) {boundMap.put (studentEntry.getId (), studentEntry.getStudent ()); } návrat boundMap; }}

The StudentMapAdapter triedne mapy Mapa do az StudentMap typ hodnoty s nasledujúcou definíciou:

@XmlType (name = "StudentMap") verejná trieda StudentMap {položky súkromného zoznamu = nový ArrayList (); @XmlElement (nillable = false, name = "entry") verejný zoznam getEntries () {návratové položky; } @XmlType (name = "StudentEntry") verejná statická trieda StudentEntry {súkromné ​​celé číslo; súkromný študent; // zakladatelia a zakladatelia}}

5. Nasadenie

5.1. Server Definícia

Na nasadenie vyššie uvedenej webovej služby budeme využívať štandardné rozhrania JAX-WS API. Pretože používame Apache CXF, framework robí ešte nejaké práce navyše, napr. generovanie a zverejnenie schémy WSDL. Takto je definovaný server služieb:

public class Server {public static void main (String args []) hodí InterruptedException {implementátor BaeldungImpl = nový BaeldungImpl (); Reťazcová adresa = "// localhost: 8080 / baeldung"; Endpoint.publish (adresa, realizátor); Závit. Spánok (60 * 1000); System.exit (0); }}

Keď je server chvíľu aktívny, aby sa uľahčilo testovanie, mal by sa vypnúť, aby sa uvoľnili systémové prostriedky. Akékoľvek pracovné trvanie servera môžete určiť na základe svojich potrieb odovzdaním a dlho argument k Závit. Spánok metóda.

5.2. Nasadenie Server

V tomto výučbe používame org.codehaus.mojo: exec -maven-plugin plugin na vytvorenie inštancie vyššie znázorneného servera a na kontrolu jeho životného cyklu. Toto je deklarované v súbore Maven POM nasledovne:

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

The mainClass konfigurácia sa týka Server trieda, kde je zverejnený koncový bod webovej služby. Po spustení java Ako cieľ tohto doplnku môžeme skontrolovať schému WSDL automaticky generovanú serverom Apache CXF po prístupe na adresu URL // localhost: 8080 / baeldung? wsdl.

6. Testovacie prípady

Táto časť vás prevedie krokmi pri písaní testovacích prípadov použitých na overenie webovej služby, ktorú sme vytvorili predtým.

Upozorňujeme, že musíme vykonať exec: java cieľom je spustiť server webových služieb pred vykonaním akéhokoľvek testu.

6.1. Príprava

Prvým krokom je deklarácia niekoľkých polí pre testovaciu triedu:

verejná trieda StudentTest {private static QName SERVICE_NAME = nový QName ("// úvod.cxf.baeldung.com/", "Baeldung"); private static QName PORT_NAME = new QName ("// úvod.cxf.baeldung.com/", "BaeldungPort"); súkromná služba; súkromný Baeldung baeldungProxy; súkromný BaeldungImpl baeldungImpl; // ďalšie vyhlásenia}

Nasledujúci inicializačný blok sa používa na inicializáciu služby pole javax.xml.ws.Služba typ pred vykonaním akejkoľvek skúšky:

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

Po pridaní závislosti JUnit do súboru POM môžeme použiť @ Predtým anotácia ako v útržku kódu nižšie. Táto metóda sa spustí pred každým testom, aby sa znova vytvorila inštancia Baeldung polia:

@Before public void reinstantiateBaeldungInstances () {baeldungImpl = nový BaeldungImpl (); baeldungProxy = service.getPort (PORT_NAME, Baeldung.class); }

The baeldungProxy premenná je proxy pre koncový bod webovej služby, zatiaľ čo baeldungImpl je len jednoduchý objekt Java. Tento objekt sa používa na porovnanie výsledkov vyvolania metód vzdialeného koncového bodu prostredníctvom servera proxy s vyvolaním miestnych metód.

Všimnite si, že a QName inštancia je identifikovaná dvoma časťami: URI Namespace a lokálna časť. Ak PORT_NAME argument, QName typu, z Service.getPort metóda je vynechaná, Apache CXF bude predpokladať, že URI Namespace argumentu je názov balíka rozhrania koncového bodu v opačnom poradí a jeho lokálna časť je názov rozhrania pripojeného Prístav, čo je úplne rovnaká hodnota PORT_NAME. Preto v tomto návode môžeme tento argument vynechať.

6.2. Implementácia testu

Prvý testovací prípad, ktorý ilustrujeme v tejto podkapitole, je overenie odpovede vrátenej zo vzdialeného vyvolania protokolu Ahoj metóda v koncovom bode služby:

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

Je zrejmé, že metóda vzdialeného koncového bodu vracia rovnakú odpoveď ako lokálna metóda, čo znamená, že webová služba funguje podľa očakávania.

Nasledujúci testovací prípad demonštruje použitie ahojštudent metóda:

@Test public void whenUsingHelloStudentMethod_thenCorrect () {Student student = new StudentImpl ("John Doe"); Reťazec endpointResponse = baeldungProxy.helloStudent (študent); Reťazec localResponse = baeldungImpl.helloStudent (študent); assertEquals (localResponse, endpointResponse); }

V takom prípade klient predloží a Študent namietne proti koncovému bodu a na oplátku dostane správu obsahujúcu meno študenta. Rovnako ako v predchádzajúcom testovacom prípade sú odpovede zo vzdialeného aj miestneho vyvolania rovnaké.

Posledný testovací prípad, ktorý tu ukážeme, je komplikovanejší. Ako je definované v triede implementácie koncového bodu služby, zakaždým, keď klient vyvolá ahojštudent metóda pre koncový bod, predložená Študent objekt bude uložený v pamäti cache. Túto cache je možné získať zavolaním na getStudents metóda v koncovom bode. Nasledujúci testovací prípad potvrdzuje, že obsah študentov cache predstavuje to, čo klient poslal do webovej služby:

@Test public void usingGetStudentsMethod_thenCorrect () {Student student1 = new StudentImpl ("Adam"); baeldungProxy.helloStudent (student1); Študent student2 = new StudentImpl ("Eva"); baeldungProxy.helloStudent (student2); Mapovať študentov = baeldungProxy.getStudents (); assertEquals ("Adam", students.get (1) .getName ()); assertEquals ("Eva", students.get (2) .getName ()); }

7. Záver

Tento výukový program predstavil Apache CXF, výkonný rámec pre prácu s webovými službami v prostredí Java. Zamerala sa na aplikáciu rámca ako štandardnej implementácie JAX-WS, pričom sa ešte za behu využívali jeho špecifické schopnosti.

Implementáciu všetkých týchto príkladov a útržkov kódu nájdete v projekte GitHub.


$config[zx-auto] not found$config[zx-overlay] not found