Quarkus
From Openshift docs
Tutorial Quarkus
aplicación CRUD OpenJDK11, Maven, Docker,MongoDB, extention panacheMongo, extension metics
Quarkus Extensions
-----------------------------------------------------------------------------------------------------------
Iniciativa Microprofile 3.2
Open Tracing 1.3 OpenApi 1.1 RestClient 1.3 Config 1.3
Fault Tolerance 2.0 Metrics 2.2 JWT Autentication 1.1 Healt Check 2.1
CDI 2.0 JSON-P 1.1 JAX-RS 2.1 JSON-B 1.0
-------------------------------------------------------------------------------------------------------------
other
Hibernate Vert.x Narayana Camel Apache Kafka Agroal
ORM
--------------------------------------------------------------------------------------------------------------
quarkus commands
mvn quarkus:create or code.quarkus.io
mvn compile quarkus:dev
mvn package -Pnative -Dquarkus.native.container-build=true
mvn quarkus:add-extension -Dextensions="quarkus-smallrye-health"
curl http;//localhost:8080/health/live
curl http://localhost:8080/health/ready
./mvnw quarkus:add-extension -Dextensions="quarkus-smallrye-metrics"
curl http://localhost:8080/metrics
curl --header "Accept:application/json" localhost:8080/metrics
./mvnw package -Pnative -Dquarkus.native.container-build=true
1:27:14 call docker image
Quarkus: de cero a Serverless en Kubernetes
Create fruit-service
$mvn io.quarkus:quarkus-maven-plugin:$QUARKUS_VERSION:create \
-DprojectGroupId="com.bext.atomic.fruit" \
-DprojectArtifactId="atomic-fruit-service" \
-DprojectVersion="1.0-SNAPSHOT" \
-DclassnName="FruitResource" \
-Dpath="fruit"
$mvn io.quarkus:quarkus-maven-plugin:$QUARKUS_VERSION:create \
-DprojectGroupId="com.bext.atomic.fruit" \
-DprojectArtifactId="atomic-fruit-service" \
-DprojectVersion="1.0-SNAPSHOT" \
-DclassnName="FruitResource" \
-Dpath="fruit"
Run it
$mvn clean quarkus:dev
Check it is running
>curl http://localhost:8080/fruit
Hello from RESTEasy Reactive
Hello from RESTEasy Reactive
Create the package for jvm
$./mvnw -DskipTests clean package
Once create the package which is in target folder
$java -jar ./target/atomic-fruit-service-1.0-SNAPSHOT-runner.jar
It says no main manifest attribute
$ java -jar atomic-fruit-service-1.0-SNAPSHOT.jar
no main manifest attribute, in atomic-fruit-service-1.0-SNAPSHOT.jar
no main manifest attribute, in atomic-fruit-service-1.0-SNAPSHOT.jar
time 16:00
To create a native run
$ ./mnvw -DskipTests clean package -Pnative
Once the native package is ready, it can be run directly
$ ./target/atomic-fruti-service-1.0-SNAPSHOT-runner.jar
./mvnw -DskipTests clean package -Pnative -Dquarkus,native,container-build=true -Dquarkus.native.container-runtime=podman
./mvnw quarkus:add-extension -Dextension="quarkus-resteasy-jsonb, quarkus-jdbc-postgresql, quarkus-hibernate-orm-panache"
usan h2 luego postgres y luego hacen portforward
curl http://localhost:8080/fruit/Summer
curl -vvv -d '{"name": "Pineapple", "season":"Summer"}' -H "Content-Type: application/json" POST http://localhost:8080/fruit
./mvnw quarkus:add-extension -Dextensions="quarkus-smallrye-openapi"
$oc login
$export PROJECT_NAME="atomic-friut-k8s"
$kubectl create ns ${PROJECT_NAME}
$kubectl create deployment my-database --image=repository.access.redhat,com/rhscl/postgresql-10-rhel7:latest -n ${PROJECT_NAME}
$kubectl set env deployment/my-database POSTGRESQL_USER=luke POSTGRESQL_PASSWORD=secret POSTGRESQL_DATABASE=my_data -n ${PROJECT_NAME}
$kubectl expose deployment my-database --port=5432 --target-port=5432
$ oc get pod
o
$kubectl get pod
$ POD_NAME=$(kubectl get pod -o name | grep -v deploy)
$ kubectl port-forward ${POD_NAME} 5432
$ oc project atomic-fruit-k8s
$ oc get pod
application.properties
-----------------------------------
#log level settings
quarkus.log.category."com.redhat.atomic".level=DEBUG
#custom properties
hello.message = ${HELLO_MESSAGE:hello Meetup}
#Data Base
quarkus.hibernate-orm.log.sql=true
quarkus.hibernate-orm.database-generation=drop-and-create
quarkus,hibernate-orm.sql-load-script=import.sql
#%dev.quarkus.datasource.db-kind=h2
#%dev.quarkus.datasource.jdbc-url=jdbc:h2:mem:myDB
quarkus.datasource.db-kind=postgresql
quarkus.datasource.jdbc.url=jdbc:postgresql://my_database:5432/my_data
quarkus.datasource.username=luke
quarkus.datasource.password=secret
-----------------------------------------------
./mvnw quarkus:add-extension -Dextension="kubernetes"
o la de openshift
./mvnw quarkus:add-extension -Dextension="openshift"
./mvnw quarkus:remove-extension -Dextension="container-image-docker"
application.properties continuation
-------------------------------------
#Kubernetes client
quarkus.kubernetes-client.trust-certs=true
quarkus.kubernetes-client.namespace=${PROJECT_NAME:atomic-fruit-k8s}
#Labels and annotations
quarkus.kubernetes.part-of=fruits-app
quarkus.kubernetes.name=atomic-friut-service
quarkus.kubernetes.labels.foo=bar
quarkus.kubernetes.annotations.foo=bar
quarkus.kubernetes-annotations-"app.quarkus/id"=42
#Environment variables
quarkus.kubernetes.env.vars.DB_USERNAME=luke
quarkus.kubernetes.env.vars.DB_PASSWORD=secret
#Configure container registry
quarkus.container-image.registry=quay.io
quarkus.container-image.group=luisarizmendi
quarkus.container-image.username=luisarizmendi
-----------------------------------------
se crea archivo kubernetes/kubernetes.yml
kind: Ingress
metadata:
name: atomic-friut-service
spec:
rules:
- host: fruits.app.cluster-2036.2036.example.opentlc.com
http:
paths:
- path: /
pathType: prefix
backend:
serviceName: atomic-friut-service
servicePort: 8080
--------------------------------------------------
Comparte pantalla CArlos Vicens
github.com/cvicens/atomic-fruit-service/blob/master/quarkus-meetup.md
Testing Quarkus App -Part 1 Daniel Oh
Testing in JVM mode
Testing in native mode
Injection of resources into tests
EXTENSION
<dependency>
<grougid>io.quarkus</grougid>
<artifactId>quarkus-junit5</artifactId>
<version>${quarkus.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<grougid>io.rest-assured</grougid>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
PLUGIN
<artifactid>maven-surefire-plugin</artifactid>
<version>${surefire-plugin.version}</version>
<configuration>
<systemPropertyVariables>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
</systemPropertiesVariables>
</Configuration>
</plugin>
Mock Support
- CDI alternatives
@Mock
@ApplicationScoped
public class MockExternalService extends ExternalService {
@Override
public String service(){
return "mock";
}
}
- Using QuarkusMock
@BeforeAll
public static void setup() {
MockeableBean1 mock = Mockito.mock(MockeableBean1.class);
Mockito.when(mock.greet("Stuart")).thenReturn("A mock for stuart");
QuarkusMock.installMockForType(mock, MockeableBean1.class);
}
From example quarkus-rest-client-reactive
mvn verify
Lets add an endpoint with param
example...
Test a CDI alternative with an example, create a service and inject with @Inject
example..
Change testp-port
application.properties
quarkus.http.test-port=8083
Debugging Quarkus App -Part II
Create a new endpoint for test debug
In STS4 with Quarkus marketplace runs fine.
Deploying Quarkus App to OpenShift - Part IV
Example
Quarkus | Complete Quarkus Tutorial
1.- How to create a Quakus project with code.quarkus.io.
2.- How to create a Quakus project with apache maven.
3.- How to enable live Reload in Quarkus.
4.- How to add a new Quarkus extension inside a project.
5.- RESTful Web Service with Quarkus.
6.- Microprofile OpenApi with Quarkus.
7.- Swagger-ui with Quarkus.
8.- Microprofile Restclient with Quarkus.
9.- Enable CORS Filter in Quarkus.
10.- Quarkus Reactive SQL Clients with PostgresSQL.
11.- Microprofile Fault Tolerance with Quarkus Part 1.
12.- Microprofile Fault Tolerance with Quarkus Part 2.
13.- Microprofile Rest Client with TLS Authentication
14.- Hibernate ORM PanacheEntity with PostgresSQL.
15.- Hibernate ORM Panache Repository with PostgresSQL.
16.- Testing Quarkus application with RestAssured and H2 Database.
17.- MicroProfile Config with Quarkus.
18.- How to use YAML configuration with Quarkus.
19.- Testing Quarkus application with Junit5, Mockito and H2 Database.
20.- How to use configuration profiles in Quarkus.
21.- How to use logging in Quarkus.
22.- How to enable Json Logging in Quarkus.
23.- Undestanding application initialization and termination in Quarkus.
24.- Testing a Quarkus application with WireMock and Rest Assured.
25.- How to debug a Quarkus application with Intelij IDEA.
26.- MicroProfile Health with Quarkus.
27.- MicroProfile Metrics with Quarkus.
28.- How to package a Quarkus Application.
29.- How to compile a Quarkus Application in Native Mode.
30.- Docketize a Quarkus application with Dockerfiles.
31.- Dockerize Quarkus application with Apache Maven.
32.- Java bean mappings with MapStruct and Quarkus.
33.- How to use MapStruct to merge 2 Java Beans.
34.- Debug Quarkus application with Visual Studio Code.
35.- How to use Project Lombok inside Quarkus application.
36.- Setup Visual Studio Code with Java and Quarkus extensions.
37.- Create a Quarkus project using MongoDB.
38.- How to use Quarkus Command Mode.
39.- TDD approach with Continuous Testing in Quarkus.
40.- Containers Tutorials Part 1 - Containerize Java Application. Docker.
41.- #1 How to use Hibernate Validator extension with Quarkus.
42.- #2 How to use Hibernate Validator extension with Quarkus.
43.- How to use Flyway DB migration Tool sqlscript.
44 .- How to use Flyway DB migration Tool java-based migration.
45.- Authentication and Authorization using JWT and Roles-based access control.
46.- How to schedule periodic tasks with Quarkus.
47.- How to use to use the Test Security extension with Quarkus.
48.- How to use Dev Services in Quarkus 2.x.
Playlist Microprofile Specifications
1.- Microprofile OpenAPI with Quarkus | Complete Tutorial | QUARKUS | Small Rye
2.- Microprofile RestClient with Quarkus | Complete Tutorial | QUARKUS | Resteasy | Java
3.- Microprofile Fault Tolerance with Quarkus Part I | Quarkus Tutorial | QUARKUS | SmallRye
4.- Microprofile Fault Tolerance with Quarkus Part 2 | Timeout | CircuitBreaker | Quarkus Tutorial
5.- MicroProfile Config with Quarkus | Quarkus Tutorial | QUARKUS | MicroProfile | Java
6.- MicroProfile Health with Quarkus | Quarkus Tutorial | QUARKUS | MicroProfile | Java | CloudNative
7.- MicroProfile Metrics with Quarkus | Quarkus Tutorial | QUARKUS | MicroProfile | Java | CloudNative
@Counted
@Timed
@Metered
@Gauge
6.- Microprofile OpenApi with Quarkus.
On the class
@Tag(name="Movie Resource" description="Movie REST APIs")
On the method
@Operation(operationId="getMovies",
summary="Get Movies",
description="Get all movies inside the list")
@APIResponse(responseCode="200",
description="Operation completed",
content=@Content(mediaType=MediaType.APPLICATION_JSON)
)
In Parameter method create
public Response createMovie(
@RequestBody( description="Movie to create",
required="true",
content= @Content(schema=@schema(implementation=Movie.class)
)
Movie newMovie) { ...
On Movie.class
@Schema(name="Movie", description="Movie presentation")
public class Movie {...
...
@Schema(required=true)
private String Title;
...
Document a parameter on updateMovie with @Parameter annotation
public Response updateMovie(
@Parameter(
description="Movie id",
required = "true"
)
@PathParameter("id") Long id;
....
To document the app use @OpenApiDefinition
@OpenApiDefinition(
info= @info(title ="Movie APIs",
description="Movie Application",
version="1.0.0",
license=@license(
name="MIT",
url="http://localhost:8080"
)
),
tags = {
@Tag(name="movies", description="Movies app")}
)
public class MovieApplication extend Application{
}
10.- Quarkus Reactive SQL Clients with PostgresSQL.
Multi<Movie>
Uni<Movie>
PgPool client;
Multi<Movie> ,
client.query("s ql instruction")
.flatMap(sql instruction)
.flatMap(sql instruction)
.await()
.indefinitely();
...onItem().transform(Movie::from);
$docker run --name my_reactive_db -e POSTGRES_USER=user -e POSTGRES_PASSWORD=password -e POSTGRES_DB=my_db -p 5432:5432 postgres:10.5
application.properties
quarkus.datasource.db-kind=postgres
quarkus.datasource.username=user
quarkus.datasource.password=password
quarkus.datasource.reactive.url=postgresql://localhost:5432/my_db
@GET
@PATH("{id}")
public Uni<Response> get(@PathParam("id") Long id) {
return Movie.findById(client, id)
.onItem()
.transform(movie -> movie != null ? Response.ok(movie) : Response.status(Reponse.Status.NOT_FOUND))
.onItem()
.transform(Response.ResponseBuilder::build);
}
public static Uni<Long> save(PgPoll client, String title) {
return client
.prepareQuery("INSERT INTO movies (title) VALUE ($1) RETURNING id")
.execute(Tuple.of(title))
.onItem()
.transform(m -> m.iterator().next().getLong("id");
}
@POST
public Uni<Response> create(Movie movie){
return Movie.save(client, movie.getTitle())
.onItem()
.transform(id -> URI.create("/movies/" + id))
.onItem()
.transform(uri -> Response.created().build())
}
public statuc Uni<Boolean> delete(PgPool client, Long id) {
return client
.prepareQuery("DELETE FROM movies WHERE id = $1")
.execute(Tuple.of(id))
.onItem()
.transform( m -> m.rowCount() == 1);
}
@DELETE
@Path("{id}")
public Uni<Response> delete(@PathParam("id") Long id){
return Movie.delete(client, id)
.onItem()
.trasnform(deleted -> deleted ? Response.status(Response.Status.NO_CONTENT): Response.status(Response.status.NOT_FOUND))
}
OR
@DELETE
@Path("{id}")
public Uni<Response> delete(@PathParam("id") Long id){
return Movie.delete(client, id)
.onItem()
.trasnform(deleted -> deleted ? Response.Status.NO_CONTENT : Response.status.NOT_FOUND)
.onItem()
.transform(status -> Response.status(status).build());
}
11.- Microprofile Fault Tolerance with Quarkus Part 1.
Fault tolerance is about leveraging defferent strategies to guide the excecution and result of some logic. Retry Policies, Bulkheads, circuit breakers. fallbacks
- Timeout.
- retry.
- fallbacks.
- CircuitBreaker.
- BulkHead. isolate failures in part of the system while the rest part of the system can still function.
12.- Microprofile Fault Tolerance with Quarkus Part 2.
Create a basic quarkus application RESTEasy JAX-RS and Jackson, clean unnecessary code.
application.properties
quarkus.http.port=8081
quarkus.http.access-log.enabled=true
Another basic quarkus application RESTEasy JAX-RS, Jackson, REST Client, REST Client Jackson.
Test
$while true; do sleep 1; curl http://localhost:8080/message; echo -e '\n'; done
quarkus-service-message
MessageResource.java
-------------------------
quarkus-rest-client
MessageResource.java
@Path("/message")
public class MessageResource {
@RestClient
MessageClient client;
@GET
@Timeout(200)
@CircuitBreaker( requestVolumeThreshold = 4,
failureRatio = 0.5,
delay = 4000,
successThreshold = 2)
@Fallback(fallbackMethod = "fallbackMessage")
public String message() {
return client.get();
}
private String fallbackMessage() {
return "Fallback Message";
}
}
-------------------------
quarkus-service-message
INFO ....
"GET /message HTTP/1.1 200 34"
INFO ...
"GET /message HTTP/1.1 200 34"
quarkus-rest-client
Fallback Message
Fallback Message
Fallback Message
Fallback Message
When
@CircuitBreaker( requestVolumeThreshold = 4,
failureRatio = 0.5,
delay = 8000,
successThreshold = 2)
The quarkus-rest-client
Fallback Message
Fallback Message
Fallback Message
Fallback Message
Fallback Message
Fallback Message
Fallback Message
Fallback Message
Also
@GET
@Timeout(200)
@Retry(maxRetries = 1)
@Fallback(fallbackMethod = "fallbackMessage") OR
@GET
@Timeout(200)
@Retry(maxRetries = 4)
@Fallback(fallbackMethod = "fallbackMessage") 13.- Microprofile Rest Client with TLS Authentication
quarkus.io/blog/quarkus-mutual-tls
Learn how to do mutual TLS in Quarkus apps.
Create quarkus project simple without extensions for now
quarkus-restclient-tls
Now a new Module "quarkus-server" with extensions RESTEasy JAX-RS, RESTEasy Jackson
modify application.properties to disable port and enable another secure port
quarkus.http.ssl.certificate.key-store-file=META-INF/resources/server.keystore |
quarkus.http.ssl.certificate.key-store-password=server_password |
quarkus.http.port=0 |
quarkus.http.ssl.client-auth=required |
|
quarkus.http.ssl.certificate.trust-store-file=META-INF/resources/client.truststore |
quarkus.http.ssl-port=8443 |
create keystore
quarkus-server/src/main/resources/META-INF.resources/generate_server_keystore.sh
keytool -genkeypair \
-storepass server_password \
-keyalg RSA \
-keysize 2048 \
-dname "CN=server" \
-alias server \
-ext "SAN:c=DNS:localhost, IP:127.0.0.1" \
-keystore server.keystore
This shell script creates .../META-INF.resources/server.keystore
14.- Hibernate ORM PanacheEntity with PostgresSQL.
Create Project quarkus-hibernate-orm-panache-entity
web->RESTEasy JAX-RS,RESTEasy Jackson
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getAll() {
List<Movie> movies = Movie.listALL();
return Response.ok(movies).build();
}
@GET
@Path("{id]")
@Produces(MediaType.APPLICATION_JSON)
public Response getById(@PathParam("id") Long id) {
return Movie.findByIdOptional(id)
.map(movie -> Response.ok(movie).build())
.orElse(Response.status(Response.Status.NOT_FOUND).build());
}
@GET
@Path("country/{contry}"
@Produces(MediaType.APPLICATION_JSON)
public Response getByCountry(@PathParam("country") String country) {
List<Movie> movies = Movie.List("SELECT m FROM MOvie m WHERE m.country = ?1 ORDER BY id " + "DESC", country);
return Reponse.ok(movies).build();
}
@GET
@Path("title/{title}"
@Produces(MediaType.APPLICATION_JSON)
public Response getByTitle(@PathParam("title") String title) {
return Movie.find("title", title)
.singleResultOptional()
.map(movie -> Response.ok(movie).build())
.orElse(Response.status(Response.Status.NOT_FOUND).build());
}
@POST
@Transactional
@Produces(MEdiaType.APPLICATON_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response create(Movie movie) {
Movie.persist(movie);
if (movie.isPersistent()){
return Response.created(URI.create("/movies" + movie.id)).build();
}
return Response.status(Response.Status.BAD_REQUEST).build();
}
@DELETE
@Transactional
@Path("id")
@Produces(MEdiaType.APPLICATON_JSON)
public REsponse deleteById(@PathPAram("id") Long id) {
boolean deleted = Movie.delete(id);
if (deleted) {
return Response.noContent().build();
}
return Response.status(Response.Status.BAD_REQUEST).build();
}
Docker
$docker run --name my_db_movie -e POSTGRES_USER=username -e POSTGRES_PASSWORD=password -e POSTGRES_DB=my_db_movie -p 5432:5432 postgres:10.5
aplication.properteis
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/my_db_movie
...
quarkus.hibernate-orm.database.generation=drop-and-create
add extension quarkus-hibernate-orm-panache
add extension quarkus-jdbc-postgresql
15.- Hibernate ORM Panache Repository with PostgresSQL.
Create Project quarkus-hibernate-orm-panache-repository
web->RESTEasy JAX-RS,RESTEasy Jackson
data->Hibenate ORM with Panache, JDBC Driver PostgresSQL,Agroal - Database connection pool
blabla
16.- Testing Quarkus application with RestAssured and H2 Database.
bla bla
Deploying Quarkus App to OpenShift - Part IV
Daniel Oh
src/main/resources/application.properties
...
quarkus.kubernetes-client.trust-certs=true
quarkus.container-image.build=true
quarkus.kubernetes.deploy=true
quarkus.kubernetes.deployment-target=openshift
quarkus.openshift.expose=true
quarkus.openshift.labels.app.openshift.io/runtime=quarkus
quarkus.s2i.base-jvm-image=registry.access.redhat.com/ubi8/openjdk-11
quarkus.container-image.build=true
quarkus.kubernetes.deploy=true
quarkus.kubernetes.deployment-target=openshift
quarkus.openshift.expose=true
quarkus.openshift.labels.app.openshift.io/runtime=quarkus
quarkus.s2i.base-jvm-image=registry.access.redhat.com/ubi8/openjdk-11
add openshift extension
$ ./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-openshift"