Bevezetés az Apache CXF-be

1. Áttekintés

Az Apache CXF egy JAX-WS teljesen kompatibilis keretrendszer.

A JAX-WS szabványok által meghatározott szolgáltatások mellett az Apache CXF biztosítja a konverzió képességét a WSDL és a Java osztályok között, a nyers XML üzenetek manipulálására használt API-kat, a JAX-RS támogatását, az integrációt a Spring Framework-szel stb.

Ez az oktatóanyag az Apache CXF-ről szóló sorozat első része, amely bemutatja a keret alapvető jellemzőit. Csak a JAX-WS szabványos API-kat használja a forráskódban, miközben továbbra is kihasználja az Apache CXF előnyeit a kulisszák mögött, például az automatikusan létrehozott WSDL metaadatokat és a CXF alapértelmezett konfigurációját.

2. Maven-függőségek

Az Apache CXF használatához szükséges kulcsfüggőség az org.apache.cxf: cxf - rt - frontend -jaxws. Ez egy JAX-WS megvalósítást biztosít a beépített JDK kiváltására:

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

Figyelje meg, hogy ez a tárgy tartalmaz egy nevű fájlt javax.xml.ws.spi.Provider benne META-INF / szolgáltatások Könyvtár. A Java virtuális gép ennek a fájlnak az első sorát vizsgálja meg a JAX-WS megvalósításának meghatározásához. Ebben az esetben a sor tartalma org.apache.cxf.jaxws.spi.ProviderImpl, hivatkozva az Apache CXF által biztosított megvalósításra.

Ebben az oktatóanyagban nem használunk servlet-tárolót a szolgáltatás közzétételéhez, ezért egy másik függőség szükséges a szükséges Java-típusú definíciók megadásához:

 org.apache.cxf cxf-rt-transports-http-móló 3.1.6 

Kérjük, nézze meg ezen függőségek legújabb verzióit cxf-rt-frontend-jaxws és cxf-rt-transport-http-móló a Maven központi adattárában.

3. Webszolgáltatás végpont

Kezdjük a szolgáltatás végpontjának konfigurálásához használt implementációs osztállyal:

@WebService (endpointInterface = "com.baeldung.cxf.introduction.Baeldung") nyilvános osztály BaeldungImpl valósítja meg Baeldung {privát térképes hallgatók = új LinkedHashMap (); public String hello (String name) {return "Hello" + név; } public String helloStudent (Student student) {students.put (students.size () + 1, student); return "Hello" + student.getName (); } nyilvános térkép getStudents () {visszatérő diákok; }}

A legfontosabb, amit itt észre kell venni, a endpointInterface attribútum a @Webes szolgáltatás annotáció. Ez az attribútum a webszolgáltatás elvont szerződését meghatározó felületre mutat.

A végpont interfészen deklarált összes metódus-aláírást végre kell hajtani, de az interfész megvalósításához nem szükséges.

Itt a BaeldungImpl implementációs osztály még mindig a következő végpont interfészt valósítja meg annak egyértelművé tétele érdekében, hogy az interfész összes deklarált metódusa megvalósult, de ez nem kötelező:

@WebService nyilvános felület Baeldung {public String hello (String name); public String helloStudent (hallgató hallgató); @XmlJavaTypeAdapter (StudentMapAdapter.class) public Map getStudents (); }

Alapértelmezés szerint az Apache CXF a JAXB-t használja adatmegkötési architektúraként. Mivel azonban a JAXB nem támogatja közvetlenül a Térkép, amelyet a getStudents módszer, adapterre van szükségünk a Térkép Java osztályba, amelyet a JAXB használhat.

Ezenkívül annak érdekében, hogy a szerződéses elemeket el lehessen különíteni azok végrehajtásától, meghatározzuk Diák interfészként, és a JAXB sem támogatja közvetlenül az interfészeket, ezért ehhez még egy adapterre van szükségünk. Valójában a kényelem kedvéért kijelenthetjük Diák mint osztály. Ennek a típusnak az interfészként való használata csak még egy bemutatója az adaptációs osztályok használatának.

Az adaptereket az alábbi szakasz mutatja be.

4. Egyedi adapterek

Ez a szakasz bemutatja az adaptációs osztályok használatának módját a Java felület és a Térkép a JAXB használatával.

4.1. Interfész adapter

Így történt a Diák interfész van meghatározva:

@XmlJavaTypeAdapter (StudentAdapter.class) nyilvános felület Student {public String getName (); }

Ez az interfész csak egy metódust deklarál, amellyel a Húr és meghatározza StudentAdapter adaptációs osztályként, hogy feltérképezze magát egy olyan típusba, amely alkalmazhatja a JAXB kötést.

A StudentAdapter osztály meghatározása a következőképpen történik:

public class StudentAdapter kiterjeszti az XmlAdaptert {public StudentImpl marsall (Student hallgató) kivételt dob ​​{if if (student instanceof StudentImpl) {return (StudentImpl) hallgató; } return new StudentImpl (student.getName ()); } public Student unmarshal (StudentImpl hallgató) dobja a Kivételt {visszatérő hallgató; }}

Egy adaptációs osztálynak kell megvalósítania a XmlAdapter interfész és megvalósítás biztosítása a marsall és unmarshal mód. A marsall metódus átalakítja a kötött típust (Diák, egy olyan interfész, amelyet a JAXB nem tud közvetlenül kezelni) egy értéktípusba (StudentImpl, a JAXB által feldolgozható betonosztály). A unmarshal módszer fordítva csinálja a dolgokat.

Itt van StudentImpl osztály meghatározása:

@XmlType (name = "Student") nyilvános osztály A StudentImpl végrehajtja a Student {private String name; // konstruktorok, getter és setter}

4.2. Térkép Adapter

A getStudents a metódusa Baeldung végpont interfész visszaadja a Térkép és egy adaptációs osztályt jelöl a konvertáláshoz Térkép a JAXB által kezelhető típusra. Hasonló a StudentAdapter osztály, ennek az adaptációs osztálynak végre kell hajtania marsall és unmarshal módszerei XmlAdapter felület:

a public class StudentMapAdapter kiterjeszti az XmlAdaptert {public StudentMap marsall (Map boundMap) dobja a Kivételt {StudentMap valueMap = new StudentMap (); for (Map.Entry boundEntry: boundMap.entrySet ()) {StudentMap.StudentEntry valueEntry = új StudentMap.StudentEntry (); valueEntry.setStudent (boundEntry.getValue ()); valueEntry.setId (boundEntry.getKey ()); valueMap.getEntries (). add (valueEntry); } return valueMap; } public Map unmarshal (StudentMap valueMap) dobja a Kivételt {Map boundMap = new LinkedHashMap (); for (StudentMap.StudentEntry studentEntry: valueMap.getEntries ()) {kötöttMap.put (studentEntry.getId (), studentEntry.getStudent ()); } return boundMap; }}

A StudentMapAdapter osztálytérképeket Térkép és vissza a StudentMap értéktípus a következő definícióval:

@XmlType (név = "StudentMap") nyilvános osztály StudentMap {privát lista bejegyzések = új ArrayList (); @XmlElement (nillable = false, name = "entry") public list getEntries () {visszatérési bejegyzések; } @XmlType (name = "StudentEntry") public static class StudentEntry {private Integer id; magántanuló hallgató; // szerelők és beállítók}}

5. Telepítés

5.1. szerver Meghatározás

A fent tárgyalt webszolgáltatás telepítéséhez a szokásos JAX-WS API-kat fogjuk használni. Mivel Apache CXF-et használunk, a keretrendszer extra munkát végez, pl. a WSDL séma generálása és közzététele. A szolgáltatáskiszolgáló meghatározása:

public class Server {public static void main (String args []) dobja az InterruptedException {BaeldungImpl implementátor = új BaeldungImpl (); Karakterlánc címe = "// localhost: 8080 / baeldung"; Endpoint.publish (cím, megvalósító); Szál.alszik (60 * 1000); System.exit (0); }}

Miután a kiszolgáló egy ideig aktív a tesztelés megkönnyítése érdekében, le kell állítani a rendszer erőforrásainak felszabadítása érdekében. Megadhatja a szerver bármely munkaidejét az Ön igényei alapján az a átadásával hosszú érv a Szál.alszik módszer.

5.2. A szerver

Ebben az oktatóanyagban a org.codehaus.mojo: exec -maven-plugin plugin a fent bemutatott szerver példányosításához és életciklusának ellenőrzéséhez. Ezt a Maven POM fájl a következőképpen deklarálja:

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

A mainClass konfiguráció a szerver osztály, ahol a webszolgáltatás végpont közzétételre kerül. Miután a Jáva A plugin célja az URL elérésével ellenőrizheti az Apache CXF által automatikusan létrehozott WSDL sémát // localhost: 8080 / baeldung? wsdl.

6. Tesztesetek

Ez a szakasz végigvezeti a korábban létrehozott webszolgáltatás ellenőrzéséhez használt tesztesetek megírásának lépésein.

Felhívjuk figyelmét, hogy végre kell hajtanunk a exec: java A webszerver indítása a teszt futtatása előtt.

6.1. Készítmény

Az első lépés a tesztosztály több mezőjének deklarálása:

public class StudentTest {private static QName SERVICE_NAME = new QName ("// bevezetés.cxf.baeldung.com/", "Baeldung"); privát statikus QName PORT_NAME = új QName ("// bevezetés.cxf.baeldung.com/", "BaeldungPort"); magánszolgáltatás; magán Baeldung baeldungProxy; magán BaeldungImpl baeldungImpl; // egyéb nyilatkozatok}

A következő inicializáló blokkot használjuk a szolgáltatás mező javax.xml.ws.Service a teszt futtatása előtt írja be:

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

Miután hozzáadta a JUnit-függőséget a POM fájlhoz, használhatjuk a @Előtt kommentár, mint az alábbi kódrészletben. Ez a módszer minden teszt előtt fut, hogy újra példázza Baeldung mezők:

@ Mielőtt a public void helyreállna BaaungungInstances () {baeldungImpl = new BaeldungImpl (); baeldungProxy = service.getPort (PORT_NAME, Baeldung.class); }

A baeldungProxy változó a webszolgáltatás végpont proxyja, míg a baeldungImpl csak egy egyszerű Java objektum. Ezt az objektumot a távoli végpont-módszerek proxyn keresztüli meghívásának eredményeinek összehasonlítására használják a helyi módszerek invokációival.

Vegye figyelembe, hogy a QName a példányt két rész azonosítja: egy névtér URI és egy helyi rész. Ha a PORT_NAME érv, a QName típusú, a Service.getPort metódus kihagyásra kerül, az Apache CXF feltételezi, hogy az argumentum Névtér URI-je a végpont interfész csomagneve fordított sorrendben, helyi része pedig a csatolt felület neve Kikötő, amely pontosan ugyanaz az értéke PORT_NAME. Ezért ebben az oktatóanyagban ezt az érvet elhagyhatjuk.

6.2. Teszt végrehajtása

Az első teszteset, amelyet ebben az alfejezetben szemléltetünk, a. Távoli meghívásából kapott válasz validálása Helló módszer a szolgáltatás végpontján:

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

Nyilvánvaló, hogy a távoli végpont módszer ugyanazt a választ adja vissza, mint a helyi módszer, vagyis a webszolgáltatás a várakozásoknak megfelelően működik.

A következő teszteset a helloStudent módszer:

@Test public void whenUsingHelloStudentMethod_thenCorrect () {Student student = new StudentImpl ("John Doe"); Karakterlánc végpontResponse = baeldungProxy.helloStudent (hallgató); String localResponse = baeldungImpl.helloStudent (hallgató); assertEquals (localResponse, endpointResponse); }

Ebben az esetben az ügyfél benyújtja a Diák kifogásolja a végpontot, és cserébe üzenetet kap a hallgató nevéről. Az előző tesztesethez hasonlóan a távoli és a helyi invokációk válaszai is megegyeznek.

Az utolsó teszteset, amelyet itt bemutatunk, bonyolultabb. A szolgáltatás végpontjának megvalósítási osztálya szerint minden alkalommal, amikor az ügyfél meghívja a helloStudent módszer a végponton, a benyújtott Diák az objektum a gyorsítótárban lesz tárolva. Ez a gyorsítótár a. Meghívásával érhető el getStudents módszer a végponton. A következő teszteset megerősíti a diákok a cache azt jelzi, hogy az ügyfél mit küldött a webszolgáltatásnak:

@Test public void usingGetStudentsMethod_thenCorrect () {Student student1 = new StudentImpl ("Adam"); baeldungProxy.helloStudent (hallgató1); Student student2 = new StudentImpl ("Éva"); baeldungProxy.helloStudent (hallgató2); Térképes hallgatók = baeldungProxy.getStudents (); assertEquals ("Ádám", hallgatók.get (1) .getName ()); assertEquals ("Éva", hallgatók.get (2) .getName ()); }

7. Következtetés

Ez az oktatóanyag bemutatta az Apache CXF-et, egy hatékony keretrendszert, amely a Java webszolgáltatásokkal használható. Arra összpontosított, hogy a keretrendszert standard JAX-WS megvalósításként alkalmazza, miközben futás közben továbbra is kihasználja a keret speciális képességeit.

Ezen példák és kódrészletek megvalósítása megtalálható egy GitHub projektben.