Nebenbuhler

Erste Schritte mit Quarkus und MicroProfile

Thilo Frotscher

© Shutterytock / Just dance

Quarkus hat aus unterschiedlichen Gründen große Aufmerksamkeit auf sich gezogen. Es verbindet technologische Innovation und spannende Features mit hoher Produktivität für Entwickler. Gleichzeitig bietet es weitreichende Kompatibilität mit gängigen Lösungen, die Entwicklern seit Langem vertraut sind. Insbesondere bietet Quarkus die Möglichkeit, zeitgemäße Anwendungen für den Betrieb in der Cloud auf Basis von JAX-RS, CDI und Hibernate zu entwickeln, ergänzt um die Features des MicroProfile. Somit eröffnet es für Unternehmen mit Java-EE-Historie einen möglichen Pfad in die Zukunft. Wächst hier ein ernstzunehmender Konkurrent für Spring Boot heran?

Bereits seit längerer Zeit diskutieren Entwickler leidenschaftlich darüber, ob Java denn eigentlich gut für die Entwicklung zeitgemäßer Anwendungen und Architekturen aufgestellt ist. Es geht dann in der Regel um Themen wie Microservices, Cloud oder Serverless. Naturgemäß gibt es unterschiedliche Meinungen, jedoch lässt sich anhand verschiedener Kriterien ein klarer Trend ablesen: Als Framework für Neuentwicklungen hat Spring Boot aktuell eindeutig die Nase vorn – und Jakarta EE (früher Java EE) ist ziemlich abgehängt.

Das hat im Wesentlichen zwei Gründe: Erstens wird Jakarta EE vielerorts noch immer mit dem Betrieb eines monolithischen Application-Servers gleichgesetzt, der nun wirklich nicht mehr in moderne IT-Infrastrukturen hineinpasst. Tatsächlich ist es aber längst so, dass auf Basis von Jakarta EE entwickelte Anwendungen als Runnable JARs gebaut und als vergleichsweise leichtgewichtige Prozesse betrieben werden können. Beim Vergleich der Frameworks sollte man sich also eher auf APIs, Features und Produktivität während der Entwicklung konzentrieren.

Dies führt zum zweiten Grund für die Favoritenrolle von Spring Boot: Im Zuge der Übergabe der Java-EE-Plattform von Oracle an die Eclipse Foundation erfolgte über mehrere Jahre praktisch keinerlei technischer Fortschritt mehr an den APIs. Das wird sich zwar hoffentlich in naher Zukunft ändern, der aktuelle Stand gilt aber zu Recht als nicht mehr zeitgemäß und bietet für die genannten Einsatzgebiete in vielen Fällen schlicht zu wenig Unterstützung. Auch in Sachen Produktivität ist Spring Boot enteilt.

Doch auch Spring Boot erfüllt nicht alle Anforderungen zufriedenstellend. So entstehen beim Build vergleichsweise große Artefakte, die dann zu deployen und zu starten sind. Zudem sind die Start-up-Zeiten und der Ressourcenverbrauch zur Laufzeit im Vergleich mit anderen Technologien immer noch recht hoch. All dies führt im Cloud-Betrieb letztlich zu (Mehr-)Kosten, die zu reduzieren im Sinne des Anwendungsbetreibers wäre. Und nicht zuletzt gibt es auch weiterhin zahlreiche Unternehmen, die über viele Jahre hinweg große Investitionen in die Entwicklung und Wartung von Java-EE-Anwendungen getätigt haben. Für sie wäre eine Zukunftsperspektive wünschenswert, wie zumindest existierende Anwendungen auf der gleichen Plattform weiterentwickelt und modernisiert werden können, ohne dass eine Neuentwicklung bedeutender Codeanteile auf Basis eines neuen Frameworks wie Spring Boot notwendig wird.

So haben sich im Windschatten des großen Erfolgs von Spring Boot einige interessante Alternativen entwickelt. Zum einen ist hier das MicroProfile zu nennen. Dabei handelt es sich um eine Reihe von APIs, die als Erweiterung von Jakarta EE dienen sollen und eine ganze Menge von Features implementieren, die man typischerweise für den Einsatz in der Cloud oder in Microservices-Architekturen benötigt. So werden etwa Metriken, Health Checks, JSON Web Tokens, OpenAPI, Open Tracing oder Strategien zur Fehlertoleranz unterstützt. Hier geht es also darum, den aktuellen Rückstand der Jakarta-EE-Plattform wettzumachen. Im Wesentlichen wird vieles kopiert, das Spring Boot bereits seit Längerem bietet. Das ist aber nicht unbedingt negativ zu bewerten, ist es doch besser, andernorts bewährte Konzepte zu übernehmen, als das Rad immer neu zu erfinden. Die Funktionalität der Frameworks wird sich also mit der Zeit zunehmend angleichen. Eine ausführliche Betrachtung des MicroProfile war bereits in [1] zu lesen.

Ein weiterer interessanter Trend ist die Entwicklung zahlreicher neuer (Micro-)Frameworks, die die Entwicklung von Cloud-basierten Anwendungen oder Microservices erleichtern wollen. In diesem Bereich entstehen aktuell viele Ideen und Konzepte. Ein besonders spannender Kandidat ist Quarkus aus dem Hause Red Hat. Es bietet sehr gute Unterstützung für Container und Kubernetes sowie vor allen Dingen die Möglichkeit, eigene Anwendungen oder Services mit Hilfe der GraalVM in ein natives Image zu kompilieren. Damit geht das Konzept des „Write once, run anywhere“ zwar verloren, für den produktiven Betrieb von Anwendungen ist das jedoch im Zeitalter von Docker ohnehin nur noch von geringer Bedeutung. Dafür ergeben sich durch den Einsatz von nativen Images jedoch extrem schnelle Start-up-Zeiten und ein deutlich reduzierter Ressourcenverbrauch, was für den Einsatz in der Cloud ausgesprochen attraktiv ist. Ein weiterer interessanter Aspekt von Quarkus liegt darin, dass es sowohl die wichtigsten Jakarta EE APIs bzw. darauf basierende Frameworks unterstützt (u. a. JAX-RS, CDI und Hibernate) als auch die APIs des MicroProfile. Somit lassen sich auf modernstem technologischem Fundament zeitgemäße Anwendungen auf Basis der bekannten Jakarata EE APIs entwickeln.

Ein interessanter Trend ist die Entwicklung zahlreicher neuer (Micro-)Frameworks, die die Entwicklung von Cloud-basierten Anwendungen oder Microservices erleichtern wollen.

Probieren geht über …

Als Proof of Concept soll mit Quarkus ein kleiner Service implementiert werden, der Zugriff auf Produktdaten im JSON-Format bietet, auf Basis von JAX-RS implementiert ist und gleichzeitig den Einsatz von MicroProfile-Features demonstriert. Während dieser Artikel verfasst wird, liegt Quarkus in Version 1.4.2 vor. Dieses Release unterstützt die JDKs 8 oder 11+ und Apache Maven ab Version 3.6.2. Ist beides installiert, kann es bereits losgehen.

Wie die meisten aktuellen Frameworks legt auch Quarkus sehr großen Wert auf bestmögliche Unterstützung für Entwickler, sodass man bereits mit verhältnismäßig wenig Aufwand zur ersten lauffähigen Anwendung kommt. Und auch anschließend geht es sehr zügig voran. Das zeigt sich erstmalig beim Erzeugen eines Gerüsts für ein neues Projekt. Quarkus bietet zu diesem Zweck ein Maven Plugin an, das für die Beispielanwendung mit der folgenden Befehlszeile gestartet wird:

mvn io.quarkus:quarkus-maven-plugin:1.4.2.Final:create 
  -DprojectGroupId=org.example 
  -DprojectArtifactId=products 
  -DclassName="org.example.api.ProductsResource" 
  -Dpath="/products"

Diese erzeugt im Ordner products ein neues Quarkus-Projekt mit den angegebenen Maven-Group- und Artifact-IDs. Die Klasse ProductsResource wird als JAX-RS-Ressource mit minimaler Funktionalität generiert: Sie beantwortet GET Requests auf den angegebenen URL-Pfad /products mit einer simplen Beispiel-Response im Plaintext-Format. Die Anwendung ist ohne eine Änderung sofort lauffähig: Folgender Befehl startet den Service im Development-Modus. Dabei ist mvnw ein Wrapper für Maven, der ebenfalls von Quarkus im Projektverzeichnis erzeugt wurde:

./mvnw quarkus:dev

Der Service startet auf einem handelsüblichen Entwicklerlaptop in knapp unter einer Sekunde. Die genaue Startzeit ist an dieser Stelle irrelevant – je nach verwendeter Hardware wird es naturgemäß gewisse Unterschiede geben. Entscheidend ist nur die Größenordnung. Wir kommen etwas später darauf zurück. Die bislang vorliegende Basisfunktionalität kann beispielsweise mit Hilfe von curl getestet werden (curl http://localhost:8080/products). Darüber hinaus wurde auch eine Landing-Page generiert, die mit einem Browser unter http://localhost:8080/ erreichbar ist.

Ein Blick auf die Maven-Projektdatei pom.xml fördert einige interessante Details zutage. So ist hier beispielsweise das Quarkus Maven Plugin zu finden, das beim Build für diverse Quarkus-Spezifika verantwortlich ist. Weiterhin ist zu erkennen, dass das Projekt bis hierhin mit dem Artefakt quarkus-resteasy nur eine einzige Abhängigkeit besitzt. Es ist also das RESTEasy Framework aus dem Hause JBoss/Red Hat, das für Quarkus als JAX-RS-Implementierung zum Einsatz kommt.

Für Tests sind als weitere Abhängigkeiten das Artefakt quarkus-junit5 und das bekannte REST-Assured Framework in der Projektdatei hinterlegt. Ein Blick in den Source Code des Projekts fördert neben der Klasse ProductsResource auch zwei Testklassen zutage, die ebenfalls generiert wurden. ProductsResourceTest testet die Ressource mit Hilfe von REST-Assured und der JVM-Version von Quarkus. Dieser Test wird vom Maven Surefire Plugin ausgeführt. NativeProductsResourceIT ist von ProductsResourceTest abgeleitet und führt die gleichen Tests aus, allerdings gegen ein natives Image der Anwendung. Hierfür sorgt die Annotation @ NativeImageTest. Die Tests des nativen Image werden vom Maven Failsage Plugin ausgeführt.

Als Nächstes soll die Ressource so erweitert werden, dass sie GET Requests im JSON-Format beantwortet. Hierzu ist lediglich die Annotation @Produces entsprechend anzupassen. Zudem soll die Ressource eine Liste von Produktnamen zurückliefern. Die Klasse wird also verändert, wie in Listing 1 gezeigt.

@Path("/products")
public class ProductsResource {
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public List<String> getProducts() {
    return List.of("Product A", "Product B", "Product C", "Product D");
  }
}

An diesem Punkt ist wichtig zu erwähnen, dass nach erfolgter Codeänderung die im vorherigen Schritt bereits gestartete Anwendung nicht erneut gestartet werden muss. Sie läuft im Development-Modus, sodass Codeänderungen mittels Hot Deployment direkt in Betrieb genommen werden. Die Änderungen können somit durch erneutes Ausführen des curl-Kommandos sofort getestet werden. Mit Hilfe dieses Features kommt man bei der Entwicklung sehr schnell voran. Spring Boot bietet Vergleichbares mit den Dev-Tools.

Wie sich zeigt, tritt nun ein Fehler auf. Die von der Ressource zurückgelieferte Stringliste kann nicht in JSON umgewandelt werden, da die Anwendung bislang noch keine JSON-Unterstützung enthält. Das lässt sich jedoch sehr leicht ändern. In der Projektdatei pom.xml ist hierzu die Abhängigkeit quarkus-resteasy in quarkus-resteasy-jsonb zu ändern. Dies aktiviert die Unterstützung für JSON-Binding (JSON-B, JSR-367). Anschließend lässt sich (erneut ohne Neustart) mit curl feststellen, dass die Ressource nun ein JSON-Array mit den Produktnamen zurückliefert.

Schließlich soll noch Injection mittels CDI demonstriert werden. Hierzu wird die Erzeugung der Liste von Produktnamen in eine Klasse namens ProductsService verlagert, die mittels @Inject in die Ressource injiziert wird (Listing 2).

@ApplicationScoped
public class ProductsService {
  public List<String> getProductNames() {
    return List.of("Product A", "Product B", "Product C", "Product D");
  }
}
 
@Path("/products")
public class ProductsResource {
  @Inject
  ProductsService productsService;
 
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  public List<String> getProducts() {
    return productsService.getProductNames();
  }
}

Mit Hilfe von curl kann wieder getestet werden, dass das Injizieren des Service wie erwartet funktioniert. Dennoch ist zu beachten, dass die Unterstützung von Quarkus für Dependency Injection zwar auf CDI 2.0 basiert, es jedoch nicht vollständig implementiert. Vielmehr wird nur eine Teilmenge der Spezifikation unterstützt. Zu den nicht unterstützten Bestandteilen von CDI zählen unter anderem Decorators, Specialization, Conversation Scope oder die Deskriptordatei beans.xml. Der überwiegende Teil existierenden Anwendungscodes sollte aber auch unter Quarkus lauffähig sein. Auch für den Fall, dass native Images gebaut werden sollen, sind hinsichtlich CDI einige Besonderheiten zu beachten. Nähere Informationen liefert die Dokumentation von Quarkus.

MicroProfile einbinden

Bis hierher wurde der Anwendungscode ausschließlich auf Basis von Jakarta EE APIs erstellt. Entwickler, die bislang vor allem auf Basis dieser Plattform entwickelt haben, dürften sich also heimisch fühlen. Nun sollen einige Features von MicroProfile hinzukommen. Quarkus 1.4.2 unterstützt MicroProfile 3.3.

Im ersten Schritt wird die Unterstützung für OpenAPI aktiviert. Hierzu ist in der Projektdatei pom.xml lediglich eine neue Abhängigkeit hinzuzufügen. Anhand der Artifact-ID wird deutlich, dass Quarkus die SmallRye-Implementierung des MicroProfile einsetzt.

<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>

Mittels curl http://localhost:8080/openapi lässt sich dann bereits eine automatisch generierte OpenAPI-Beschreibung des Produkt-Service abfragen. Diese ist noch sehr rudimentär, da auch die Implementierung des Service bislang sehr einfach gehalten ist. Durch eine Weiterentwicklung des Service, beispielsweise die Implementierung von DTO-Klassen, die für die Responses verwendet werden, würde auch die generierte OpenAPI-Beschreibung automatisch mitwachsen. Daneben bietet das MicroProfile jedoch auch die Möglichkeit, den Anwendungscode mit speziellen Annotationen anzureichern, die den Inhalt der generierten OpenAPI-Beschreibung beeinflussen. So könnten der Methode getProducts() beispielsweise die Annotationen @Operation und @APIResponse hinzugefügt werden:

@GET
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Returns a list of product names")
@APIResponse(responseCode = "200", description = "Success")
public List<String> getProducts() {
  return productsService.getProductNames();
}

Ebenso könnte eine JAX-RS-Application-Klasse erstellt werden, die mit weiteren OpenAPI-Annotationen angereichert ist (Listing 3).

@OpenAPIDefinition(
  info = @Info(
    title="Products API",
    version = "0.0.1",
    contact = @Contact(
      name = "Products API Support",
      url = "http://my-company.com/contact",
      email = "support@my-company.com"),
    license = @License(
      name = "Apache 2.0",
      url = "http://www.apache.org/licenses/LICENSE-2.0.html"))
)
public class ExampleApiApplication extends Application {}

Auch das Hinterlegen einer statischen OpenAPI-Beschreibungsdatei ist mit dem MicroProfile möglich, weitere Details hierzu finden sich in der Entwicklerdokumentation. Unabhängig davon, mit welcher Strategie die OpenAPI-Beschreibung erstellt wird, steht zusätzlich eine auf SwaggerUI basierende HTML-Dokumentation des Service zur Verfügung. Sie kann mit einem Browser unter http://localhost:8080/swagger-ui angesteuert werden.

Als zweites MicroProfile-Feature soll die Verwendung von Health Checks demonstriert werden. Health Checks dienen dazu, den Zustand eines Rechnerknotens von einem anderen Rechner aus zu überprüfen. Ein Haupteinsatzgebiet hierfür sind Cloud-Infrastrukturen und Kubernetes. Health Checks können dort etwa verwendet werden, um zu entscheiden, ob ein Rechnerknoten beendet bzw. heruntergefahren ist und durch einen neuen Knoten ersetzt werden muss. Für eine Unterstützung von Health Checks wird in der Datei pom.xml einfach wieder eine neue Abhängigkeit hinzugefügt:

<dependency>
  <groupId>io.quarkus</groupId>
  <artifactId>quarkus-smallrye-health</artifactId>
</dependency>

Unter http://localhost:8080/health lässt sich fortan der aktuelle Zustand der Anwendung einsehen. Da bislang keine Health Checks implementiert wurden, die fehlschlagen könnten, hat die Anwendung folglich den Gesamtstatus UP.

{
  "status": "UP",
  "checks": [ ]
}

Die Quarkus-Dokumentation erläutert die Verwendung von MicroProfile Health recht anschaulich anhand der Beispielklasse DatabaseConnectionHealthCheck, die implementiert ist, wie in Listing 4 gezeigt.

@Readiness
@ApplicationScoped
public class DatabaseConnectionHealthCheck implements HealthCheck {
 
  @ConfigProperty(name = "database.up", defaultValue = "false")
  private boolean databaseUp;
 
  @Override
  public HealthCheckResponse call() {
 
    HealthCheckResponseBuilder responseBuilder = 
      HealthCheckResponse.named("Database connection health check");
 
    try {
      simulateDatabaseConnectionVerification();
      responseBuilder.up();
 
    } catch (IllegalStateException e) {
      // cannot access the database
      responseBuilder.down();
    }
 
    return responseBuilder.build();
  }
 
  private void simulateDatabaseConnectionVerification() {
    if (!databaseUp) {
      throw new IllegalStateException("Cannot contact database");
    }
  }
}

Die Klasse implementiert das vom MicroProfile spezifizierte Interface HealthCheck, das die Methode call() definiert. In der beispielhaften Implementierung wird ein Verbindungscheck mit einer imaginären Datenbank simuliert. Tatsächlich wird aber nur der Konfigurationsparameter database.up ausgewertet. Solange er nicht den Wert true besitzt, schlägt der Verbindungscheck fehl und es wird eine entsprechende HealthCheckResponse mit dem Status down erzeugt. Im positiven Fall transportiert die Response hingegen den Status up. Der aktuelle Wert des Konfigurationsparameters wird mittels eines weiteren Features des MicroProfile bereitgestellt, und zwar mit dem Config API. Dieses ermöglicht es, Konfigurationswerte mit der Annotation @ConfigProperty direkt in eine Anwendungsklasse zu injizieren und dabei gegebenenfalls auch Defaultwerte anzugeben (in diesem Fall false), falls der Konfigurationsparameter nicht gefunden werden konnte.

MicroProfile Health unterscheidet zwischen zwei unterschiedlichen Arten von Health Checks. Die sogenannten Liveness Checks sollen Auskunft darüber geben, ob eine Anwendung grundsätzlich läuft. Readiness Checks hingegen zeigen an, ob die Anwendung auch bereit ist, eingehende Requests zu verarbeiten oder nicht. Im Fall einer vorübergehend fehlschlagenden Datenbankverbindung würde also beispielsweise ein Liveness Check positiv ausfallen, ein Readiness Check aber negativ. Die Beispielklasse ist mit der Annotation @Readiness versehen, es handelt sich also um einen Readiness Check.

Nach dem Hinzufügen von DatabaseConnectionHealthCheck zur Beispielanwendung liefert der Endpunkt http://localhost:8080/health nun einen anderen Status. Der Gesamtstatus ist jetzt DOWN, da der Konfigurationsparameter database.up bislang nicht existiert und somit der implementierte Defaultwert gilt. Das JSON-Array checks enthält nun das Ergebnis der Datenbankverbindungsprüfung. So können einer Anwendung beliebig viele Health Checks hinzugefügt werden.

Der fehlende Konfigurationsparameter kann auf unterschiedliche Weise gesetzt werden. MicroProfile Config definiert verschiedene Konfigurationsquellen, wie Umgebungsvariablen, System Properties oder eine innerhalb der Anwendung befindliche Konfigurationsdatei. Im Fall von Quarkus hat sie den Namen application.properties und wurde ebenfalls bereits zu Beginn generiert. Wird beispielsweise dort der fehlende Parameter eingetragen (database.up = true), liefert der Health-Check-Endpunkt anschließend den Gesamtstatus UP.

Mit Quarkus buhlt ein ungeheuer spannendes Framework um die Gunst der Entwickler. Obwohl es noch relativ jung ist, erscheint es dennoch bereits ziemlich ausgereift.

Native Images

Auf Basis des jetzigen Stands kann der Service nun Schritt für Schritt weiter ausgebaut werden. Insbesondere das MicroProfile bietet hierzu vielfältige Möglichkeiten zum Experimentieren. So können etwa unterschiedliche Metriken eingebaut, die Anwendung mit Hilfe des Fault Tolerance API widerstandsfähiger gemacht oder Unterstützung für JSON Web Tokens hinzugefügt werden. Aber auch die vielfältigen anderen von Quarkus unterstützten Standards und Frameworks laden zum Erweitern der Beispielanwendung ein.

Zum Abschluss soll jedoch noch eines der spannendsten Features von Quarkus demonstriert werden: die Kompilierung des Service in ein ausführbares natives Image. Hierfür ist wie eingangs erwähnt die GraalVM zuständig, die gegebenenfalls zu installieren wäre. Aber weshalb installieren, wenn es doch Container gibt? So bietet Quarkus die Möglichkeit, den Compile-Vorgang in einen Container auszulagern, in dem die GraalVM bereits maßgeschneidert vorinstalliert wurde. Voraussetzung hierfür wäre dann natürlich eine existierende Installation von Docker auf dem Rechner, auf dem der Build ausgeführt wird. Die Erzeugung eines nativen Image innerhalb eines Containers erledigt dann der folgende Befehl:

./mvnw package -Pnative -Dquarkus.native.container-build=true

Anschließend liegt der Product Service als lauffähige Binäranwendung im Ordner target und kann wie folgt gestartet werden:

./target/products-1.0-SNAPSHOT-runner

Interessant ist nun ein Vergleich mit der zuvor gemessenen Startzeit. Die native Anwendung startet auf dem Laptop des Autors in weniger als 50 ms, also etwa um den Faktor 20 schneller als die JVM-Variante. Zudem ist die Anwendung mit etwa 30 MB erfreulich klein. Ein erheblicher Unterschied zu einer Spring-Boot-Anwendung plus zugehöriger Java-Laufzeitumgebung. Allerdings muss fairerweise erwähnt werden, dass sich unter bestimmten Voraussetzungen und mit einigem Aufwand auch eine Spring-Boot-Anwendung mittels GraalVM in eine native Anwendung überführen lässt.

Das ausführbare native Image kann im letzten Schritt auf einfache Weise in einen Docker-Container gepackt werden. Das hierfür notwendige Dockerfile wurde unter dem Dateinamen Dockerfile.native ebenfalls beim initialen Generieren des Projektgerüsts erzeugt und befindet sich im Ordner src/main/docker. Die folgenden Befehle erzeugen mit dessen Hilfe einen Docker-Container, der die Beispielanwendung enthält. Als Basis für den Container dient ein Universal Base Image, das von Quarkus bereitgestellt wird.

docker build -f src/main/docker/Dockerfile.native
  -t jm-quarkus/product-service.
docker run -i --rm -p 8080:8080 jm-quarkus/product-service

Fazit

Mit Quarkus buhlt ein ungeheuer spannendes Framework um die Gunst der Entwickler. Obwohl es noch relativ jung ist, erscheint es dennoch bereits ziemlich ausgereift. Entwickler mit Vorkenntnissen in den üblichen Jakarta EE APIs wie JAX-RS, CDI und JPA können bereits nach sehr kurzer Einarbeitungszeit lauffähige Services entwickeln, die auf modernstem technischen Stand sind und mit der alten Java-EE-Welt nur noch die (weiterhin rückwärtskompatiblen) APIs gemein haben. In Kombination mit den neuen Möglichkeiten, die das MicroProfile bietet, ist hier eine sehr ernstzunehmende Konkurrenz zu Spring Boot entstanden. Für neue Projekte muss Spring Boot daher keinesfalls mehr (quasi automatisch) als Technologie gesetzt sein. Auch für bisherige Spring-Anwender lohnt sich ein Blick auf Quarkus durchaus. Zum aktuellen Zeitpunkt werden Spring DI, Spring Web und Spring Data JPA unterstützt. Man darf gespannt sein, wie es auch an dieser Stelle mit Quarkus weitergeht.

Geschrieben von
Thilo Frotscher
Thilo Frotscher
Thilo Frotscher arbeitet als freiberuflicher Softwarearchitekt und Trainer. Seine technischen Schwerpunkte sind die Java-Plattform sowie der Themenbereich Services und Systemintegration. Er unterstützt Unternehmen durch die Mitarbeit in Entwicklungsprojekten und die Durchführung praxisnaher Schulungen.
Kommentare

Hinterlasse einen Kommentar

avatar
4000
  Subscribe  
Benachrichtige mich zu: