Unterhaus weiterhin einig im Nicht-entscheiden – droht jetzt der harte Pexit?

Das britische Parlament hat das Austrittsabkommen zum dritten Mal abgelehnt. Bis zum 12. April muss geklärt werden, wie es weitergehen soll. Droht jetzt auch für den beliebten JEE-Server Payara der Pexit, d. h. die Abschottung vom Rest der Welt?

Der Server wird von der Payara Services Ltd in Malvern, United Kingdom, angeboten und als Open Source Software entwickelt. Könnte bei einem Pexit ohne Deal Entwicklern aus dem restlichen Europa der freie Zugang zum Quellcode entzogen werden?

Auf der Payara-Webseite finden sich Aussagen wie „Always Open Source“, „Public open source development“ und „encouraging users’ involvement“, aber lassen sich diese vor dem Hintergrund der entscheidungsunfähigen Politik noch halten?

Payara hat neben dem Hauptsitz auch ein Office in Portugal. Vielleicht lassen sich Downloads, Contributions und Service Requests zukünftig über dieses europäische Büro abwickeln.

Die letzten Entscheidungen stehen noch aus; hoffentlich kann Payara doch noch in der Community verbleiben!

Übrigens: Wir bieten unsere JEE-Kurse auch auf Payara an und das vermittelte Wissen ist garantiert nicht vom britischen Parlament abhängig. Schauen Sie doch mal vorbei: https://gedoplan-it-training.de/.

Werbeanzeigen

Wie läuft’s denn so? Monitoring mit MicroProfile Metrics

In meinem Blog-Eintrag „Alles gesund? Health checking mit MicroProfile Health“ habe ich dargestellt, wie einfach man den Gesundheitszustand einer Anwendung auf Basis von MicroProfile Health veröffentlichen kann. Und wenn man nun nicht nur wissen möchte, ob ein Service läuft, sondern mehr Details über den Service-Zustand erfahren möchte? Dann unterstützt uns ein weiterer Baustein: MicroProfile Metrics.

Telemetriedaten out of the box

Über den Rest-Endpoint /metrics/base werden ohne weiteren Programmieraufwand Basis-Telemetriedaten zur Verfügung gestellt:

{
  "memory.maxHeap": 8342470656,
  "memory.usedHeap": 259349504,
  "gc.G1 Young Generation.count": 28,
  "cpu.systemLoadAverage": 0.6,
  "thread.count": 111,
  ...
}

Die Daten werden in JSON geliefert, wenn man sie mit diesem Media Type anfordert (z. B. curl -H "Accept: application/json" localhost:8080/metrics/base). Mit dem Default-Media-Type text/plain werden die Daten passend für die Verarbeitung in Prometheus geliefert.

Der Endpoint /metrics/vendor ist für herstellerspezifische Messdaten aus der genutzten Plattform vorgesehen.

Anwendungsspezifische Metriken

EE-Anwendungen können weitere Messdaten bereitstellen. So kann man bspw. Methoden von CDI Beans mit der Annotation @Gauge versehen:

  @Gauge(name = "answerToLifeUniverseAndEverything", absolute = true, unit = MetricUnits.NONE)
  public long getAnswerToLifeUniverseAndEverything() {
    return 42;
  }

Die derart zur Verfügung gestellten Werte werden im Endpoint /metrics/application veröffentlicht:

{
  "answerToLifeUniverseAndEverything": 42
}

Neben dieser Möglichkeit, eigene Messwerte zu berechnen und zu veröffentlichen, kann man auch Telemetriedaten durch das Framework aggregieren lassen:

  @GET
  @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
  @Timed(name = "personList", absolute = true)
  public List getAll() {
    return this.personRepository.findAll();
  }

@Timed bewirkt hier, dass die Ausführungszeiten der annotierten Methode gemessen und zu verschiedenen statistischen Werten aggregiert werden:

{
  "personList": {
    "p50": 4922800.0,
    "p75": 5160200.0,
    "p95": 1.00322E7,
    "p98": 1.00322E7,
    "p99": 1.00322E7,
    "p999": 1.00322E7,
    "min": 3218000.0,
    "mean": 5476794.800597489,
    "max": 1.00322E7,
    "stddev": 2340795.005960796,
    "count": 5,
    "meanRate": 0.6766077577220262,
    "oneMinRate": 1.0,
    "fiveMinRate": 1.0,
    "fifteenMinRate": 1.0
  }
}

Analog könnte mit @Counted ein Aufrufzähler für eine Methode etabliert werden.

Gesamt-Metrik

Der Endpoint /metrics fasst die bislang genannten Datengruppen in ein Gesamtergebnis zusammen.

Plattformen

MicroProfile Metrics wird u. a. von folgenden JEE-Servern unterstützt:

  • OpenLiberty (mit aktivierten Features mpMetrics-1.1 und monitor-1.0).
  • Payara.
  • WildFly (Achtung: WildFly hat unterschiedliche Ports für Applikations- und Management-Zugriffe, im Default 8080 und 9990. Der o. a. REST-Endpoint /metrics steht über den Management-Port zur Verfügung).

Die genannten Klassen befinden sich bspw. in der Maven-Dependency org.eclipse.microprofile:microprofile.

Demo

In https://github.com/GEDOPLAN/metrics-demo finden Sie ein Beispielprojekt mit einem REST-Service, dessen GET– und POST-Methoden so annotiert sind, dass Zeiten bzw. Aufrufzahlen gemessen werden. Der o. a. Service, der die legendäre 42 als Ergebnis liefert, ist ebenfalls im Beispielprojekt enthalten. Die Anwendung kann als WAR-File auf einen der genannten Server deployt werden. Alternativ können über vorkonfigurierte Maven-Profile Docker-Images zum direkten Ausprobieren erstellt werden.

Bis bald – vielleicht auch in einem unserer Trainings in Berlin, Bielefeld, Köln oder bei Ihnen!
https://gedoplan-it-training.de/

WildFly 16 released!

Seit gestern steht die Version 16.0.0.Final des WildFly zum Download bereit (http://wildfly.org/downloads/).

Bei einem kurzen Blick darauf sind mir zwei interessante Neuerungen aufgefallen:

  • Der Server unterstützt nun auch Microprofile Metrics.
  • Mit Hilfe von Galleon (https://github.com/wildfly/galleon), einem neuen Provisionierungstool, können Serverinstallationen erzeugt werden, die nur die jeweils benötigten Module enthalten.

Beide Punkte zeigen, dass der Server sich immer weiter in Richtung Cloud Readiness entwickelt.

Bis bald – vielleicht auch in einem unserer Trainings in Berlin, Bielefeld, Köln oder bei Ihnen!
https://gedoplan-it-training.de/

Transaktionssteuerung mit @Transactional

Transaktionen sind nötig, um Daten atomar, konsistent, isoliert und dauerhaft bearbeiten und speichern zu können (ACID-Prinzip). Methoden von CDI-Beans können durch eine simple Annotation mit einem aktiven Transaktionskontext versehen werden.

Transaktionsinterceptor mit dem Binding @Transactional

Schon seit der Version 1.1 von CDI steht ein global aktivierter Transaktionsinterceptor zur Verfügung. Er wird mit der Annotation @Transactional einer Methode einer CDI-Bean zugeordnet:

public class SomeService {
  ...
  @Transactional
  public void doSomethingTransactionally() {
    ...
  }

Beim Aufruf der Methode ohne aktive Transaktion wird nun eine Transaktion gestartet und nach dem Verlassen der Methode wieder geschlossen. Die Regeln für das Transaktionsende sind etwas seltsam:

  • Endet die Methode mit einem Return, wird ein Commit versucht.
  • Wirft die Methode eine sog. System Exception, resultiert dies in einem Rollback. System Exceptions sind i. W. die unchecked Exceptions (ergänzt um die RemoteException, die aber explizit kaum eine Rolle spielt).
  • Wirft die Methode eine Application Exception – das sind alle anderen Exeptions – wird ein Commit (!) versucht.

Insbesondere der letzte Punkt ist (zumindest mir) unverständlich: Für mich modellieren Exceptions immer Ausnahmesituationen, die den jeweiligen Geschäftsprozess ungültig machen. Glücklicherweise kann man mit einem Parameter der Annotation auch in diesem Fall ein Rollback ansteuern:

  @Transactional(rollbackOn=Exception.class)
  public void doSomethingTransactionally() {

Transaktionsmodus

Die Art der Transaktionssteuerung durch @Transactional kann mit dem Parameter value bestimmt werden:

  • TxType.REQUIRED ist der Default, der in den allermeisten Fällen passend ist. Beim Aufruf einer davon betroffenen Methode wird geprüft, ob bereits eine aktive Transaktion vorliegt. Wenn ja, wird diese für den Methodenaufruf genutzt. Andernfalls wird eine neue Transaktion gestartet und am Methodenende wieder beendet.
  • TxType.REQUIRES_NEW startet bei Methodenbeginn stets eine neue Transaktion, die am Methodenende wieder beendet wird. Eine ggf. bereits aktive Transaktion wird zuvor suspendiert. Dieser Modus sollte dann verwendet werden, wenn die Ergebnisse des Methodenaufrufs auch dann dauerhaft abgespeichert werden sollen, wenn die umgebende Transaktoin zurückgerollt wird. Beispiel: Auditing/Protokollierung von Methodenaufrufen.
  • TxType.MANDATORY verlangt eine aktive Transaktion bei Methodenbeginn und wirft andernfalls eine TransactionRequiredException. Dieser Modus ist könnte prinzipiell für Repositories (a.k.a DAOs) interessant sein, da deren feingranulare Methoden i. A. von einem Service aufgerufen werden, der selbst transaktional ist. Leider werden Lifecycle-Methoden (@PostConstruct-annotierte Methoden etc.) nicht durch die @Transactional-Interceptoren intercepted. Häufig werden darin Repository-Methoden aufgerufen. Dann sollte für Repositories wie auch bei anderen Services TxType.REQUIRED verwendet werden.
  • Die weiteren Modi TxType.NOT_SUPPORTED, TxType.SUPPORTS und TxType.NEVER sind i. A. unbrauchbar.

Danke für’s Lesen und bis bald – vielleicht auch in einem unserer Trainings in Berlin, Bielefeld, Köln oder bei Ihnen!
https://gedoplan-it-training.de/

Alles gesund? Health checking mit MicroProfile Health

Im Bereich von Microservices und verteilten Systemen – aber nicht nur dort – ist es wichtig zu wissen, ob ein Service/System ordnungsgemäß läuft oder gestört ist. Im MicroProfile (https://microprofile.io) ist mit MicroProfile Health ein Teil enthalten, der es in Kombination mit CDI sehr einfach macht, Health Checking in EE-Anwendungen zu integrieren.

Health Check Callbacks

Die Idee von MicroProfile Health ist, dass Anwendungen auf EE-Servern oder auf Basis von MicroProfile-Frameworks ein oder mehrere Methoden zum Prüfen des Gesundheitszustandes enthalten. Der Server sammelt die Zustände bei Bedarf ein und aggregiert daraus einen Gesamtzustand, der auf dem Rest-Endpoint /health veröffentlicht wird:

GET /health

200 OK
{
  "outcome": "UP",
  "checks": [{
    "name": "Service1",
    "state": "UP",
    "data": {
      "memory": 180672240
    }
  }, {
    "name": "Service2",
    "state": "UP"
  }]
}

Die Callback-Methoden heißen – etwas uninspiriert – call und stammen aus dem Interface org.eclipse.microprofile.health.HealthCheck. Der Server sucht sich automatisch alle Klassen zusammen, die dieses Interface implementieren und mit dem CDI-Qualifier org.eclipse.microprofile.health.Health versehen sind:

@ApplicationScoped
@Health
public class HealthCheck1 implements HealthCheck {

  @Override
  public HealthCheckResponse call() {
    ...

Das Prüfergebnis können die Methoden bequem mittels Builder-Pattern zusammensetzen:

  public HealthCheckResponse call() {
    return HealthCheckResponse
        .named("Service1")
        .up()
        .withData("memory", Runtime.getRuntime().freeMemory())
        .build();

Neben up gibt es auch down sowie die Methode status, der der Gesundheitszustand als Parameter übergeben wird.

Gesamtgesundheit

Bei einem GET-Request auf den Pfad /health werden alle verfügbaren call-Methoden aus allen Anwendungen des Servers aufgerufen und zu einem Gesamtzustand kombiniert. Liefern alle Checks UP, ist das Attribut outcome im Gesamtergebnis ebenfalls UP und der Response hat den Status 200 OK. Andernfalls wird der Response mit 503 Service unavailable ausgeliefert und outcome ist darin DOWN.

Plattformen

MicroProfile Health wird u. a. von folgenden JEE-Servern unterstützt:

  • OpenLiberty (mit aktiviertem Feature mpHealth-1.0).
  • Payara.
  • WildFly (Achtung: WildFly hat unterschiedliche Ports für Applikations- und Management-Zugriffe, im Default 8080 und 9990. Der o. a. REST-Endpoint /health steht über den Management-Port zur Verfügung).

Die genannten Klassen befinden sich bspw. in der Maven-Dependency org.eclipse.microprofile:microprofile.

Demo

In https://github.com/GEDOPLAN/health-demo finden Sie ein Beispielprojekt mit zwei Health Checks, deren Ergebnis über eine Webseite beeinflusst werden kann. Die Anwendung kann als WAR-File auf einen der genannten Server deployt werden. Alternativ können über vorkonfigurierte Maven-Profile Docker-Images zum direkten Ausprobieren erstellt werden.

Ausblick

Im Beispiel wird als Zusatzinformation die Menge freien Speichers hinzugefügt, was im Kontext von Health Checking nicht grundsätzlich falsch ist, aber doch eher eine Metrik darstellt. Für deren Veröffentlichung hält MicroProfile eine weitere Teilspezifikation bereit: MicroProfile Metrics. Sie wird Gegenstand eines der nächsten Blog Posts sein – stay tuned!

Bis bald – vielleicht auch in einem unserer Trainings in Berlin, Bielefeld, Köln oder bei Ihnen!
https://gedoplan-it-training.de/

Schlanke JEE-Services mit Apache Meecrowave

Das Programmmodell von JEE (aka Java EE / Jakarta EE) ermöglicht schon seit vielen Jahren – namentlich seit der Version 5 – eine effiziente Entwicklung von schlanken Geschäftsanwendungen. Als Ablaufumgebungen stehen ausgereifte und leistungsfähige JEE-Server wie WildFly oder Open Liberty zur Verfügung, die als eine Art Allrounder den Anwendungen recht umfassende Infrastruktur anbieten und sogar mehrere Anwendungen gleichzeitig betreiben können.

Gerade der letzte Punkt, der Parallelbetrieb mehrere Anwendungen, wird allerdings nur selten genutzt, um Störeffekte zwischen Anwendungen zu minimieren. Es gibt also typischerweise genau eine Anwendung pro Server, der ggf. sogar selbst in einem dedizierten Rechner – meist einer virtuelle Maschine – läuft.

Wenn man nun noch einen nur eingeschränkten Teil der angebotenen Infrastruktur benötigt, bspw. JPA, CDI und JAX-RS, also den klassischen Microservice-Stack, kann man sich die Frage stellen, ob tatsächlich ein kompletter JEE-Server gebraucht wird, oder ob man nicht einfach die benötigten Dienste in die Anwendung einbetten könnte.

An dieser Stelle setzt Apache Meecrowave an. Dieses Apache-Projekt verknüpft den JPA-Provider EclipseLink, den CDI-Container OpenWebBeans und die REST-Implementierung CXF zu einem ganz schlanken Server – oder eigentlich zu einer Server-Bibliothek, mit deren Hilfe man den Server einfach als Main-Programm startet.

Zur Einbindung von Meecrowave reicht es aus, die folgende Dependency in den Classpath zu holen:

  
    org.apache.meecrowave
    meecrowave-core
    1.2.3
  

Der in der Anwendung eingebettete Server wird dann z. B. so gestartet:

  public static void main(String[] args) {
    try (Meecrowave meecrowave = new Meecrowave().bake()) {
      // Do work here ...
    }

Beim Eintritt in den try-Block wird der Server gestartet, beim Verlassen wieder gestoppt. Sämtliche aus CDI bekannte Mechanismen für den Bootstrap einer Anwendung können zur Aktivierung von Services etc. genutzt werden, z. B. Observer für den Container Lifecycle:

  void startSomething(@Observes @Initialized(ApplicationScoped.class) Object obj) {
    // Gets called on server start ...
  }

Ein einfacher REST-Service ist dann nur noch ein Ding von wenigen Zeilen:

@Path("hello")
@ApplicationScoped
public class HelloResource {

  @GET
  @Produces(MediaType.TEXT_PLAIN)
  public String getHello() {
    return "Hello!";
  }
}

So ist also dieser – zugegebenermaßen winzige – Microservice mit nur ganz wenig Code schon fertig. Und beeindruckt mit Startzeiten im Sekundenbruchteil-Bereich sowie einem Memory Footprint von nur ca. 12 MB.

Ein einfaches Demoprojekt kann von GitHub heruntergeladen werden: https://github.com/GEDOPLAN/meecrowave-demo.

Bis bald – vielleicht in einem unserer Trainings in Berlin, Bielefeld, Köln oder bei Ihnen!
http://gedoplan-it-training.de/

Using GlassFish / Payara 5 with Eclipse Oxygen

If you want to try GlassFish or Payara 5 with one of the current Eclipse versions (Oxygen, which includes JBoss Developer Studio), you run into the problem that the GlassFish Tools plugin checks the GlassFish version and refuses to work with the current release.

As a workaround edit the manifest of glassfish-api.jar located in the modules directory of your GlassFish installation and change the Bundle-Version to 4.0.0.

After this modification you can connect GlassFish 5 to Eclipse via GlassFish Tools, run the server and deploy applications as usual.

See you in our Java EE trainings in Berlin, Bielefeld or at your site: gedoplan-it-training.de/