Contract first web service met JDeveloper 11g tp4
Ik ben de laatste tijd voor mijn klanten veel bezig met het helpen inrichten van SOA ontwikkelstraten en de bijbehorende omgevingen, procedures, standaarden en richtlijnen. Een van de moeilijkste keuzes is altijd hoe we om moeten gaan met web services, en in welke technologie(en) deze gemaakt moeten worden. Ik wil in dit artikel niet ingaan op deze specifieke vraag, maar wel een nieuwe mogelijkheid presenteren.
Ik ben al geruime tijd erg gecharmeerd van EJB3 en het bouwen van web services op basis van EJB3 stateless session beans in combinatie met JAX-WS en JAXB. Bij het uitproberen van JDeveloper 11g Technology Preview 4 zag ik tot mijn grote vreugde de optie om op basis van een WSDL met deze technologieën skeletons voor web services te genereren. Bij deze wil ik een korte tutorial aan jullie presenteren om te laten zien hoe dit werkt.
Allereerst hebben we JDeveloper 11g Technology Preview 4 nodig, die is te downloaden via deze link. Let er op dat indien de base versie wordt gedownload, deze alleen werkt in combinatie met een Java 5 SDK!
Deze kort tutorial is gebaseerd op deze JAXB tutorial van Netbeans. De WSDL van deze tutorial wordt ook gebruikt voor deze tutorial. De WSDL kan worden gedownload via deze link.
Start JDeveloper. JDeveloper opent en het volgende scherm verschijnt:
Start met het aanmaken van een nieuwe applicatie. Klik in de application navigator op de link ‘New Application…’. Er verchijnt een pop-up window voor het aanmaken van een nieuwe applicatie:
Vul als naam voor de applicatie in: SampleApplication. Laat de directory op de default waarde staan. Kies voor de Application Package Prefix een naam voor de package waarin de classes gegenereerd moeten worden. In dit voorbeeld is nl.florisautomatisering.tutorial gekozen als package naam. Hier kan ook een eigen package naam worden gekozen. Laat de Application Template ongewijzigd. Klik op ‘OK’ om door te gaan.
Nu start automatisch de wizard voor het aanmaken van een nieuw project in de applicatie workspace die we zojuist hebben aangemaakt. De volgende pop-up window verschijnt:
Kies voor de naam van het project: CreditReportService. Laat de directory op de default waarde staan, en klik op ‘OK’ om het project aan te maken.
JDeveloper opent nu de applicatie in de workspace, het volgende scherm verschijnt:
We hebben nu een project waarin we de webservice kunnen gaan genereren. Download de WSDL vanaf de Netbeans tutorial via de bovenstaande link in deze tutorial. Sla de WSDL op in de map: C:\JDeveloper\mywork\SampleApplication\CreditReportService\src. Indien de map ‘src’ nog niet is aangemaakt, voeg deze dan zelf toe. Plaats de WSDL op in de src map. Klik vervolgens in JDeveloper op het ‘refresh’ icoontje om de WSDL zichtbaar te maken in de workspace. Dubbelklik op CreditReportSimple.wsdl op deze te openen in de editor. Het volgende scherm verschijnt:
Nu kunnen we de web service genereren op basis van deze WSDL. Klik met de rechtermuisknop op het CreditReportService project in de Application Navigator. Kies in het context menu ‘New…’. De volgende dialoog verschijnt:
Kies in de selectieboom onder het kopje Business Tier voor Web Services. Klik vervolgens rechts op ‘Java Web Service from WSDL’. Klik nu op de ‘OK’ button om de wizard voor het aanmaken van de web service te starten. De wizard opent. Klik op ‘Next’ om vanaf het introductiescherm naar de eerste echte stap te gaan. Stap 2 van de wizard verschijnt nu:
Kies de optie Java EE 1.5 with JAX-WS annotations. Aangezien we gaan deployen in de met JDeveloper meegeleverde embedded OC4J container hoeven we niet de referentie implementatie optie te gebruiken. Klik op ‘Next’ om naar de volgende stap te gaan:
Nu moeten we de WSDL zoeken waarop we de web service gaan baseren. Omdat we deze reeds in ons project hebben gekopieerd kunnen we deze snel selecteren door rechts op het pijltje voor het drop-down veld te kiezen, en onze WSDL te selecteren. Normaal gesproken kan hier ook een andere lokatie op de harde schijf of een URL worden gebruikt om de WSDL te selecteren. Kies bij Service Type voor: EJB3. Zet het vinkje aan bij ‘Add Service Endpoint Interface’. Klik op ‘Next’ om naar de volgende stap te gaan:
In deze stap kan een package naam worden gekozen voor de gegenereerde web service klassen, evenals de bijbehorende klassen die worden gegenereerd voor de types. Standaard wordt hier de package naam ingevuld die we hebben gekozen bij het aanmaken van de Application. Klik op ‘Next’ om door te gaan naar de volgende stap:
In deze stap kan worden gekozen om de gegenereerde session bean statefull in plaats van stateless te maken. In principe wordt deze optie bijna nooit gebruikt, aangezien web services principieel stateless van aard dienen te zijn. Slechts in specifieke gevallen is het noodzakelijk statefull session beans te gebruiken. Laat de checkbox ongevinkt en klik op ‘Next’ om naar de volgende stap in de wizard te gaan:
In deze stap kan de service verder gespecificeerd worden. Dit scherm is reeds voor ingevuld op basis van wat er in de wizard gedefinieerd stond. Er kan hier worden gekozen om per Port de service uit te breiden met o.a. WS-Addressing en/of WS-Security opties. Voor deze tutorial maken wij hier geen gebruik van. Klik op ‘Next’ voor de volgende stap van de wizard:
In stap 7 van de wizard is het mogelijk om extra Handlers toe te voegen voor het afhandelen van SOAP berichten zoals deze de service in komen. Dit is nodig indien er bijvoorbeeld attributen zijn opgenomen in de SOAP header die uitgelezen moeten worden. Dit kan door een Handler aan te maken. Voor deze tutorial zijn geen Handlers nodig. Klik op ‘Next’ om naar de laatste stap van de wizard te gaan:
De laatste stap geeft een overzicht van alle keuzes gemaakt in de voorgaande stappen. Klik op ‘Finish’ om de wizard te beeindigen. JDeveloper gaat nu alle Java code genereren voor de web service. Ook voegt JDeveloper automatisch een aantal libraries toe aan het project. Na het genereren ziet de workspace er als volgt uit:
Er zijn een aantal klassen aangemaakt: CreditReportPortType en CreditReportPortTypeImpl voor de feitelijke implementatie van de service, en ObjectFactory, CreditQuery en CreditReport voor de in- en output types voor de argumenten van de service operaties.
JDeveloper heeft automatisch een aantal benodigde libraries toegevoegd aan het project. Klik met de rechtermuisknop op het CreditReportService project in de Application Navigator, en kies in het context menu voor de optie ‘Project Properties’. Er verschijnt een pop-up window met daarin alle instellingen voor het project. Kies in de boom links voor ‘Libraries and Classpath’. Het volgende scherm verschijnt:
Hierin is te zien dat de libraries JAX-WS Web Services, Java EE 1.5, JAXB en EJB 3.0 zijn toegevoegd aan ons project. Klik op ‘Cancel’ om de dialoog te sluiten.
Dubbelklik op de CreditReportPortTypeImpl klasse in de Application Navigator om deze in de editor te openen. Onze WSDL bevat maar 1 operatie: <wsdl:operation name=”CreditReportOperation”>. Deze is terug te vinden in de zojuist geopende klasse als Java methode: public CreditReport creditReportOperation(CreditQuery creditQueryPart).
Voeg de volgende code toe (regel 19-45):
Op regel 21 instantieren we de gegenereerde ObjectFactory. Dit is de zogenaamde JAXB XmlRepository waarmee we objecten kunnen aanmaken die op hun beurt weer gebruikt worden voor het genereren ((un-)marshallen) van de XML voor de service in- en output. Op regel 22 is te zien hoe de object factory wordt gebruikt om een nieuw CreditReport te maken, wat de output van onze service operatie is. In regel 25 t/m 41 zetten we wat waarden in het CreditReport ter illustratie van de werking van de service. Normaal gesproken zouden we hier bijvoorbeeld de database bevragen en business logica uitvoeren. Op regel 44 geven we het CreditReport terug als resultaat van de service.
Om te controleren of alles goed is geprogrammeerd moeten we de sources compileren. Klik met de rechtermuisknop op het CreditReportService project, en kies in het context menu voor ‘Make’. Als alles goed is zijn er geen fouten tijdens het compileren:
De service is nu gereed om gedeployed te worden. Klik op de groene ‘play’ button (Run) om de service automatisch te laten deployen in de met JDeveloper meegeleverde ingebouwde OC4J 11g container. Er opent onder in het scherm een nieuw tabblad venster met daarin de uitvoer van de OC4J container. Er verschijnen een aantal fouten die genegeerd kunnen worden. Na een tijdje verschijnt de tekst:
Ready message received from Oc4jNotifier.
Embedded OC4J Server startup time: 53859 ms.Target URL — http://localhost:8988/EJB-SampleApplication-CreditReportService-context-root/CreditReportPortType
Process exited.
Net zoals in de volgende screenshot:
Kopieer de gegeven url in je favoriete internet browser. De volgende HTML pagina verschijnt:
Dit is een specifiek scherm dat door de Oracle JAX-WS implementatie gegenereerd wordt om de service te kunnen testen. Omdat we in onze service geen gebruik maken van de input kunnen we de service direct testen, zonder eerst waarden in te voeren, door op de knop ‘Invoke’ te klikken. De service wordt nu uitgevoerd, en het resultaat wordt teruggegeven. Klik om dit leesbaar te maken op de link ‘Formatted XML’ boven in het resultaat scherm. Dit zou er als volgt uit moeten zien:
We hebben nu succesvol een EJB3 web service gemaakt op basis van een WSDL. Dit is de zogenaamde ‘contract first’ methode om services te ontwikkelen. Naar mijn mening is dit de beste manier om services te ontwikkelen, omdat de interface het allerbelangrijkste aspect van een service is. De interfact dient normaal gesproken gedefinieerd te worden op basis van het semantische model (types) en de gewenste business functionaliteit (operaties). In een zuivere SOA omgeving en methodiek bestaat de WSDL dan ook voordat de service wordt geimplementeerd.
De in deze tutorial gegenereerde service zal niet zomaar deployen op een Oracle 10g applicatie server. Er kan in JDeveloper 11g Technology Preview geen connectie worden gemaakt met 10g applicatie servers. Ook het bouwen van een EAR file, en deze deployen op 10g gaat niet zomaar. Dit komt omdat de Oracle 10g applicatie server gebruik maakt van een verouderde (eigen implementatie van) JAX-WS en JAXB. In een volgend artikel zal ik laten zien hoe een 10g applicatie server kan worden aangepast voor het ondersteunen van deze JAX-WS 2 en JAXB 2 web services.
Tags: 11g, contract, J2EE, jax-ws, jaxb, jaxws, jdeveloper, Oracle, service, soap, web services, webservice, wsdl