JEE-Microservices mit Quarkus - eine Einführung
25.11.2019
Dirk Weil, GEDOPLAN GmbH
Dirk Weil
GEDOPLAN GmbH, Bielefeld
GEDOPLAN IT Consulting
Consulting, coaching, concepts, reviews, development
GEDOPLAN IT Training & partner
Java, JEE, tools trainings
Berlin, Frankfurt, Bielefeld, Köln, on-site
JEE since 1998
Speaker and author
JEE-Microservices mit Quarkus - eine Einführung 2gedoplan.de
Java EE  Jakarta EE
2017:
Projekt EE4J (Eclipse Enterprise for Java)
Produktname Jakarta EE
Oracle behält Namens- und Urheberrechte
Java EE
Paketnamen javax.*
Jakarta EE 8
codegleich zu Java EE 8
Release 10.09.2019
JEE-Microservices mit Quarkus - eine Einführung 3
JEE
gedoplan.de
MicroProfile
microprofile.io
„Next step of Java EE / Jakarta EE evolution“
„… optimize Enterprise Java for a microservices architecture …“
JEE-Microservices mit Quarkus - eine Einführung 4gedoplan.de
Config
1.3
Fault Tolerance
2.0
Health
2.0
JWT Authentication
1.1
Metrics
2.0.0
OpenAPI
1.1
OpenTracing
1.3
Rest Client
1.3
CDI
2.0
JAX-RS
2.1
JSON-B
1.0
JSON-P
1.1
MicroProfile Runtimes: Klassische Application Server
5
Anwendungsklassen
Konfigurationsfiles
(Deployment Descriptors,
Properties, …)
JEE Server
CDI Runtime
JPA Runtime
REST Runtime
Technische Konfiguration *
JRE
build deploy
run
* DB-Verbindungen,
Messaging
Security
…
Thin WAR
klein
groß
gedoplan.deJEE-Microservices mit Quarkus - eine Einführung
MicroProfile Runtimes: „Micro“ Frameworks
6
Anwendungsklassen
Konfigurationsfiles *
CDI Runtime
JPA Runtime
REST Runtime
JRE
build
run
* Anwendungsparameter,
DB-Verbindungen,
Messaging
Security
…
Fat JAR
JAR + Dependencies
groß
gedoplan.deJEE-Microservices mit Quarkus - eine Einführung
Workshop-Projekt
Source
github.com/GEDOPLAN/quarkus-workshop
Branches:
master
Demos, Skripte, Kopiervorlagen, …
jvmcon2019
basiert auf master
wird während des Workshops sukzessive aufgebaut
Tooling
JDK 8+ (z. B. adoptopenjdk.net)
Maven 3 (maven.apache.org/download.cgi)
Git Client (git-scm.com/downloads)
curl (curl.haxx.se/download.html)
JEE-Microservices mit Quarkus - eine Einführung 7gedoplan.de
Quarkus
Red Hats Antwort auf Spring Boot
Designierter Nachfolger von Thorntail (aka WildFly Swarm)
Optimiert für kurze Startzeiten
Hotspot und GraalVM
https://quarkus.io/
JEE-Microservices mit Quarkus - eine Einführung 8gedoplan.de
Quarkus
Core
+ Extensions
(= Maven Dependencies)
Project Bootstrap mit
Maven Plugin
(oder Gradle)
 quarkus.io/guides/maven-tooling.html
JEE-Microservices mit Quarkus - eine Einführung 9gedoplan.de
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
mvn io.quarkus:quarkus-maven-plugin:1.0.0.CR1:create 
-DprojectGroupId=… 
-DprojectArtifactId=… 
-B
Quarkus
Maven-Plugin für Build
Thin jar target/quarkus-getting-started-runner.jar
Dependencies in target/lib/
Anwendungsstart
java –jar target/quarkus-getting-started-runner.jar
JEE-Microservices mit Quarkus - eine Einführung 10gedoplan.de
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<goals><goal>build</goal></goals>
</execution>
Quarkus
Development mode
Hot reload
bei REST/Web-Request
falls Quellcodeänderung
JEE-Microservices mit Quarkus - eine Einführung 11gedoplan.de
$ mvn quarkus:dev
Listening for transport dt_socket at address: 5005
17:54:50,319 INFO [io.qua.dep.QuarkusAugmentor] (main) Beginning quarkus au
17:54:50,949 INFO [io.qua.resteasy] (build-1) Resteasy running without serv
17:54:50,949 INFO [io.qua.resteasy] (build-1) - Add quarkus-undertow to run
17:54:50,980 INFO [io.qua.dep.QuarkusAugmentor] (main) Quarkus augmentation
17:54:52,452 INFO [io.quarkus] (main) Quarkus 0.26.1 started in 2.320s. Lis
17:54:52,452 INFO [io.quarkus] (main) Profile dev activated. Live Coding ac
17:54:52,454 INFO [io.quarkus] (main) Installed features: [cdi, resteasy]
Quarkus
Configuration
application.properties
Properties quarkus.… für Quarkus
quarkus.io/guides/config
quarkus.io/guides/all-config
Weitere Properties für Anwendung (MicroProfile Config)
Configuration Profiles %prod, %dev, %test
JEE-Microservices mit Quarkus - eine Einführung 12gedoplan.de
# Ports
quarkus.http.port=8080
# Logging
quarkus.log.console.format=%d{HH:mm:ss,SSS} %-6p [%c{1.}] (%t) %s%e%n
quarkus.log.console.color=false
quarkus.log.level=INFO
quarkus.log.category."some.logger.name".level=WARN
%dev.quarkus.log.category."some.logger.name".level=FINE
Demo: getting-started
Bootstrap
Start
JEE-Microservices mit Quarkus - eine Einführung 13gedoplan.de
mvn io.quarkus:quarkus-maven-plugin:1.0.0.CR1:create 
-DprojectGroupId=jvmcon 
-DprojectArtifactId=getting-started 
-DclassName="jvmcon.GreetingResource" 
-B
getting-started-bootstrap.sh
cd getting-started
mvn compile quarkus:dev
Kleiner Ausflug: JAX-RS
Klasse mit @Path definiert Rest Endpoints
Methoden mit @GET, @PUT, @POST, @DELETE
@Path kann auf Methoden ergänzend genutzt werden
Pfade dürfen Templates enthalten
@Produces und @Consumes bestimmen (De-)Serialisierung
Parameter können aus URL übernommen werden
siehe Klasse GreetingResource (nach Bootstrap ergänzt)
Beispiel-Aufrufe mittels curl
siehe getting-started-curl.txt
JEE-Microservices mit Quarkus - eine Einführung 14gedoplan.de
Übungs-Domäne
Skipass-Verwaltung und Nutzung
1. Schritt: skipass-manager
mit POST-Endpoint zur Erzeugung von Skipässen
JEE-Microservices mit Quarkus - eine Einführung 15gedoplan.de
skipass-manager
• POST /skipass?validTo=2019-12-14T18:00
Erzeugen eines Skipasses (id = UUID)
• GET /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/validTo
Abfrage der Gültigkeit (Ende-Timestamp oder Ungültig-Wert)
• PUT /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/blocked
Sperren oder Freigeben eines Skipasses
• …
DB
skipass-gate
• GET /gate/2a910ff2-b92a-477f-861d-36fdf2c3c249
Einlass-Prüfung (GREEN/RED)
Übungs-Domäne
1. Schritt: skipass-manager
mit POST-Endpoint zur Erzeugung von Skipässen
(Project Bootstrap, JAX-RS)
JEE-Microservices mit Quarkus - eine Einführung 16gedoplan.de
skipass-manager
• POST /skipass?validTo=2019-12-14T18:00
Erzeugen eines Skipasses (id = UUID)
• GET /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/validTo
Abfrage der Gültigkeit (Ende-Timestamp oder Ungültig-Wert)
• PUT /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/blocked
Sperren oder Freigeben eines Skipasses
• …
DB skipass-gate
• GET /gate/2a910ff2-b92a-477f-861d-36fdf2c3c249
Einlass-Prüfung (GREEN/RED)
Übung 1: Bootstrap skipass-manager
1. Erzeugen Sie das Quarkus-Projekt skipass-manager
2. Ergänzen Sie die Entity SkiPass
• Kopiervorlage: skipass.txt
• Paket, Getter, Setter, toString nach Gusto
JEE-Microservices mit Quarkus - eine Einführung 17gedoplan.de
mvn io.quarkus:quarkus-maven-plugin:1.0.0.CR1:create 
-DprojectGroupId=jvmcon 
-DprojectArtifactId=skipass-manager 
-B
public class SkiPass {
private String id;
private LocalDateTime validFrom;
private LocalDateTime validTo;
private boolean blocked;
Übung 1: Bootstrap skipass-manager
3. Ergänzen Sie die Rest-Resource SkiPassResource
• @Path("skipass")
• Methode für Skipass-Anlage
• @POST
• @Produces(MediaType.TEXT_PLAIN)
• Parameter
• @QueryParam("validTo") LocalDateTime validTo
• @QueryParam("validFrom") LocalDateTime validFrom
• neues SkiPass-Objekt instanziieren und seine Id als Returnwert liefern
4. Anwendung starten
5. Rest-Call ausprobieren
JEE-Microservices mit Quarkus - eine Einführung 18gedoplan.de
curl -X POST -i http://localhost:8080/skipass?validTo=2019-12-24T23:59
mvn compile quarkus:dev
Übungs-Domäne
2. Schritt: Skipässe persistent ablegen
(JPA, CDI, JSON-B)
Validierungslogik
JEE-Microservices mit Quarkus - eine Einführung 19gedoplan.de
skipass-manager
• POST /skipass?validTo=2019-12-14T18:00
Erzeugen eines Skipasses (id = UUID)
• GET /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/validTo
Abfrage der Gültigkeit (Ende-Timestamp oder Ungültig-Wert)
• PUT /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/blocked
Sperren oder Freigeben eines Skipasses
• …
DB skipass-gate
• GET /gate/2a910ff2-b92a-477f-861d-36fdf2c3c249
Einlass-Prüfung (GREEN/RED)
Kleiner Ausflug: CDI
Anwendungen / Geschäftslogik besteht aus vielen Services
die einander benutzen / referenzieren
deren Daten unterschiedlich lang benötigt werden
(gesamte Laufzeit, einzelner Request, …)
JEE-Microservices mit Quarkus - eine Einführung 20gedoplan.de
Application
Use Case
Domain Data
Service
Domain Data
Service
Data Repository
Data Repository Data Repository
Page / View Endpoint
TX
JPA
Mail
JMS
Kleiner Ausflug: CDI
Definition von Beans (=Services)
und Zuordnung zu Scopes (=Lebensdauer)
Verknüpfung untereinander
mittels Injektion
Descriptor META-INF/beans.xml
für Quarkus optional
Inhalt wird von Quarkus (derzeit?) nicht genutzt
JEE-Microservices mit Quarkus - eine Einführung 21gedoplan.de
@ApplicationScoped
public class PersonRepository {
@ApplicationScoped
@Path("person")
public class PersonResource {
@Inject
PersonRepository personRepository;
Kleiner Ausflug: CDI
Interceptors z. B. für Transaktionssteuerung
Weitere Features (hier nicht benötigt):
Qualifier
Alternatives
Producer
Events
JEE-Microservices mit Quarkus - eine Einführung 22gedoplan.de
@ApplicationScoped
@Transactional(rollbackOn = Exception.class)
public class PersonRepository {
@Inject
EntityManager entityManager;
public void persist(Person entity) {
this.entityManager.persist(entity);
Kleiner Ausflug: JPA
Aufgabenstellung:
Speichern und Laden von
Java-Objekten
Mapping OO  RDBMS
Entities (=persistente Objekte)
sind POJOs
nicht final
No-args constructor
@Entity
@Id
Diskussion über Ids, Generatoren, equals, hashCode siehe
javaeeblog.wordpress.com/2017/11/15/
identity-and-equality-of-jpa-entities/
JEE-Microservices mit Quarkus - eine Einführung 23gedoplan.de
@Entity
public class Person {
@Id
@GeneratedValue(strategy = …)
private Integer id;
private String name;
private String firstname;
protected Person() {
}
Kleiner Ausflug: JPA
EntityManager = API für CRUD, Queries, …
JEE-Microservices mit Quarkus - eine Einführung 24gedoplan.de
public class PersonRepository {
@Inject
EntityManager entityManager;
public Person findById(Integer id) {
return this.entityManager.find(Person.class, id);
}
public List<Person> findAll() {
return this.entityManager
.createQuery("select x from Person x", Person.class)
.getResultList();
}
public void persist(Person entity) {
this.entityManager.persist(entity);
JPA in Quarkus
Extensions für Hibernate und DB-Treiber
Konfiguration der Datasource(s)
META-INF/persistence.xml optional
JEE-Microservices mit Quarkus - eine Einführung 25gedoplan.de
mvn quarkus:add-extensions –Dextensions=quarkus-hibernate-orm,quarkus-jdbc-h2
# Datasource
quarkus.datasource.url=jdbc:h2:mem:test;…
quarkus.datasource.driver=org.h2.Driver
quarkus.datasource.username=showcase
quarkus.datasource.password=showcase
quarkus.hibernate-orm.database.generation=update
quarkus.datasource.hugo.url=jdbc:…
application.properties
Kleiner Ausflug: JSON-B
(De-)Serialisierung POJO  JSON
Automatische Nutzung in JAX-RS
Mediatype application/json
Quarkus-Extension quarkus-resteasy-jsonb
(statt quarkus-resteasy)
JEE-Microservices mit Quarkus - eine Einführung 26gedoplan.de
Person person = new Person("Wacker", "Willi");
Jsonb jsonb = JsonbBuilder.create();
String personJson = jsonb.toJson(person);
Übung 2a: Persistenz in skipass-manager
1. Ergänzen Sie die für JPA nötigen Extensions
2. Konfigurieren Sie die Datasource
3. Machen Sie die Entity SkiPass JPA-fähig
• @Entity, @Id
• No-args constructor
JEE-Microservices mit Quarkus - eine Einführung 27gedoplan.de
mvn quarkus:add-extensions 
–Dextensions=quarkus-hibernate-orm,quarkus-jdbc-h2
# Datasource
quarkus.datasource.url=jdbc:h2:~/h2/jvmcon;AUTO_SERVER=TRUE
quarkus.datasource.driver=org.h2.Driver
quarkus.datasource.username=jvmcon
quarkus.datasource.password=jvmcon
quarkus.hibernate-orm.database.generation=update
Übung 2a: Persistenz in skipass-manager
4. Ergänzen Sie die Klasse SkiPassRepository für CRUD-Operationen
• vgl. PersonRepository aus rest-cdi-jpa
• persist, findAll und findById reichen
5. Nutzen Sie SkiPassRepository in SkiPassResource
• Injizieren Sie eine SkiPassRepository-Instanz
• Ergänzen Sie die POST-Methode um die Speicherung des Skipasses
6. Prüfen Sie, ob mittels POST erzeugte Skipässe in der DB gespeichert
werden
• Das Treiber-Jar der H2-DB enthält einen einfachen Client
• liegt im lokalen Maven-Repository
(~/.m2/repository/com/h2database/h2/1.4.197/h2-1.4.197.jar)
• Start per java -jar h2-1.4.197.jar
JEE-Microservices mit Quarkus - eine Einführung 28gedoplan.de
Übung 2a: Persistenz in skipass-manager
7. Tauschen Sie die Quarkus-Extension für Rest gegen die mit
JSON-B-Unterstützung aus
• quarkus-resteasy-jsonb
8. Ergänzen Sie SkiPassResource um GET-Methoden für alle
Skipässe bzw. für einen Skipass in JSON
• GET /skipass
• GET /skipass/{id}
9. Fragen Sie zum Test bspw. per curl Skipässe ab
• curl http://localhost:8080/skipass
• curl http://localhost:8080/skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249
JEE-Microservices mit Quarkus - eine Einführung 29gedoplan.de
Übung 2b: Logik für Skipass-Validierung
1. Ergänzen Sie den Rest-Service um eine PUT-Methode
zum Setzen des blocked-Attributs eines Skipasses
• PUT /skipass/{id}/blocked
• Konsumiert boolean als JSON
• Skipass zur angegebenen Id suchen und blocked setzen
• @Transactional
2. Ergänzen Sie eine weitere Methode zur Abfrage des
Gültigkeitsendes eines Skipasses
• GET /skipass/{id}/validTo
• Liefert LocalDateTime-Objekt als JSON
• falls Skipass gültig (*), sein validTo
(* vorhanden, nicht blockiert, jetzt gültig)
• andernfalls LocalDateTime.MIN
JEE-Microservices mit Quarkus - eine Einführung 30gedoplan.de
Übungs-Domäne
3. Schritt: Service skipass-gate
mit Aufruf von skipass-manager
(Rest Client)
JEE-Microservices mit Quarkus - eine Einführung 31gedoplan.de
skipass-manager
• POST /skipass?validTo=2019-12-14T18:00
Erzeugen eines Skipasses (id = UUID)
• GET /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/validTo
Abfrage der Gültigkeit (Ende-Timestamp oder Ungültig-Wert)
• PUT /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/blocked
Sperren oder Freigeben eines Skipasses
• …
DB skipass-gate
• GET /gate/2a910ff2-b92a-477f-861d-36fdf2c3c249
Einlass-Prüfung (GREEN/RED)
Kleiner Ausflug: MicroProfile Rest Client
Rest Client
Injizierbare REST clients
aus Interface generiert
konfigurierbare URL
JEE-Microservices mit Quarkus - eine Einführung 32gedoplan.de
@Path("v2")
@RegisterRestClient
public interface CountryApi {
@GET
@Path("all")
@Produces("application/json")
Collection<Country> getAll();
de.gedoplan.showcase.….CountryApi/mp-rest/url=http://restcountries.eu/rest
META-INF/microprofile-config.properties
@Path("country")
@ApplicationScoped
public class CountryResource {
@Inject
@RestClient
CountryApi countryClient;
@GET
@Path("count")
@Produces(MediaType.APPLICATION_JSON)
public int getCount() {
return countryClient.getAll().size();
MP Rest Client in Quarkus
Extension
Konfiguration von externer URL und Scope auch in
application.properties möglich
JEE-Microservices mit Quarkus - eine Einführung 33gedoplan.de
mvn quarkus:add-extensions –Dextensions=quarkus-rest-client
# Rest Client
fully.qual.rest.Intf/mp-rest/url=http://…
fully.qual.rest.Intf/mp-rest/scope=javax.enterprise.context.ApplicationScoped
application.properties
Übung 3: skipass-gate
1. Erzeugen Sie das Quarkus-Projekt skipass-gate
2. Ergänzen Sie ein Rest Client Interface SkiPassManager
• beschreibt Ihren Rest Service in skipass-manager
(Methode für GET /skipass/{id}/validTo reicht)
• @RegisterRestClient
JEE-Microservices mit Quarkus - eine Einführung 34gedoplan.de
mvn io.quarkus:quarkus-maven-plugin:1.0.0.CR1:create 
-DprojectGroupId=jvmcon 
-DprojectArtifactId=skipass-gate 
-Dextensions=quarkus-resteasy-jsonb,quarkus-rest-client
-B
Übung 3: skipass-gate
3. Ergänzen Sie in skipass-gate den Service GateService
• zunächst nur als Wrapper um SkiPassManager
(Kopiervorlage: gateservice.txt)
JEE-Microservices mit Quarkus - eine Einführung 35gedoplan.de
@ApplicationScoped
public class GateService {
@Inject
@RestClient
SkiPassManager skiPassManager;
public boolean isValid(String skiPassId) {
LocalDateTime validTo = fetch(skiPassId);
return validTo != null && validTo.isAfter(LocalDateTime.now());
}
private LocalDateTime fetch(String skiPassId) {
return this.skiPassManager.getValidTo(skiPassId);
}
Übung 3: skipass-gate
4. Ergänzen Sie in skipass-gate einen Rest Endpoint
• @Path("gate")
• GateService-Objekt injizieren
• GET-Methode für Tor-Öffnung
• GET /gate/{id}
• nutzt GateService zur Prüfung
• liefert "GREEN" oder "RED" in text/plain
5. Konfigurieren Sie andere Ports
• HTTP-Port mit Config Property:
quarkus.http.port=8180
• Debug-Port mittels Startparameter: -Ddebug=5105
6. Prüfen Sie die Funktion mit curl
JEE-Microservices mit Quarkus - eine Einführung 36gedoplan.de
Übungs-Domäne
4. Schritt: Fault Tolerance in skipass-gate
JEE-Microservices mit Quarkus - eine Einführung 37gedoplan.de
skipass-manager
• POST /skipass?validTo=2019-12-14T18:00
Erzeugen eines Skipasses (id = UUID)
• GET /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/validTo
Abfrage der Gültigkeit (Ende-Timestamp oder Ungültig-Wert)
• PUT /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/blocked
Sperren oder Freigeben eines Skipasses
• …
DB skipass-gate
• GET /gate/2a910ff2-b92a-477f-861d-36fdf2c3c249
Einlass-Prüfung (GREEN/RED)
Kleiner Ausflug: MicroProfile Fault Tolerance
Interceptors für Resilience
@Retry wiederholt Aufruf bei Fehler (=Exception)
@Timeout bricht langsame Aufrufe ab
@Fallback liefert Ersatzwert
JEE-Microservices mit Quarkus - eine Einführung 38gedoplan.de
@Retry(maxRetries = 4)
public int doSomethingWithRetry() {
@Timeout(1000)
public int doSomethingWithTimeout() {
private int return42() {
return 42;
}
@Fallback(fallbackMethod = "return42")
public int doSomethingWithFallback() {
MicroProfile Fault Tolerance
Interceptors für Resilience
@CircuitBreaker unterdrückt Aufrufe bei hoher Fehlerrate
Quarkus-Extension: quarkus-smallrye-fault-tolerance
JEE-Microservices mit Quarkus - eine Einführung 39gedoplan.de
@CircuitBreaker(failureRatio = 0.25, requestVolumeThreshold = 10)
public int doSomethingWithCircuitBreaker() {
closed open
half-open
zu viele
Fehler
ok
Delay
Fehler
Übung 4: Fault Tolerance in skipass-gate
1. Machen Sie GateService.isValid in skipass-gate
fault-tolerant
• skipass-manager nicht erreichbar  Gate öffnen
• Fallback-Methode, die immer true liefert
• @Fallback auf isValid
2. Prüfen Sie die Funktion von skipass-gate bei nicht laufendem
skipass-manager
JEE-Microservices mit Quarkus - eine Einführung 40gedoplan.de
Übungs-Domäne
5. Schritt: Caching der Skipass-daten in skipass-gate
Invalidierung des Caches per Message
JEE-Microservices mit Quarkus - eine Einführung 41gedoplan.de
skipass-manager
• POST /skipass?validTo=2019-12-14T18:00
Erzeugen eines Skipasses (id = UUID)
• GET /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/validTo
Abfrage der Gültigkeit (Ende-Timestamp oder Ungültig-Wert)
• PUT /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/blocked
Sperren oder Freigeben eines Skipasses
• …
DB skipass-gate
• GET /gate/2a910ff2-b92a-477f-861d-36fdf2c3c249
Einlass-Prüfung (GREEN/RED)
Übung 5a: Cache in skipass-gate
1. Simulieren Sie eine langsame Ausführung von skipass-gate
• In skipass-manager,
Methode für GET /skipass/{id}/validTo:
Thread.sleep(3000)
2. Verifizieren Sie, dass skipass-gate nun recht zäh arbeitet
3. Cachen Sie die Skipass-Gültigkeit in skipass-gate,
GateService
• nutzen Sie ein ConcurrentMap<String,
LocalDateTime> zum cachen der Gültigkeit der Skipässe
(Kopiervorlage: gateservice-chached.txt)
JEE-Microservices mit Quarkus - eine Einführung 42gedoplan.de
Übung 5a: Cache in skipass-gate
4. Verifizieren Sie, dass skipass-gate
• nun nur einmal pro Id langsam arbeitet,
• danach aber auch bei nachträglicher Blockierung eines
Skipasses weiter mit veralteten Daten arbeitet
Abhilfe: Invalidieren (Entfernen) der gecachten Einträge in skipass-
gate nach jeder Änderung in skipass-manager
JEE-Microservices mit Quarkus - eine Einführung 43gedoplan.de
skipass-manager
• PUT /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/blocked
Sperren oder Freigeben eines Skipasses
skipass-gate
2a910ff2-b92a-477f-861d-36fdf2c3c249
Kleiner Ausflug: (Reactive) Messaging
@Incoming = Meldungsempfänger
Analog: @Outgoing für Meldungsproduzenten
im Workshop ungenutzt
@Channel(…) Emitter
= Brücke imperativ  reaktiv
JEE-Microservices mit Quarkus - eine Einführung 44gedoplan.de
@Incoming("channel-one")
public void onReceive(String someReceivedString) {
@Inject
@Channel("channel-two")
Emitter<String> emitter;
…
this.emitter.send(someString);
Reactive Message in Quarkus mit AMQP
Extension
Konfiguration
JEE-Microservices mit Quarkus - eine Einführung 45gedoplan.de
mvn quarkus:add-extensions –Dextensions=quarkus-smallrye-reactive-messaging-amqp
# Messaging
amqp-username=quarkus
amqp-password=quarkus
mp.messaging.incoming.channel-one.connector=smallrye-amqp
mp.messaging.incoming.channel-one.address=topic-one-on-amqp-server
mp.messaging.incoming.channel-one.durable=false
mp.messaging.incoming.channel-one.broadcast=true
mp.messaging.outgoing.channel-two.connector=smallrye-amqp
mp.messaging.outgoing.channel-two.address=topic-two-on-amqp-server
mp.messaging.outgoing.channel-two.durable=false
mp.messaging.outgoing.channel-two.broadcast=true
application.properties
Übung 5b: Cache in skipass-gate
1. Installieren, konfigurieren und starten Sie ActiveMQ Artemis
• Demo-Projekt active-mq-artemis
• mvn lädt Artemis herunter
und konfiguriert Broker in target/demoserver
• Start: target/demoserver/bin/artemis run
2. Ergänzen Sie die AMQP-Konfiguration in skipass-manager
(Kopiervorlage: skipass-manager-amqp.txt)
JEE-Microservices mit Quarkus - eine Einführung 46gedoplan.de
# Messaging
amqp-username=quarkus
amqp-password=quarkus
mp.messaging.outgoing.skipassInvalidation.connector=smallrye-amqp
mp.messaging.outgoing.skipassInvalidation.address=skipassInvalidation
mp.messaging.outgoing.skipassInvalidation.durable=false
mp.messaging.outgoing.skipassInvalidation.broadcast=true
Übung 5b: Cache in skipass-gate
3. Senden Sie die Ids von veränderten Skipässen als Message
• In SkiPassResource in skipass-manager:
• Emitter<String> injizieren für Channel
skipassInvalidation
• In Methode für PUT /skipass/{id}/blocked am Ende
Id des geänderten Skipasses versenden
4. Ergänzen Sie die AMQP-Konfiguration in skipass-gate
(Kopiervorlage: skipass-gate-amqp.txt)
JEE-Microservices mit Quarkus - eine Einführung 47gedoplan.de
amqp-username=quarkus
amqp-password=quarkus
mp.messaging.incoming.skipassInvalidation.connector=smallrye-amqp
mp.messaging.incoming.skipassInvalidation.address=skipassInvalidation
mp.messaging.incoming.skipassInvalidation.durable=false
mp.messaging.incoming.skipassInvalidation.broadcast=true
Übung 5b: Cache in skipass-gate
5. Ergänzen Sie im GateService von skipass-gate eine
Methode,
• die eingehende Ids von veränderten Skipässen annimmt
• und diese aus dem Cache entfernt
6. Verifizieren Sie dass skipass-gate nun auch nach
(Ent-)Sperren von Skipässen richtig arbeitet
JEE-Microservices mit Quarkus - eine Einführung 48gedoplan.de
@Incoming("skipassInvalidation")
public void invalidate(String skiPassId) {
this.cache.remove(skiPassId);
}
Weitere Quarkus-Features
Tests mit @QuarkustTest
OpenAPI
MongoDB, Neo4j, …
Kafka, JMS, Camel
OpenID Connect
Health, Metrics
Spring Integration
Scheduling
Mail
Native Mode
JEE-Microservices mit Quarkus - eine Einführung 49gedoplan.de
More
Wir bilden Sie aus!
www.gedoplan-it-training.de
Trainings in Berlin, Frankfurt, Köln, Bielefeld, inhouse
neu: JEE Microservice Foundation
neu: Java DevOps: Development und
Delivery mit Docker und Kubernetes
Wir unterstützen Sie in Ihren Projekten
www.gedoplan-it-consulting.de
Reviews, Coaching, …
javaeeblog.wordpress.com
 dirk.weil@gedoplan.de
@dirkweil
50gedoplan.deJEE-Microservices mit Quarkus - eine Einführung

JEE-Microservices mit Quarkus – eine Einführung

  • 1.
    JEE-Microservices mit Quarkus- eine Einführung 25.11.2019 Dirk Weil, GEDOPLAN GmbH
  • 2.
    Dirk Weil GEDOPLAN GmbH,Bielefeld GEDOPLAN IT Consulting Consulting, coaching, concepts, reviews, development GEDOPLAN IT Training & partner Java, JEE, tools trainings Berlin, Frankfurt, Bielefeld, Köln, on-site JEE since 1998 Speaker and author JEE-Microservices mit Quarkus - eine Einführung 2gedoplan.de
  • 3.
    Java EE Jakarta EE 2017: Projekt EE4J (Eclipse Enterprise for Java) Produktname Jakarta EE Oracle behält Namens- und Urheberrechte Java EE Paketnamen javax.* Jakarta EE 8 codegleich zu Java EE 8 Release 10.09.2019 JEE-Microservices mit Quarkus - eine Einführung 3 JEE gedoplan.de
  • 4.
    MicroProfile microprofile.io „Next step ofJava EE / Jakarta EE evolution“ „… optimize Enterprise Java for a microservices architecture …“ JEE-Microservices mit Quarkus - eine Einführung 4gedoplan.de Config 1.3 Fault Tolerance 2.0 Health 2.0 JWT Authentication 1.1 Metrics 2.0.0 OpenAPI 1.1 OpenTracing 1.3 Rest Client 1.3 CDI 2.0 JAX-RS 2.1 JSON-B 1.0 JSON-P 1.1
  • 5.
    MicroProfile Runtimes: KlassischeApplication Server 5 Anwendungsklassen Konfigurationsfiles (Deployment Descriptors, Properties, …) JEE Server CDI Runtime JPA Runtime REST Runtime Technische Konfiguration * JRE build deploy run * DB-Verbindungen, Messaging Security … Thin WAR klein groß gedoplan.deJEE-Microservices mit Quarkus - eine Einführung
  • 6.
    MicroProfile Runtimes: „Micro“Frameworks 6 Anwendungsklassen Konfigurationsfiles * CDI Runtime JPA Runtime REST Runtime JRE build run * Anwendungsparameter, DB-Verbindungen, Messaging Security … Fat JAR JAR + Dependencies groß gedoplan.deJEE-Microservices mit Quarkus - eine Einführung
  • 7.
    Workshop-Projekt Source github.com/GEDOPLAN/quarkus-workshop Branches: master Demos, Skripte, Kopiervorlagen,… jvmcon2019 basiert auf master wird während des Workshops sukzessive aufgebaut Tooling JDK 8+ (z. B. adoptopenjdk.net) Maven 3 (maven.apache.org/download.cgi) Git Client (git-scm.com/downloads) curl (curl.haxx.se/download.html) JEE-Microservices mit Quarkus - eine Einführung 7gedoplan.de
  • 8.
    Quarkus Red Hats Antwortauf Spring Boot Designierter Nachfolger von Thorntail (aka WildFly Swarm) Optimiert für kurze Startzeiten Hotspot und GraalVM https://quarkus.io/ JEE-Microservices mit Quarkus - eine Einführung 8gedoplan.de
  • 9.
    Quarkus Core + Extensions (= MavenDependencies) Project Bootstrap mit Maven Plugin (oder Gradle)  quarkus.io/guides/maven-tooling.html JEE-Microservices mit Quarkus - eine Einführung 9gedoplan.de <dependencies> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-resteasy</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-junit5</artifactId> <scope>test</scope> </dependency> mvn io.quarkus:quarkus-maven-plugin:1.0.0.CR1:create -DprojectGroupId=… -DprojectArtifactId=… -B
  • 10.
    Quarkus Maven-Plugin für Build Thinjar target/quarkus-getting-started-runner.jar Dependencies in target/lib/ Anwendungsstart java –jar target/quarkus-getting-started-runner.jar JEE-Microservices mit Quarkus - eine Einführung 10gedoplan.de <plugins> <plugin> <groupId>io.quarkus</groupId> <artifactId>quarkus-maven-plugin</artifactId> <version>${quarkus.version}</version> <executions> <execution> <goals><goal>build</goal></goals> </execution>
  • 11.
    Quarkus Development mode Hot reload beiREST/Web-Request falls Quellcodeänderung JEE-Microservices mit Quarkus - eine Einführung 11gedoplan.de $ mvn quarkus:dev Listening for transport dt_socket at address: 5005 17:54:50,319 INFO [io.qua.dep.QuarkusAugmentor] (main) Beginning quarkus au 17:54:50,949 INFO [io.qua.resteasy] (build-1) Resteasy running without serv 17:54:50,949 INFO [io.qua.resteasy] (build-1) - Add quarkus-undertow to run 17:54:50,980 INFO [io.qua.dep.QuarkusAugmentor] (main) Quarkus augmentation 17:54:52,452 INFO [io.quarkus] (main) Quarkus 0.26.1 started in 2.320s. Lis 17:54:52,452 INFO [io.quarkus] (main) Profile dev activated. Live Coding ac 17:54:52,454 INFO [io.quarkus] (main) Installed features: [cdi, resteasy]
  • 12.
    Quarkus Configuration application.properties Properties quarkus.… fürQuarkus quarkus.io/guides/config quarkus.io/guides/all-config Weitere Properties für Anwendung (MicroProfile Config) Configuration Profiles %prod, %dev, %test JEE-Microservices mit Quarkus - eine Einführung 12gedoplan.de # Ports quarkus.http.port=8080 # Logging quarkus.log.console.format=%d{HH:mm:ss,SSS} %-6p [%c{1.}] (%t) %s%e%n quarkus.log.console.color=false quarkus.log.level=INFO quarkus.log.category."some.logger.name".level=WARN %dev.quarkus.log.category."some.logger.name".level=FINE
  • 13.
    Demo: getting-started Bootstrap Start JEE-Microservices mitQuarkus - eine Einführung 13gedoplan.de mvn io.quarkus:quarkus-maven-plugin:1.0.0.CR1:create -DprojectGroupId=jvmcon -DprojectArtifactId=getting-started -DclassName="jvmcon.GreetingResource" -B getting-started-bootstrap.sh cd getting-started mvn compile quarkus:dev
  • 14.
    Kleiner Ausflug: JAX-RS Klassemit @Path definiert Rest Endpoints Methoden mit @GET, @PUT, @POST, @DELETE @Path kann auf Methoden ergänzend genutzt werden Pfade dürfen Templates enthalten @Produces und @Consumes bestimmen (De-)Serialisierung Parameter können aus URL übernommen werden siehe Klasse GreetingResource (nach Bootstrap ergänzt) Beispiel-Aufrufe mittels curl siehe getting-started-curl.txt JEE-Microservices mit Quarkus - eine Einführung 14gedoplan.de
  • 15.
    Übungs-Domäne Skipass-Verwaltung und Nutzung 1.Schritt: skipass-manager mit POST-Endpoint zur Erzeugung von Skipässen JEE-Microservices mit Quarkus - eine Einführung 15gedoplan.de skipass-manager • POST /skipass?validTo=2019-12-14T18:00 Erzeugen eines Skipasses (id = UUID) • GET /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/validTo Abfrage der Gültigkeit (Ende-Timestamp oder Ungültig-Wert) • PUT /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/blocked Sperren oder Freigeben eines Skipasses • … DB skipass-gate • GET /gate/2a910ff2-b92a-477f-861d-36fdf2c3c249 Einlass-Prüfung (GREEN/RED)
  • 16.
    Übungs-Domäne 1. Schritt: skipass-manager mitPOST-Endpoint zur Erzeugung von Skipässen (Project Bootstrap, JAX-RS) JEE-Microservices mit Quarkus - eine Einführung 16gedoplan.de skipass-manager • POST /skipass?validTo=2019-12-14T18:00 Erzeugen eines Skipasses (id = UUID) • GET /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/validTo Abfrage der Gültigkeit (Ende-Timestamp oder Ungültig-Wert) • PUT /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/blocked Sperren oder Freigeben eines Skipasses • … DB skipass-gate • GET /gate/2a910ff2-b92a-477f-861d-36fdf2c3c249 Einlass-Prüfung (GREEN/RED)
  • 17.
    Übung 1: Bootstrapskipass-manager 1. Erzeugen Sie das Quarkus-Projekt skipass-manager 2. Ergänzen Sie die Entity SkiPass • Kopiervorlage: skipass.txt • Paket, Getter, Setter, toString nach Gusto JEE-Microservices mit Quarkus - eine Einführung 17gedoplan.de mvn io.quarkus:quarkus-maven-plugin:1.0.0.CR1:create -DprojectGroupId=jvmcon -DprojectArtifactId=skipass-manager -B public class SkiPass { private String id; private LocalDateTime validFrom; private LocalDateTime validTo; private boolean blocked;
  • 18.
    Übung 1: Bootstrapskipass-manager 3. Ergänzen Sie die Rest-Resource SkiPassResource • @Path("skipass") • Methode für Skipass-Anlage • @POST • @Produces(MediaType.TEXT_PLAIN) • Parameter • @QueryParam("validTo") LocalDateTime validTo • @QueryParam("validFrom") LocalDateTime validFrom • neues SkiPass-Objekt instanziieren und seine Id als Returnwert liefern 4. Anwendung starten 5. Rest-Call ausprobieren JEE-Microservices mit Quarkus - eine Einführung 18gedoplan.de curl -X POST -i http://localhost:8080/skipass?validTo=2019-12-24T23:59 mvn compile quarkus:dev
  • 19.
    Übungs-Domäne 2. Schritt: Skipässepersistent ablegen (JPA, CDI, JSON-B) Validierungslogik JEE-Microservices mit Quarkus - eine Einführung 19gedoplan.de skipass-manager • POST /skipass?validTo=2019-12-14T18:00 Erzeugen eines Skipasses (id = UUID) • GET /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/validTo Abfrage der Gültigkeit (Ende-Timestamp oder Ungültig-Wert) • PUT /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/blocked Sperren oder Freigeben eines Skipasses • … DB skipass-gate • GET /gate/2a910ff2-b92a-477f-861d-36fdf2c3c249 Einlass-Prüfung (GREEN/RED)
  • 20.
    Kleiner Ausflug: CDI Anwendungen/ Geschäftslogik besteht aus vielen Services die einander benutzen / referenzieren deren Daten unterschiedlich lang benötigt werden (gesamte Laufzeit, einzelner Request, …) JEE-Microservices mit Quarkus - eine Einführung 20gedoplan.de Application Use Case Domain Data Service Domain Data Service Data Repository Data Repository Data Repository Page / View Endpoint TX JPA Mail JMS
  • 21.
    Kleiner Ausflug: CDI Definitionvon Beans (=Services) und Zuordnung zu Scopes (=Lebensdauer) Verknüpfung untereinander mittels Injektion Descriptor META-INF/beans.xml für Quarkus optional Inhalt wird von Quarkus (derzeit?) nicht genutzt JEE-Microservices mit Quarkus - eine Einführung 21gedoplan.de @ApplicationScoped public class PersonRepository { @ApplicationScoped @Path("person") public class PersonResource { @Inject PersonRepository personRepository;
  • 22.
    Kleiner Ausflug: CDI Interceptorsz. B. für Transaktionssteuerung Weitere Features (hier nicht benötigt): Qualifier Alternatives Producer Events JEE-Microservices mit Quarkus - eine Einführung 22gedoplan.de @ApplicationScoped @Transactional(rollbackOn = Exception.class) public class PersonRepository { @Inject EntityManager entityManager; public void persist(Person entity) { this.entityManager.persist(entity);
  • 23.
    Kleiner Ausflug: JPA Aufgabenstellung: Speichernund Laden von Java-Objekten Mapping OO  RDBMS Entities (=persistente Objekte) sind POJOs nicht final No-args constructor @Entity @Id Diskussion über Ids, Generatoren, equals, hashCode siehe javaeeblog.wordpress.com/2017/11/15/ identity-and-equality-of-jpa-entities/ JEE-Microservices mit Quarkus - eine Einführung 23gedoplan.de @Entity public class Person { @Id @GeneratedValue(strategy = …) private Integer id; private String name; private String firstname; protected Person() { }
  • 24.
    Kleiner Ausflug: JPA EntityManager= API für CRUD, Queries, … JEE-Microservices mit Quarkus - eine Einführung 24gedoplan.de public class PersonRepository { @Inject EntityManager entityManager; public Person findById(Integer id) { return this.entityManager.find(Person.class, id); } public List<Person> findAll() { return this.entityManager .createQuery("select x from Person x", Person.class) .getResultList(); } public void persist(Person entity) { this.entityManager.persist(entity);
  • 25.
    JPA in Quarkus Extensionsfür Hibernate und DB-Treiber Konfiguration der Datasource(s) META-INF/persistence.xml optional JEE-Microservices mit Quarkus - eine Einführung 25gedoplan.de mvn quarkus:add-extensions –Dextensions=quarkus-hibernate-orm,quarkus-jdbc-h2 # Datasource quarkus.datasource.url=jdbc:h2:mem:test;… quarkus.datasource.driver=org.h2.Driver quarkus.datasource.username=showcase quarkus.datasource.password=showcase quarkus.hibernate-orm.database.generation=update quarkus.datasource.hugo.url=jdbc:… application.properties
  • 26.
    Kleiner Ausflug: JSON-B (De-)SerialisierungPOJO  JSON Automatische Nutzung in JAX-RS Mediatype application/json Quarkus-Extension quarkus-resteasy-jsonb (statt quarkus-resteasy) JEE-Microservices mit Quarkus - eine Einführung 26gedoplan.de Person person = new Person("Wacker", "Willi"); Jsonb jsonb = JsonbBuilder.create(); String personJson = jsonb.toJson(person);
  • 27.
    Übung 2a: Persistenzin skipass-manager 1. Ergänzen Sie die für JPA nötigen Extensions 2. Konfigurieren Sie die Datasource 3. Machen Sie die Entity SkiPass JPA-fähig • @Entity, @Id • No-args constructor JEE-Microservices mit Quarkus - eine Einführung 27gedoplan.de mvn quarkus:add-extensions –Dextensions=quarkus-hibernate-orm,quarkus-jdbc-h2 # Datasource quarkus.datasource.url=jdbc:h2:~/h2/jvmcon;AUTO_SERVER=TRUE quarkus.datasource.driver=org.h2.Driver quarkus.datasource.username=jvmcon quarkus.datasource.password=jvmcon quarkus.hibernate-orm.database.generation=update
  • 28.
    Übung 2a: Persistenzin skipass-manager 4. Ergänzen Sie die Klasse SkiPassRepository für CRUD-Operationen • vgl. PersonRepository aus rest-cdi-jpa • persist, findAll und findById reichen 5. Nutzen Sie SkiPassRepository in SkiPassResource • Injizieren Sie eine SkiPassRepository-Instanz • Ergänzen Sie die POST-Methode um die Speicherung des Skipasses 6. Prüfen Sie, ob mittels POST erzeugte Skipässe in der DB gespeichert werden • Das Treiber-Jar der H2-DB enthält einen einfachen Client • liegt im lokalen Maven-Repository (~/.m2/repository/com/h2database/h2/1.4.197/h2-1.4.197.jar) • Start per java -jar h2-1.4.197.jar JEE-Microservices mit Quarkus - eine Einführung 28gedoplan.de
  • 29.
    Übung 2a: Persistenzin skipass-manager 7. Tauschen Sie die Quarkus-Extension für Rest gegen die mit JSON-B-Unterstützung aus • quarkus-resteasy-jsonb 8. Ergänzen Sie SkiPassResource um GET-Methoden für alle Skipässe bzw. für einen Skipass in JSON • GET /skipass • GET /skipass/{id} 9. Fragen Sie zum Test bspw. per curl Skipässe ab • curl http://localhost:8080/skipass • curl http://localhost:8080/skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249 JEE-Microservices mit Quarkus - eine Einführung 29gedoplan.de
  • 30.
    Übung 2b: Logikfür Skipass-Validierung 1. Ergänzen Sie den Rest-Service um eine PUT-Methode zum Setzen des blocked-Attributs eines Skipasses • PUT /skipass/{id}/blocked • Konsumiert boolean als JSON • Skipass zur angegebenen Id suchen und blocked setzen • @Transactional 2. Ergänzen Sie eine weitere Methode zur Abfrage des Gültigkeitsendes eines Skipasses • GET /skipass/{id}/validTo • Liefert LocalDateTime-Objekt als JSON • falls Skipass gültig (*), sein validTo (* vorhanden, nicht blockiert, jetzt gültig) • andernfalls LocalDateTime.MIN JEE-Microservices mit Quarkus - eine Einführung 30gedoplan.de
  • 31.
    Übungs-Domäne 3. Schritt: Serviceskipass-gate mit Aufruf von skipass-manager (Rest Client) JEE-Microservices mit Quarkus - eine Einführung 31gedoplan.de skipass-manager • POST /skipass?validTo=2019-12-14T18:00 Erzeugen eines Skipasses (id = UUID) • GET /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/validTo Abfrage der Gültigkeit (Ende-Timestamp oder Ungültig-Wert) • PUT /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/blocked Sperren oder Freigeben eines Skipasses • … DB skipass-gate • GET /gate/2a910ff2-b92a-477f-861d-36fdf2c3c249 Einlass-Prüfung (GREEN/RED)
  • 32.
    Kleiner Ausflug: MicroProfileRest Client Rest Client Injizierbare REST clients aus Interface generiert konfigurierbare URL JEE-Microservices mit Quarkus - eine Einführung 32gedoplan.de @Path("v2") @RegisterRestClient public interface CountryApi { @GET @Path("all") @Produces("application/json") Collection<Country> getAll(); de.gedoplan.showcase.….CountryApi/mp-rest/url=http://restcountries.eu/rest META-INF/microprofile-config.properties @Path("country") @ApplicationScoped public class CountryResource { @Inject @RestClient CountryApi countryClient; @GET @Path("count") @Produces(MediaType.APPLICATION_JSON) public int getCount() { return countryClient.getAll().size();
  • 33.
    MP Rest Clientin Quarkus Extension Konfiguration von externer URL und Scope auch in application.properties möglich JEE-Microservices mit Quarkus - eine Einführung 33gedoplan.de mvn quarkus:add-extensions –Dextensions=quarkus-rest-client # Rest Client fully.qual.rest.Intf/mp-rest/url=http://… fully.qual.rest.Intf/mp-rest/scope=javax.enterprise.context.ApplicationScoped application.properties
  • 34.
    Übung 3: skipass-gate 1.Erzeugen Sie das Quarkus-Projekt skipass-gate 2. Ergänzen Sie ein Rest Client Interface SkiPassManager • beschreibt Ihren Rest Service in skipass-manager (Methode für GET /skipass/{id}/validTo reicht) • @RegisterRestClient JEE-Microservices mit Quarkus - eine Einführung 34gedoplan.de mvn io.quarkus:quarkus-maven-plugin:1.0.0.CR1:create -DprojectGroupId=jvmcon -DprojectArtifactId=skipass-gate -Dextensions=quarkus-resteasy-jsonb,quarkus-rest-client -B
  • 35.
    Übung 3: skipass-gate 3.Ergänzen Sie in skipass-gate den Service GateService • zunächst nur als Wrapper um SkiPassManager (Kopiervorlage: gateservice.txt) JEE-Microservices mit Quarkus - eine Einführung 35gedoplan.de @ApplicationScoped public class GateService { @Inject @RestClient SkiPassManager skiPassManager; public boolean isValid(String skiPassId) { LocalDateTime validTo = fetch(skiPassId); return validTo != null && validTo.isAfter(LocalDateTime.now()); } private LocalDateTime fetch(String skiPassId) { return this.skiPassManager.getValidTo(skiPassId); }
  • 36.
    Übung 3: skipass-gate 4.Ergänzen Sie in skipass-gate einen Rest Endpoint • @Path("gate") • GateService-Objekt injizieren • GET-Methode für Tor-Öffnung • GET /gate/{id} • nutzt GateService zur Prüfung • liefert "GREEN" oder "RED" in text/plain 5. Konfigurieren Sie andere Ports • HTTP-Port mit Config Property: quarkus.http.port=8180 • Debug-Port mittels Startparameter: -Ddebug=5105 6. Prüfen Sie die Funktion mit curl JEE-Microservices mit Quarkus - eine Einführung 36gedoplan.de
  • 37.
    Übungs-Domäne 4. Schritt: FaultTolerance in skipass-gate JEE-Microservices mit Quarkus - eine Einführung 37gedoplan.de skipass-manager • POST /skipass?validTo=2019-12-14T18:00 Erzeugen eines Skipasses (id = UUID) • GET /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/validTo Abfrage der Gültigkeit (Ende-Timestamp oder Ungültig-Wert) • PUT /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/blocked Sperren oder Freigeben eines Skipasses • … DB skipass-gate • GET /gate/2a910ff2-b92a-477f-861d-36fdf2c3c249 Einlass-Prüfung (GREEN/RED)
  • 38.
    Kleiner Ausflug: MicroProfileFault Tolerance Interceptors für Resilience @Retry wiederholt Aufruf bei Fehler (=Exception) @Timeout bricht langsame Aufrufe ab @Fallback liefert Ersatzwert JEE-Microservices mit Quarkus - eine Einführung 38gedoplan.de @Retry(maxRetries = 4) public int doSomethingWithRetry() { @Timeout(1000) public int doSomethingWithTimeout() { private int return42() { return 42; } @Fallback(fallbackMethod = "return42") public int doSomethingWithFallback() {
  • 39.
    MicroProfile Fault Tolerance Interceptorsfür Resilience @CircuitBreaker unterdrückt Aufrufe bei hoher Fehlerrate Quarkus-Extension: quarkus-smallrye-fault-tolerance JEE-Microservices mit Quarkus - eine Einführung 39gedoplan.de @CircuitBreaker(failureRatio = 0.25, requestVolumeThreshold = 10) public int doSomethingWithCircuitBreaker() { closed open half-open zu viele Fehler ok Delay Fehler
  • 40.
    Übung 4: FaultTolerance in skipass-gate 1. Machen Sie GateService.isValid in skipass-gate fault-tolerant • skipass-manager nicht erreichbar  Gate öffnen • Fallback-Methode, die immer true liefert • @Fallback auf isValid 2. Prüfen Sie die Funktion von skipass-gate bei nicht laufendem skipass-manager JEE-Microservices mit Quarkus - eine Einführung 40gedoplan.de
  • 41.
    Übungs-Domäne 5. Schritt: Cachingder Skipass-daten in skipass-gate Invalidierung des Caches per Message JEE-Microservices mit Quarkus - eine Einführung 41gedoplan.de skipass-manager • POST /skipass?validTo=2019-12-14T18:00 Erzeugen eines Skipasses (id = UUID) • GET /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/validTo Abfrage der Gültigkeit (Ende-Timestamp oder Ungültig-Wert) • PUT /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/blocked Sperren oder Freigeben eines Skipasses • … DB skipass-gate • GET /gate/2a910ff2-b92a-477f-861d-36fdf2c3c249 Einlass-Prüfung (GREEN/RED)
  • 42.
    Übung 5a: Cachein skipass-gate 1. Simulieren Sie eine langsame Ausführung von skipass-gate • In skipass-manager, Methode für GET /skipass/{id}/validTo: Thread.sleep(3000) 2. Verifizieren Sie, dass skipass-gate nun recht zäh arbeitet 3. Cachen Sie die Skipass-Gültigkeit in skipass-gate, GateService • nutzen Sie ein ConcurrentMap<String, LocalDateTime> zum cachen der Gültigkeit der Skipässe (Kopiervorlage: gateservice-chached.txt) JEE-Microservices mit Quarkus - eine Einführung 42gedoplan.de
  • 43.
    Übung 5a: Cachein skipass-gate 4. Verifizieren Sie, dass skipass-gate • nun nur einmal pro Id langsam arbeitet, • danach aber auch bei nachträglicher Blockierung eines Skipasses weiter mit veralteten Daten arbeitet Abhilfe: Invalidieren (Entfernen) der gecachten Einträge in skipass- gate nach jeder Änderung in skipass-manager JEE-Microservices mit Quarkus - eine Einführung 43gedoplan.de skipass-manager • PUT /skipass/2a910ff2-b92a-477f-861d-36fdf2c3c249/blocked Sperren oder Freigeben eines Skipasses skipass-gate 2a910ff2-b92a-477f-861d-36fdf2c3c249
  • 44.
    Kleiner Ausflug: (Reactive)Messaging @Incoming = Meldungsempfänger Analog: @Outgoing für Meldungsproduzenten im Workshop ungenutzt @Channel(…) Emitter = Brücke imperativ  reaktiv JEE-Microservices mit Quarkus - eine Einführung 44gedoplan.de @Incoming("channel-one") public void onReceive(String someReceivedString) { @Inject @Channel("channel-two") Emitter<String> emitter; … this.emitter.send(someString);
  • 45.
    Reactive Message inQuarkus mit AMQP Extension Konfiguration JEE-Microservices mit Quarkus - eine Einführung 45gedoplan.de mvn quarkus:add-extensions –Dextensions=quarkus-smallrye-reactive-messaging-amqp # Messaging amqp-username=quarkus amqp-password=quarkus mp.messaging.incoming.channel-one.connector=smallrye-amqp mp.messaging.incoming.channel-one.address=topic-one-on-amqp-server mp.messaging.incoming.channel-one.durable=false mp.messaging.incoming.channel-one.broadcast=true mp.messaging.outgoing.channel-two.connector=smallrye-amqp mp.messaging.outgoing.channel-two.address=topic-two-on-amqp-server mp.messaging.outgoing.channel-two.durable=false mp.messaging.outgoing.channel-two.broadcast=true application.properties
  • 46.
    Übung 5b: Cachein skipass-gate 1. Installieren, konfigurieren und starten Sie ActiveMQ Artemis • Demo-Projekt active-mq-artemis • mvn lädt Artemis herunter und konfiguriert Broker in target/demoserver • Start: target/demoserver/bin/artemis run 2. Ergänzen Sie die AMQP-Konfiguration in skipass-manager (Kopiervorlage: skipass-manager-amqp.txt) JEE-Microservices mit Quarkus - eine Einführung 46gedoplan.de # Messaging amqp-username=quarkus amqp-password=quarkus mp.messaging.outgoing.skipassInvalidation.connector=smallrye-amqp mp.messaging.outgoing.skipassInvalidation.address=skipassInvalidation mp.messaging.outgoing.skipassInvalidation.durable=false mp.messaging.outgoing.skipassInvalidation.broadcast=true
  • 47.
    Übung 5b: Cachein skipass-gate 3. Senden Sie die Ids von veränderten Skipässen als Message • In SkiPassResource in skipass-manager: • Emitter<String> injizieren für Channel skipassInvalidation • In Methode für PUT /skipass/{id}/blocked am Ende Id des geänderten Skipasses versenden 4. Ergänzen Sie die AMQP-Konfiguration in skipass-gate (Kopiervorlage: skipass-gate-amqp.txt) JEE-Microservices mit Quarkus - eine Einführung 47gedoplan.de amqp-username=quarkus amqp-password=quarkus mp.messaging.incoming.skipassInvalidation.connector=smallrye-amqp mp.messaging.incoming.skipassInvalidation.address=skipassInvalidation mp.messaging.incoming.skipassInvalidation.durable=false mp.messaging.incoming.skipassInvalidation.broadcast=true
  • 48.
    Übung 5b: Cachein skipass-gate 5. Ergänzen Sie im GateService von skipass-gate eine Methode, • die eingehende Ids von veränderten Skipässen annimmt • und diese aus dem Cache entfernt 6. Verifizieren Sie dass skipass-gate nun auch nach (Ent-)Sperren von Skipässen richtig arbeitet JEE-Microservices mit Quarkus - eine Einführung 48gedoplan.de @Incoming("skipassInvalidation") public void invalidate(String skiPassId) { this.cache.remove(skiPassId); }
  • 49.
    Weitere Quarkus-Features Tests mit@QuarkustTest OpenAPI MongoDB, Neo4j, … Kafka, JMS, Camel OpenID Connect Health, Metrics Spring Integration Scheduling Mail Native Mode JEE-Microservices mit Quarkus - eine Einführung 49gedoplan.de
  • 50.
    More Wir bilden Sieaus! www.gedoplan-it-training.de Trainings in Berlin, Frankfurt, Köln, Bielefeld, inhouse neu: JEE Microservice Foundation neu: Java DevOps: Development und Delivery mit Docker und Kubernetes Wir unterstützen Sie in Ihren Projekten www.gedoplan-it-consulting.de Reviews, Coaching, … javaeeblog.wordpress.com  dirk.weil@gedoplan.de @dirkweil 50gedoplan.deJEE-Microservices mit Quarkus - eine Einführung