Java EE heeft zich sinds 1999(!) bewezen als ontwikkelplatform voor de zakelijke markt. Java Enterprise Edition bestaat uit een set van gestandaardiseerde specificaties, die vanuit een community wordt opgesteld en ontwikkeld. Deze specificaties definiëren API’s en bijbehorende interacties waar Java ontwikkelaars tegenaan kunnen bouwen. Deze specificaties zijn geversioneerd en vormen de bouwstenen voor overkoepelende Java EE versies. De implementatie van deze specificaties wordt verzorgd door applicatieservers, zoals Payara, Wildfly en TomEE. In theorie zou broncode voor Java EE moeiteloos van applicatieserver kunnen verhuizen, aangezien deze op de dezelfde specificaties zijn gebaseerd. In 2017 heeft Oracle aangekondigd het beheer van Java EE los te laten en deze te verhuizen naar de Eclipse Foundation. Deze verhuizing is momenteel in volle gang en daarna zal het project in een nieuwe opzet verder gaan onder de naam Jakarta EE.
Auteur: Antek Jaworski
Hoewel Java EE 8 (de meest recente versie uit 2017) een vrij complete set met functionaliteiten biedt, zijn er op bepaalde terreinen nog tekortkomingen. Voor gedistribueerde systemen, zoals microservices, missen bijvoorbeeld een aantal basisbehoeften op het gebied van robuustheid, monitoring en een betere inzage in berichtenverkeer. Een aantal platform partijen heeft hiervoor de handen ineen geslagen en een nieuw open source project gestart binnen de Eclipse Foundation: Eclipse MicroProfile. Dit project heeft als doel om een gestandaardiseerde oplossing te bieden voor de tekortkomingen van Java EE voor moderne (gedistribueerde) systemen en cloud toepassingen. Eclipse MicroProfile vormt een bouwsteen bovenop Java EE en wordt volgens dezelfde filosofie ontwikkeld. Nieuwe standaarden worden door de community bedacht en deze worden vervolgens in specificaties en API’s gegoten. Aan de applicatieservers is de schone taak om de implementatie voor deze specificaties te verzorgen. Mogelijk zullen een aantal van deze nieuwe standaarden ooit deel uit gaan maken van Jakarta EE.
MicroProfile versie 2.2 bestaat op dit moment uit de volgende specificaties:
Een van de meest recente mijlpalen binnen het MicroProfile project is de oprichting van de MicroProfile starter (https://start.microprofile.io). Deze website is de MicroProfile variant van de Spring Initializr en werkt volgens hetzelfde concept. Op een overzichtelijke webpagina kunnen de gewenste bouwstenen gekozen worden en binnen een paar klikken kan een zip-file met daarin het skelet voor het nieuwe (Maven) project worden gedownload. Bij het selecteren van de MicroProfile versie wordt de lijst met ondersteunende applicatieservers aangepast. Het aanbod hiervan verschilt per MicroProfile versie, maar de applicatie platformen zijn druk bezig om aan de specificaties van de nieuwste Microprofile versies te voldoen. Ook is in één oogopslag te zien welke Microprofile functionaliteiten geïmplementeerd kunnen worden (als voorbeelden) en deze worden standaard allemaal geselecteerd. De MicroProfile starter is een handig hulpmiddel voor ontwikkelaars, die al enige tijd ervaring hebben met Java EE en/of MicroProfile en zo snel nieuwe projecten kunnen starten. Voor ontwikkelaars die nog geen ervaring hebben met de concepten van Jave EE en Microprofile is de starter uitermate nuttig. De eenvoud om een voorbeeldproject met documentatie te downloaden, bouwen en starten zorgt ervoor dat deze groep in een mum van tijd bekend kan raken met de concepten van Java EE en MicroProfile.
In dit voorbeeld wordt binnen een paar seconden een nieuw project aangemaakt:
Na het uitpakken van de zip is de volgende structuur zichtbaar:
In de readme.md staat informatie over het gecreëerde project. Er wordt beschreven hoe het project gebouwd en gestart kan worden. Ook is er voor elke MicroProfile specificatie een beschrijving van het voorbeeld met een verwijzing naar online documentatie. Deze voorbeelden dienen als prima basismateriaal om een aantal API’s van de specificaties te doorgronden. Nu volgt een korte toelichting op de specificaties en een voorbeeld uit de zip die eenvoudig zelf te genereren is.
Eén van de zaken, die gemist wordt in Java EE, is een gestandaardiseerd en eenvoudig configuratiemechanisme. MicroProfile Config biedt de mogelijkheid om externe configuratie op een simpele manier beschikbaar te maken in een applicatie. Het voorbeeld laat zien hoe waarden vanuit een properties file kunnen worden geïnjecteerd in een klasse. Via zogenaamde ConfigSources is het mogelijk om desgewenst eigen configuratiebronnen te ondersteunen. Gebruik de @ConfigProperty annotatie om configuratie te injecteren.
Voor Fault Tolerance zijn er een aantal bouwstenen beschikbaar: TimeOut, Retry, Fallback, Bulkhead, CircuitBreaker en Asynchronous. Deze bouwstenen zijn met voorbeelden te vinden op de website van MicroProfile. Een voorbeeld van Fallback en TimeOut is opgenomen als voorbeeld in het aangemaakte project in de klasse ResilienceController.java. In de code wordt teruggevallen op een Fallback-methode wanneer een gespecificeerde time-out wordt overschreden bij de aanroep van een Rest interface.
In een gedistribueerde omgeving is er voor de communicatie tussen servers en clients een manier nodig om de beveiliging en authenticiteit van berichten te waarborgen. Een veelgebruikte manier is het gebruik van security tokens, waar de JWT Authentication specificatie om draait. Op basis van een sleutelpaar (private en public key) worden tokens gegenereerd en gevalideerd. In het token zit alles wat nodig is om te bepalen of het bericht van de juiste afzender is en welke rollen en rechten de gebruiker heeft. Met behulp van de RolesAllowed annotatie is het mogelijk om object en methoden te beveiligen. Bij de annotatie kunnen rollen vermeld worden, die aanwezig dienen te zijn in het token. De Claim annotatie kan worden gebruikt om eventuele andere gegevens van het token eenvoudig uit te lezen. In de test-tak van het project is een client (JWTClient.java) te vinden, waarmee het voorbeeld endpoint kan worden aangeroepen. In deze client wordt een token aangemaakt met de rol protected.
Een health endpoint is tegenwoordig een basisbehoefte, wanneer gebruik wordt gemaakt van cloud infrastructuur, zoals bijvoorbeeld Kubernetes. Via dit endpoint kan gecontroleerd worden of de applicatie nog functioneert. In dat geval is de reactie van het endpoint: up. Deze check kan desgewenst uitgebreid worden met informatie over de checks, die zijn uitgevoerd. Het health endpoint is standaard te vinden op /health.
Metrics zijn erg nuttig voor monitoring van de toestand en prestaties van een applicatie. Veel standaard metrieken met betrekking tot de JVM en het besturingssysteem zijn beschikbaar op /metrics/base, maar ook is er de mogelijkheid om via een programmeerbare API eigen metrieken toe te voegen. Deze API biedt mogelijkheden voor bijvoorbeeld het bekijken van de actuele waarde van een object (Gauge), het tellen van aanroepen (Counter) van een methode en statistieken over tijdsduur van aanroepen (Timer). Zo kan met behulp van simpele bouwstenen informatie verzameld worden over de prestaties van (cruciale) processen binnen de applicatie. De applicatiespecifieke metrieken zijn te vinden op /metrics/application.
Aangezien veel berichtenverkeer in gedistribueerde systemen, zoals microservices, bestaat uit communicatie met Rest API’s, is het belangrijk dat beschrijvende documentatie aanwezig is. In veel gevallen was het nodig om een behoorlijke portie code toe te voegen, voordat deze documentatie kon worden gegenereerd. MicroProfile OpenAPI kan zonder toegevoegde code een opvraagbaar overzicht genereren in YAML. Dit zal in veel gevallen voldoende zijn voor ontwikkelaars binnen een project. Wanneer meer documentatie gewenst is, is er een API, waarmee dit kan worden toegevoegd. Het OpenAPI overzicht is standaard te vinden op /openapi.
Vanuit het oogpunt van een ontwikkelaar is er behoefte aan een zo kort mogelijke feedback loop tussen geschreven code en het resultaat. Het is dan aan te raden om de volledige serverversie van de gekozen implementatie lokaal te downloaden. Deze servers zijn vaak een subset van de web/micro varianten, maar bieden meestal meer ondersteuning in IDE’s, zoals Eclipse, NetBeans en IntelliJ. Denk hierbij aan mogelijkheden voor deployen, debuggen en (in sommige gevallen) code hotswapping. Op deze manier kunnen aanpassingen van de code snel worden getest. Een typisch Java EE (en ook Microprofile) project bevat meestal maar weinig dependencies, aangezien de applicatieserver de implementaties voor de specificaties voor zijn rekening neemt. Herbouwen van code is hierdoor qua tijdsduur tot een minimum beperkt. De enige code, die gebouwd moet worden, bestaat uit de logica van de applicatie en hooguit een handjevol dependencies met als resultaat een zogenaamde thin war. Deze thin war is dan binnen een paar seconden gedeployed op een draaiende server.
Het concept van thin wars is al sinds jaar en dag gebruikelijk bij Java EE. Deze gelaagde opzet is in de wereld van containers en PAAS omgevingen ook uitermate relevant en geschikt. Het past perfect in het gelaagde model van bijvoorbeeld Docker containers, waarbij de opbouw bestaat uit lagen (images). Een gebruikelijke manier is via een basisbesturingssysteemlaag, met daarop een JDK-installatielaag, daarboven de applicatieserver en tot slot de projectcode in een thin war, die dan samen met eventuele configuratie in een container gestart kan worden.
Bij een aanpassing in de broncode van het project zal enkel deze bovenste laag gewijzigd worden en de thin war van enkele kilobytes of megabytes wanneer er externe dependencies worden gebruikt. Dit zorgt ervoor dat er een minimale hoeveelheid bandbreedte en opslagcapaciteit nodig is van de lokale omgeving en de gebruikte Docker registry en versiebeheer, zoals Docker registry.
Voor de meeste applicatieservers staan kant-en-klare Docker images gereed waar eenvoudig een project in gedeployed kan worden.
Een voorbeeld voor een Payara Micro Dockerfile voor het voorbeeldproject:
FROM payara/micro COPY target/javamagazine.war $DEPLOY_DIR/ROOT.war
Merk op dat het project als ROOT.war gedeployed wordt, zodat het geen context-root heeft. Dit verschilt per applicatieserver. Deze Docker file kan worden gebruikt om het project als Docker image te bouwen:
docker build -t org.nljug/javamagazine .
Deze image kan dan worden gestart met:
docker run -p 8080:8080 org.nljug/javamagazine
Vervolgens kan op localhost:8080 een overzicht worden bekeken van de eerdere besproken voorbeelden op de index.html pagina van de applicatie, die nu als Docker container actief is.
De MicroProfile starter vormt een belangrijk onderdeel van het MicroProfile project. Het biedt een overzichtelijke manier om binnen een paar muisklikken een nieuw MicroProfile project te starten. Op deze manier kunnen ontwikkelaars eenvoudig kennismaken met de concepten van Java EE en Eclipse MicroProfile. Deze vormen namelijk een verlengstuk op elkaar en zorgen ervoor dat ontwikkelaars zich volledig op de logica van de applicatie kunnen richten, die resulteren in thin wars. Door de gelaagde opzet lenen deze projecten met hun thin wars zich erg goed voor container oplossingen.
Voor ontwikkelaars in een microservices project kan het een leuk idee zijn om de volgende microservice te ontwikkelen met Eclipse MicroProfile. Met de MicroProfile starter ben je zo up & running!