Een gids voor Apache CXF met Spring

1. Overzicht

Deze tutorial richt zich op het configureren van en met behulp van het Apache CXF-framework samen met Spring - hetzij met Java- of XML-configuratie.

Het is de tweede in een serie over Apache CXF; de eerste was gericht op de basisprincipes van CXF als een implementatie van de JAX-WS standaard API's.

2. Maven afhankelijkheden

Net als bij de vorige zelfstudie, moeten de volgende twee afhankelijkheden worden opgenomen:

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

Voor de nieuwste versies van Apache CXF-artefacten, ga je naar apache-cxf.

Daarnaast zijn de volgende afhankelijkheden nodig om Spring te ondersteunen:

 org.springframework spring-context 4.3.1.RELEASE org.springframework spring-webmvc 4.3.1.RELEASE 

De nieuwste versies van lente-artefacten zijn hier te vinden.

Ten slotte, omdat we de applicatie programmatisch zullen configureren met behulp van de Java Servlet 3.0+ API in plaats van een traditionele web.xml implementatie descriptor, hebben we het onderstaande artefact nodig:

 javax.servlet javax.servlet-api 3.1.0 

Hier kunnen we de laatste versie van de Servlet API vinden.

3. Componenten aan de serverzijde

Laten we nu eens kijken naar de componenten die aan de serverzijde aanwezig moeten zijn om het webservice-eindpunt te publiceren.

3.1. WebApplicationInitilizer Koppel

De WebApplicationInitializer interface is geïmplementeerd om het ServletContext interface voor de applicatie. Indien aanwezig op het klassenpad, is het onStartup methode wordt automatisch aangeroepen door de servlet-container en daarna de ServletContext wordt geïnstantieerd en geïnitialiseerd.

Hier is hoe een klasse wordt gedefinieerd om het WebApplicationInitializer koppel:

openbare klasse AppInitializer implementeert WebApplicationInitializer {@Override public void onStartup (ServletContext-container) {// Methode-implementatie}}

De onStartup () methode wordt geïmplementeerd met behulp van onderstaande codefragmenten.

Eerst wordt een Spring-toepassingscontext gemaakt en geconfigureerd om een ​​klasse te registreren die configuratiemetagegevens bevat:

AnnotationConfigWebApplicationContext context = nieuwe AnnotationConfigWebApplicationContext (); context.register (ServiceConfiguration.class);

De ServiceConfiguration klasse is geannoteerd met de @Configuratie annotatie om bean-definities te geven. Deze klasse wordt besproken in de volgende paragraaf.

Het volgende fragment laat zien hoe de Spring-toepassingscontext wordt toegevoegd aan de servlet-context:

container.addListener (nieuwe ContextLoaderListener (context));

De CXFServlet class, die wordt gedefinieerd door Apache CXF, wordt gegenereerd en geregistreerd om inkomende verzoeken af ​​te handelen:

ServletRegistration.Dynamic dispatcher = container.addServlet ("dispatcher", nieuwe CXFServlet ());

De toepassingscontext laadt Spring-elementen die zijn gedefinieerd in een configuratiebestand. In dit geval is de naam van de servlet cxfdaarom zoekt de context naar die elementen in een bestand met de naam cxf-servlet.xml standaard.

Ten slotte wordt de CXF-servlet toegewezen aan een relatieve URL:

dispatcher.addMapping ("/ services");

3.2. De goede oude web.xml

Als alternatief, als we gebruik willen maken van een (ietwat ouderwetse) deployment descriptor in plaats van de WebApplicationInitilizer interface, de bijbehorende web.xml bestand moet de volgende servletdefinities bevatten:

 cxf org.apache.cxf.transport.servlet.CXFServlet 1 cxf / services / * 

3.3. ServiceConfiguration Klasse

Laten we nu eens kijken naar de serviceconfiguratie - eerst een basisskelet met bean-definities voor het webservice-eindpunt:

@Configuration openbare klasse ServiceConfiguration {// Bean-definities}

De eerste vereiste boon is de SpringBus - die extensies levert voor Apache CXF om te werken met het Spring Framework:

@Bean openbare SpringBus springBus () {retourneer nieuwe SpringBus (); }

Een EnpointImpl bean moet ook worden gemaakt met de SpringBus bean en een webservice uitvoerder. Deze bean wordt gebruikt om het eindpunt op het opgegeven HTTP-adres te publiceren:

@Bean public Endpoint endpoint () {EndpointImpl endpoint = nieuw EndpointImpl (springBus (), nieuwe BaeldungImpl ()); endpoint.publish ("// localhost: 8080 / services / baeldung"); eindpunt teruggeven; }

De BaeldungImpl class wordt gebruikt om de webservice-interface te implementeren. De definitie ervan wordt gegeven in de volgende onderafdeling.

Als alternatief kunnen we het servereindpunt ook declareren in een XML-configuratiebestand. In het bijzonder de cxf-servlet.xml onderstaande bestand werkt met de web.xml inzetdescriptor zoals gedefinieerd in paragraaf 3.1 en beschrijft exact hetzelfde eindpunt:

Houd er rekening mee dat het XML-configuratiebestand is vernoemd naar de servletnaam die is gedefinieerd in de implementatiedescriptor, namelijk cxf.

3.4. Typ definities

Volgende - hier is de definitie van de uitvoerder dat is al genoemd in de vorige paragraaf:

@WebService (endpointInterface = "com.baeldung.cxf.spring.Baeldung") openbare klasse BaeldungImpl implementeert Baeldung {private int counter; public String hallo (String naam) {return "Hallo" + naam + "!"; } openbaar String register (Student student) {counter ++; return student.getName () + "is geregistreerd studentnummer" + teller; }}

Deze klasse biedt een implementatie voor het Baeldung eindpuntinterface die Apache CXF zal opnemen in de gepubliceerde WSDL-metadata:

@WebService openbare interface Baeldung {String hallo (String naam); String register (student student); }

Zowel de eindpuntinterface als de implementator maak gebruik van de Leerling klasse, die als volgt wordt gedefinieerd:

openbare klas Student {privé Stringnaam; // constructeurs, getters en setters}

4. Bonen aan de kant van de klant

Om te profiteren van het Spring Framework, verklaren we een boon in een @Configuratie geannoteerde klasse:

@Configuration openbare klasse ClientConfiguration {// Bean-definities}

Een boon met de naam cliënt is gedefinieerd:

@Bean (naam = "client") openbaar object GenereerProxy () {retourneer proxyFactoryBean (). Create (); }

De cliënt bean vertegenwoordigt een proxy voor de Baeldung webservice. Het wordt gemaakt door een aanroep naar het creëren methode op een JaxWsProxyFactoryBean bean, een fabriek voor het maken van JAX-WS-proxy's.

De JaxWsProxyFactoryBean object wordt gemaakt en geconfigureerd door de volgende methode:

@Bean openbare JaxWsProxyFactoryBean proxyFactoryBean () {JaxWsProxyFactoryBean proxyFactory = nieuwe JaxWsProxyFactoryBean (); proxyFactory.setServiceClass (Baeldung.class); proxyFactory.setAddress ("// localhost: 8080 / services / baeldung"); retourneer proxyFactory; }

De fabriek serviceClass eigenschap geeft de webservice-interface aan, terwijl de adres eigenschap geeft het URL-adres aan voor de proxy om externe aanroepen te doen.

Ook voor de Spring Beans aan de clientzijde kan men terugvallen op een XML-configuratiebestand. De volgende elementen verklaren dezelfde bonen als degene die we zojuist programmatisch hierboven hebben geconfigureerd:

5. Testgevallen

Deze sectie beschrijft testcases die worden gebruikt om Apache CXF-ondersteuning voor Spring te illustreren. De testgevallen worden gedefinieerd in een klasse met de naam StudentTest.

Eerst moeten we een Spring-toepassingscontext laden uit het bovengenoemde ServiceConfiguration configuratieklasse en cachegeheugen in de context veld:

private ApplicationContext context = nieuwe AnnotationConfigApplicationContext (ClientConfiguration.class);

Vervolgens wordt een proxy voor de service-eindpuntinterface gedeclareerd en geladen vanuit de toepassingscontext:

private Baeldung baeldungProxy = (Baeldung) context.getBean ("cliënt");

Dit Baeldung proxy wordt gebruikt in testcases die hieronder worden beschreven.

In het eerste testgeval bewijzen we dat wanneer de Hallo methode lokaal wordt aangeroepen op de proxy, het antwoord is precies hetzelfde als wat het eindpunt is implementator keert terug van de externe webservice:

@Test openbare leegte whenUsingHelloMethod_thenCorrect () {String response = baeldungProxy.hello ("John Doe"); assertEquals ("Hallo John Doe!", antwoord); }

In het tweede testgeval schrijven studenten zich in voor Baeldung-cursussen door lokaal een beroep te doen op de registreren methode op de proxy, die op zijn beurt de webservice aanroept. Die service op afstand berekent vervolgens de studentnummers en stuurt ze terug naar de beller. Het volgende codefragment bevestigt wat we verwachten:

@Test public void whenUsingRegisterMethod_thenCorrect () {Student student1 = nieuwe student ("Adam"); Student student2 = nieuwe student ("Eve"); String student1Response = baeldungProxy.register (student1); String student2Response = baeldungProxy.register (student2); assertEquals ("Adam is geregistreerd studentnummer 1", student1Response); assertEquals ("Eve is geregistreerd studentnummer 2", student2Response); }

6. Integratietesten

Om als webtoepassing op een server te worden geïmplementeerd, moeten codefragmenten in deze zelfstudie eerst in een WAR-bestand worden verpakt. Dit kan worden bereikt door de verpakking eigenschap in het POM-bestand:

oorlog

De verpakkingstaak wordt geïmplementeerd door de Maven WAR-plug-in:

 maven-war-plugin 2.6 false 

Deze plug-in verpakt de gecompileerde broncode in een WAR-bestand. Omdat we de servlet-context configureren met behulp van Java-code, is de traditionele web.xml Deployment descriptor hoeft niet aanwezig te zijn. Als resultaat is het failOnMissingWebXml eigenschap moet worden ingesteld op false om fouten te voorkomen wanneer de plug-in wordt uitgevoerd.

We kunnen deze link volgen voor de meest recente versie van de Maven WAR-plug-in.

Om de werking van de webservice te illustreren, maken we een integratietest. Deze test genereert eerst een WAR-bestand en start een ingebedde server, laat vervolgens clients de webservice aanroepen, verifieert daaropvolgende reacties en stopt uiteindelijk de server.

De volgende plug-ins moeten worden opgenomen in het Maven POM-bestand. Bekijk deze tutorial over integratietesten voor meer informatie.

Hier is de Maven Surefire-plug-in:

 maven-surefire-plugin 2.19.1 StudentTest.java 

De laatste versie van deze plug-in is hier te vinden.

EEN profiel sectie met de ID kaart van integratie wordt verklaard om de integratietest te vergemakkelijken:

  integratie ... 

De Maven Cargo-plug-in is opgenomen in het integratie profiel:

 org.codehaus.cargo cargo-maven2-plugin 1.5.0 jetty9x embedded localhost 8080 start-server pre-integratie-test start stop-server post-integratie-test stop 

Merk op dat de cargo.hostnaam en cargo.servlet.port configuratie-eigenschappen zijn alleen voor de duidelijkheid opgenomen. Deze configuratie-eigenschappen kunnen worden weggelaten zonder enige impact op de toepassing, aangezien hun waarden hetzelfde zijn als de standaardwaarden. Deze plug-in start de server, wacht op verbindingen en stopt uiteindelijk de server om systeembronnen vrij te geven.

Met deze link kunnen we de nieuwste versie van de Maven Cargo-plug-in bekijken.

De Maven Surefire-plug-in wordt opnieuw gedeclareerd, binnen de integratie profiel, om de configuratie ervan in de main bouwen sectie en om testcases uit te voeren die in de vorige sectie zijn beschreven:

 maven-surefire-plugin 2.19.1 integratietest test geen 

Nu kan het hele proces worden uitgevoerd met de opdracht: mvn -Pintegration schone installatie.

7. Conclusie

Deze tutorial illustreerde Apache CXF-ondersteuning voor Spring. In het bijzonder is getoond hoe een webservice kan worden gepubliceerd met behulp van een Spring-configuratiebestand, en hoe een klant kan communiceren met die service via een proxy die is gemaakt door een Apache CXF-proxyfabriek, die is gedeclareerd in een ander configuratiebestand.

De implementatie van al deze voorbeelden en codefragmenten is te vinden in het gekoppelde GitHub-project.


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