miércoles, 27 de septiembre de 2023

Quarkus

 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"
 
Run it
$mvn  clean quarkus:dev

Check it is running
>curl http://localhost:8080/fruit
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
 
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.certificate.trust-store-password=client_password
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

Test with Postman de movie crud

 
  

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 

add openshift extension

$ ./mvnw quarkus:add-extension -Dextensions="io.quarkus:quarkus-openshift"

No hay comentarios:

Publicar un comentario