├── first-step
├── src
│ ├── main
│ │ ├── resources
│ │ │ └── application.properties
│ │ └── java
│ │ │ └── org
│ │ │ └── agoncal
│ │ │ └── fascicle
│ │ │ └── quarkus
│ │ │ └── firststep
│ │ │ └── AuthorResource.java
│ └── test
│ │ └── java
│ │ └── org
│ │ └── agoncal
│ │ └── fascicle
│ │ └── quarkus
│ │ └── firststep
│ │ └── AuthorResourceTest.java
└── pom.xml
├── event-inventory
├── src
│ ├── main
│ │ ├── resources
│ │ │ ├── application.properties
│ │ │ └── META-INF
│ │ │ │ └── resources
│ │ │ │ └── index.html
│ │ ├── java
│ │ │ └── org
│ │ │ │ └── agoncal
│ │ │ │ └── fascicle
│ │ │ │ └── quarkus
│ │ │ │ └── inventory
│ │ │ │ └── InventoryResource.java
│ │ └── docker
│ │ │ ├── Dockerfile.native-distroless
│ │ │ ├── Dockerfile.native
│ │ │ ├── Dockerfile.legacy-jar
│ │ │ └── Dockerfile.jvm
│ └── test
│ │ └── java
│ │ └── org
│ │ └── agoncal
│ │ └── fascicle
│ │ └── quarkus
│ │ └── inventory
│ │ ├── NativeInventoryResourceIT.java
│ │ └── InventoryResourceTest.java
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.properties
│ │ └── MavenWrapperDownloader.java
└── pom.xml
├── rest-number
├── health-origin.json
├── health.json
├── curl-dummy.json
├── curl.json
├── curl-origin.json
├── openapi-origin.yaml
├── curl-origin-separator.json
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.properties
│ │ └── MavenWrapperDownloader.java
├── logs.txt
├── src
│ ├── test
│ │ └── java
│ │ │ └── org
│ │ │ └── agoncal
│ │ │ └── fascicle
│ │ │ └── quarkus
│ │ │ └── number
│ │ │ ├── NativeNumberResourceIT.java
│ │ │ └── NumberResourceTest.java
│ └── main
│ │ ├── resources
│ │ ├── application.properties
│ │ └── META-INF
│ │ │ └── resources
│ │ │ └── index.html
│ │ ├── docker
│ │ ├── Dockerfile.native-distroless
│ │ ├── Dockerfile.native
│ │ ├── Dockerfile.legacy-jar
│ │ └── Dockerfile.jvm
│ │ └── java
│ │ └── org
│ │ └── agoncal
│ │ └── fascicle
│ │ └── quarkus
│ │ └── number
│ │ ├── health
│ │ └── PingNumberResourceHealthCheck.java
│ │ ├── NumberApplication.java
│ │ ├── BookNumbers.java
│ │ ├── NumberApplicationLifeCycle.java
│ │ └── NumberResource.java
├── logs-origin.txt
├── startup-prod.txt
├── startup-origin.txt
├── metrics.json
├── startup.txt
├── startup-profile.txt
├── test.txt
└── openapi.yaml
├── ui-vintagestore
├── src
│ ├── main
│ │ ├── resources
│ │ │ ├── application.properties
│ │ │ ├── META-INF
│ │ │ │ └── resources
│ │ │ │ │ └── index.html
│ │ │ └── default_banner.txt
│ │ └── docker
│ │ │ └── Dockerfile.native
│ ├── environments
│ │ ├── environment.prod.ts
│ │ └── environment.ts
│ ├── favicon.ico
│ ├── app
│ │ ├── app.component.ts
│ │ ├── shared
│ │ │ ├── model
│ │ │ │ ├── bookNumbers.ts
│ │ │ │ └── book.ts
│ │ │ └── api
│ │ │ │ └── numberEndpoint.service.ts
│ │ ├── inventory
│ │ │ ├── inventory-routing.module.ts
│ │ │ └── inventory.module.ts
│ │ ├── number
│ │ │ ├── number-routing.module.ts
│ │ │ ├── number.module.ts
│ │ │ └── number-generate
│ │ │ │ ├── number-generate.component.ts
│ │ │ │ └── number-generate.component.html
│ │ ├── book
│ │ │ ├── book-random
│ │ │ │ ├── book-random.component.html
│ │ │ │ └── book-random.component.ts
│ │ │ ├── book-delete
│ │ │ │ ├── book-delete.component.html
│ │ │ │ └── book-delete.component.ts
│ │ │ ├── book-list
│ │ │ │ ├── book-list.component.ts
│ │ │ │ └── book-list.component.html
│ │ │ ├── book-detail
│ │ │ │ ├── book-detail.component.ts
│ │ │ │ └── book-detail.component.html
│ │ │ ├── book-form
│ │ │ │ ├── book-form.component.ts
│ │ │ │ └── book-form.component.html
│ │ │ ├── book-routing.module.ts
│ │ │ └── book.module.ts
│ │ ├── app.module.ts
│ │ ├── app-routing.module.ts
│ │ └── app.component.html
│ ├── jumbotron.scss
│ ├── index.html
│ ├── main.ts
│ └── polyfills.ts
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.properties
│ │ └── MavenWrapperDownloader.java
├── package.sh
├── tsconfig.app.json
├── browserslist
├── tsconfig.json
├── package.json
├── angular.json
├── README.md
└── pom.xml
├── cover.jpg
├── .dockerignore
├── dist
└── agoncal-fascicle-quarkus-practising-2.0.zip
├── rest-book
├── src
│ ├── main
│ │ ├── resources
│ │ │ ├── default_banner.txt
│ │ │ ├── application.properties
│ │ │ └── META-INF
│ │ │ │ └── resources
│ │ │ │ └── index.html
│ │ ├── java
│ │ │ └── org
│ │ │ │ └── agoncal
│ │ │ │ └── fascicle
│ │ │ │ └── quarkus
│ │ │ │ └── book
│ │ │ │ ├── client
│ │ │ │ ├── IsbnNumbers.java
│ │ │ │ └── NumberProxy.java
│ │ │ │ ├── health
│ │ │ │ ├── PingBookResourceHealthCheck.java
│ │ │ │ └── DatabaseConnectionHealthCheck.java
│ │ │ │ ├── BookApplication.java
│ │ │ │ ├── Book.java
│ │ │ │ └── BookService.java
│ │ └── docker
│ │ │ ├── Dockerfile.native-distroless
│ │ │ ├── Dockerfile.native
│ │ │ ├── Dockerfile.legacy-jar
│ │ │ └── Dockerfile.jvm
│ └── test
│ │ └── java
│ │ └── org
│ │ └── agoncal
│ │ └── fascicle
│ │ └── quarkus
│ │ └── book
│ │ ├── NativeBookResourceIT.java
│ │ ├── client
│ │ └── MockNumberProxy.java
│ │ └── BookTest.java
├── book.json
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.properties
│ │ └── MavenWrapperDownloader.java
├── health.json
├── curl.json
└── openapi.yaml
├── load-vintagestore
├── .mvn
│ └── wrapper
│ │ ├── maven-wrapper.properties
│ │ └── MavenWrapperDownloader.java
├── src
│ └── main
│ │ └── java
│ │ └── org
│ │ └── agoncal
│ │ └── fascicle
│ │ └── quarkus
│ │ └── load
│ │ ├── VintageStoreLoad.java
│ │ ├── WeightedRandomResult.java
│ │ ├── ScenarioNumber.java
│ │ ├── ScenarioInvoker.java
│ │ ├── Endpoint.java
│ │ └── ScenarioBook.java
└── pom.xml
├── bootstrap-dummy.sh
├── assembly.sh
├── bootstrap-ui-vintagestore.sh
├── infrastructure
├── prometheus.yaml
├── postgresql.yaml
├── monitoring
│ ├── prometheus-linux.yml
│ └── prometheus.yml
├── pom.xml
└── vintage-store-app.yaml
├── bootstrap-first-step.sh
├── .editorconfig
├── bootstrap-event-inventory.sh
├── .gitignore
├── bootstrap-rest-number.sh
├── bootstrap-rest-book.sh
├── LICENSE
├── pom_to_be_renamed.xml
├── assembly.xml
├── pom.xml
└── README.md
/first-step/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/event-inventory/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/rest-number/health-origin.json:
--------------------------------------------------------------------------------
1 | {
2 | "status": "UP",
3 | "checks": []
4 | }
5 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | quarkus.http.port=8700
2 |
--------------------------------------------------------------------------------
/cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agoncal/agoncal-fascicle-quarkus-pract/HEAD/cover.jpg
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | *
2 | !target/*-runner
3 | !target/*-runner.jar
4 | !target/lib/*
5 | !target/quarkus-app/*
6 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agoncal/agoncal-fascicle-quarkus-pract/HEAD/ui-vintagestore/src/favicon.ico
--------------------------------------------------------------------------------
/dist/agoncal-fascicle-quarkus-practising-2.0.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/agoncal/agoncal-fascicle-quarkus-pract/HEAD/dist/agoncal-fascicle-quarkus-practising-2.0.zip
--------------------------------------------------------------------------------
/rest-number/health.json:
--------------------------------------------------------------------------------
1 | {
2 | "status": "UP",
3 | "checks": [
4 | {
5 | "name": "Ping Number REST Endpoint",
6 | "status": "UP"
7 | }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/rest-number/curl-dummy.json:
--------------------------------------------------------------------------------
1 | {
2 | "asin": "dummy",
3 | "ean_13": "7438504344437",
4 | "ean_8": "38833700",
5 | "isbn_10": "1-383-10381-X",
6 | "isbn_13": "978-0-929138-68-8"
7 | }
8 |
--------------------------------------------------------------------------------
/rest-number/curl.json:
--------------------------------------------------------------------------------
1 | {
2 | "asin": "B000A3PI3G",
3 | "ean_13": "7438504344437",
4 | "ean_8": "38833700",
5 | "isbn_10": "1-383-10381-X",
6 | "isbn_13": "978-0-929138-68-8"
7 | }
8 |
--------------------------------------------------------------------------------
/rest-book/src/main/resources/default_banner.txt:
--------------------------------------------------------------------------------
1 | ______ _
2 | | ___ \ | |
3 | | |_/ / ___ ___ | | __
4 | | ___ \/ _ \ / _ \| |/ /
5 | | |_/ / (_) | (_) | <
6 | \____/ \___/ \___/|_|\_\
7 |
--------------------------------------------------------------------------------
/rest-book/book.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": 0,
3 | "author": "Antonio Goncalves",
4 | "isbn10": "to be fixed",
5 | "isbn13": "to be fixed",
6 | "title": "Practising Quarkus",
7 | "yearOfPublication": 2020
8 | }
9 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/main/resources/META-INF/resources/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/rest-number/curl-origin.json:
--------------------------------------------------------------------------------
1 | {
2 | "asin": "B0000AB07P",
3 | "ean13": "6615352338240",
4 | "ean8": "13354022",
5 | "generationDate": "2020-01-11T09:25:18.541227Z",
6 | "isbn10": "1932563601",
7 | "isbn13": "9791961975483"
8 | }
9 |
--------------------------------------------------------------------------------
/rest-number/openapi-origin.yaml:
--------------------------------------------------------------------------------
1 | openapi: 3.0.3
2 | info:
3 | title: rest-number API
4 | version: 2.0.0-SNAPSHOT
5 | paths:
6 | /api/numbers:
7 | get:
8 | responses:
9 | "200":
10 | description: OK
11 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 |
3 | @Component({
4 | selector: 'bs-root',
5 | templateUrl: "app.component.html",
6 | styles: []
7 | })
8 | export class AppComponent {
9 | }
10 |
--------------------------------------------------------------------------------
/rest-number/curl-origin-separator.json:
--------------------------------------------------------------------------------
1 | {
2 | "asin": "B0000AB07P",
3 | "ean13": "6615352338240",
4 | "ean8": "13354022",
5 | "generationDate": "2020-01-11T09:25:18.541227Z",
6 | "isbn10": "1-932563-60-1",
7 | "isbn13": "979-1-9619754-8-3"
8 | }
9 |
--------------------------------------------------------------------------------
/rest-book/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/rest-number/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/jumbotron.scss:
--------------------------------------------------------------------------------
1 | /* Move down content because we have a fixed navbar that is 3.5rem tall */
2 | body {
3 | padding-top: 3.5rem;
4 | }
5 |
6 | .jumbotron {
7 | padding: 1rem 1rem;
8 | }
9 |
10 | .container {
11 | margin-left: 10px;
12 | }
13 |
--------------------------------------------------------------------------------
/event-inventory/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/load-vintagestore/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/ui-vintagestore/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/bootstrap-dummy.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # tag::adocBootstrap[]
3 | mvn io.quarkus:quarkus-maven-plugin:2.5.0.Final:create \
4 | -DplatformVersion=2.5.0.Final \
5 | -DprojectGroupId=org.agoncal.fascicle.quarkus-practising \
6 | -DprojectArtifactId=dummy
7 | # end::adocBootstrap[]
8 |
--------------------------------------------------------------------------------
/rest-number/logs.txt:
--------------------------------------------------------------------------------
1 | 16:02:28 INFO [i.quarkus] Quarkus started in 1.125s. Listening on: http://localhost:8701
2 | 16:02:28 INFO [i.quarkus] Profile dev activated. Live Coding activated.
3 | 16:02:28 INFO [i.quarkus] Installed features: [cdi, resteasy, resteasy-jsonb, smallrye-openapi, swagger-ui]
4 |
--------------------------------------------------------------------------------
/ui-vintagestore/package.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # tag::adocSnippet[]
3 | export DEST=src/main/resources/META-INF/resources
4 | ./node_modules/.bin/ng build --prod --base-href "."
5 | rm -Rf ${DEST}/ui-vintagestore
6 | mkdir -p ${DEST}/ui-vintagestore
7 | cp -R dist/* ${DEST}
8 | # end::adocSnippet[]
9 |
10 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/shared/model/bookNumbers.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Several formats of book numbers
3 | */
4 | // tag::adocSnippet[]
5 | export interface BookNumbers {
6 | asin?: string;
7 | ean_13?: string;
8 | ean_8?: string;
9 | isbn_10: string;
10 | isbn_13: string;
11 | }
12 | // end::adocSnippet[]
13 |
--------------------------------------------------------------------------------
/assembly.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | cp pom.xml dummy.pom.xml
3 | mv pom_to_be_renamed.xml pom.xml
4 |
5 | mvn assembly:single
6 |
7 | mv pom.xml pom_to_be_renamed.xml
8 | cp dummy.pom.xml pom.xml
9 |
10 | mv dist/agoncal-fascicle-quarkus-practising-2.0.0-SNAPSHOT.zip dist/agoncal-fascicle-quarkus-practising-2.0.zip
11 |
--------------------------------------------------------------------------------
/bootstrap-ui-vintagestore.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | mvn io.quarkus:quarkus-maven-plugin:2.5.0.Final:create \
3 | -DplatformVersion=2.5.0.Final \
4 | -DprojectGroupId=org.agoncal.fascicle.quarkus-practising \
5 | -DprojectArtifactId=ui-vintagestore \
6 | -DprojectVersion=2.0.0-SNAPSHOT \
7 | -Dextensions="undertow"
8 |
--------------------------------------------------------------------------------
/rest-book/src/test/java/org/agoncal/fascicle/quarkus/book/NativeBookResourceIT.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.book;
2 |
3 | import io.quarkus.test.junit.NativeImageTest;
4 |
5 | @NativeImageTest
6 | public class NativeBookResourceIT extends BookResourceTest {
7 |
8 | // Execute the same tests but in native mode.
9 | }
10 |
--------------------------------------------------------------------------------
/infrastructure/prometheus.yaml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | # tag::adocSnippet[]
3 | services:
4 | monitoring:
5 | image: "prom/prometheus:v2.31.1"
6 | container_name: "vintage_store_monitoring"
7 | ports:
8 | - 9090:9090
9 | volumes:
10 | - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
11 | # end::adocSnippet[]
12 |
--------------------------------------------------------------------------------
/rest-number/src/test/java/org/agoncal/fascicle/quarkus/number/NativeNumberResourceIT.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.number;
2 |
3 | import io.quarkus.test.junit.NativeImageTest;
4 |
5 | @NativeImageTest
6 | public class NativeNumberResourceIT extends NumberResourceTest {
7 |
8 | // Execute the same tests but in native mode.
9 | }
10 |
--------------------------------------------------------------------------------
/event-inventory/src/test/java/org/agoncal/fascicle/quarkus/inventory/NativeInventoryResourceIT.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.inventory;
2 |
3 | import io.quarkus.test.junit.NativeImageTest;
4 |
5 | @NativeImageTest
6 | public class NativeInventoryResourceIT extends InventoryResourceTest {
7 |
8 | // Execute the same tests but in native mode.
9 | }
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/inventory/inventory-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { Routes, RouterModule } from '@angular/router';
3 |
4 |
5 | const routes: Routes = [];
6 |
7 | @NgModule({
8 | imports: [RouterModule.forChild(routes)],
9 | exports: [RouterModule]
10 | })
11 | export class InventoryRoutingModule { }
12 |
--------------------------------------------------------------------------------
/rest-book/health.json:
--------------------------------------------------------------------------------
1 | {
2 | "status": "UP",
3 | "checks": [
4 | {
5 | "name": "Ping Book REST Endpoint",
6 | "status": "UP"
7 | },
8 | {
9 | "name": "Book Datasource connection health check",
10 | "status": "UP",
11 | "data": {
12 | "Number of books in the database": 102
13 | }
14 | }
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/rest-number/logs-origin.txt:
--------------------------------------------------------------------------------
1 | 2020-01-15 15:56:19,218 INFO [io.quarkus] (main) Quarkus started in 1.125s. Listening on: http://localhost:8701
2 | 2020-01-15 15:56:19,219 INFO [io.quarkus] (main) Profile dev activated. Live Coding activated.
3 | 2020-01-15 15:56:19,219 INFO [io.quarkus] (main) Installed features: [cdi, resteasy, resteasy-jsonb, smallrye-openapi, swagger-ui]
4 |
--------------------------------------------------------------------------------
/infrastructure/postgresql.yaml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | # tag::adocSnippet[]
3 | services:
4 | database:
5 | image: "postgres:14.1"
6 | container_name: "vintage_store_books_database"
7 | ports:
8 | - "5432:5432"
9 | environment:
10 | - POSTGRES_DB=books_database
11 | - POSTGRES_USER=book
12 | - POSTGRES_PASSWORD=book
13 | # end::adocSnippet[]
14 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | VintageStore
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/ui-vintagestore/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/app",
6 | "types": []
7 | },
8 | "files": [
9 | "src/main.ts",
10 | "src/polyfills.ts"
11 | ],
12 | "include": [
13 | "src/**/*.d.ts"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/bootstrap-first-step.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | mvn io.quarkus:quarkus-maven-plugin:2.5.0.Final:create \
3 | -DplatformVersion=2.5.0.Final \
4 | -DprojectGroupId=org.agoncal.fascicle.quarkus-practising \
5 | -DprojectArtifactId=first-step \
6 | -DprojectVersion=2.0.0-SNAPSHOT \
7 | -DclassName="org.agoncal.fascicle.quarkus.firststep.AuthorResource" \
8 | -Dpath="/authors"
9 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/inventory/inventory.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 |
4 | import { InventoryRoutingModule } from './inventory-routing.module';
5 |
6 |
7 | @NgModule({
8 | declarations: [],
9 | imports: [
10 | CommonModule,
11 | InventoryRoutingModule
12 | ]
13 | })
14 | export class InventoryModule { }
15 |
--------------------------------------------------------------------------------
/rest-book/src/main/java/org/agoncal/fascicle/quarkus/book/client/IsbnNumbers.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.book.client;
2 |
3 | import javax.json.bind.annotation.JsonbProperty;
4 |
5 | // tag::adocSnippet[]
6 | public class IsbnNumbers {
7 |
8 | @JsonbProperty("isbn_10")
9 | public String isbn10;
10 | @JsonbProperty("isbn_13")
11 | public String isbn13;
12 | }
13 | // end::adocSnippet[]
14 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 |
4 | import { AppModule } from './app/app.module';
5 | import { environment } from './environments/environment';
6 |
7 | if (environment.production) {
8 | enableProdMode();
9 | }
10 |
11 | platformBrowserDynamic().bootstrapModule(AppModule)
12 | .catch(err => console.error(err));
13 |
--------------------------------------------------------------------------------
/load-vintagestore/src/main/java/org/agoncal/fascicle/quarkus/load/VintageStoreLoad.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.load;
2 |
3 | // tag::adocSnippet[]
4 | public class VintageStoreLoad {
5 |
6 | public static void main(String[] args) {
7 | Thread bookScenario = new Thread(new ScenarioBook());
8 | bookScenario.start();
9 | Thread numberScenario = new Thread(new ScenarioNumber());
10 | numberScenario.start();
11 | }
12 | }
13 | // end::adocSnippet[]
14 |
--------------------------------------------------------------------------------
/event-inventory/src/main/java/org/agoncal/fascicle/quarkus/inventory/InventoryResource.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.inventory;
2 |
3 | import javax.ws.rs.GET;
4 | import javax.ws.rs.Path;
5 | import javax.ws.rs.Produces;
6 | import javax.ws.rs.core.MediaType;
7 |
8 | @Path("/api/inventory")
9 | public class InventoryResource {
10 |
11 | @GET
12 | @Produces(MediaType.TEXT_PLAIN)
13 | public String hello() {
14 | return "Hello RESTEasy";
15 | }
16 | }
--------------------------------------------------------------------------------
/ui-vintagestore/browserslist:
--------------------------------------------------------------------------------
1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 |
5 | # You can see what browsers were selected by your queries by running:
6 | # npx browserslist
7 |
8 | > 0.5%
9 | last 2 versions
10 | Firefox ESR
11 | not dead
12 | not IE 9-11 # For IE 9-11 support, remove 'not'.
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 |
9 | # Change these settings to your own preference
10 | indent_style = space
11 | indent_size = 2
12 |
13 | # We recommend you to keep these unchanged
14 | end_of_line = lf
15 | charset = utf-8
16 | trim_trailing_whitespace = true
17 | insert_final_newline = true
18 |
19 | [*.md]
20 | trim_trailing_whitespace = false
21 |
--------------------------------------------------------------------------------
/infrastructure/monitoring/prometheus-linux.yml:
--------------------------------------------------------------------------------
1 | global:
2 | scrape_interval: 15s
3 |
4 | # tag::adocPrometheus[]
5 | scrape_configs:
6 | - job_name: 'prometheus'
7 | static_configs:
8 | - targets: ['localhost:9090']
9 | - job_name: 'number'
10 | metrics_path: '/q/metrics'
11 | static_configs:
12 | - targets: ['localhost:8701']
13 | - job_name: 'book'
14 | metrics_path: '/q/metrics'
15 | static_configs:
16 | - targets: ['localhost:8702']
17 | # end::adocPrometheus[]
18 |
--------------------------------------------------------------------------------
/infrastructure/monitoring/prometheus.yml:
--------------------------------------------------------------------------------
1 | global:
2 | scrape_interval: 15s
3 |
4 | # tag::adocPrometheus[]
5 | scrape_configs:
6 | - job_name: 'prometheus'
7 | static_configs:
8 | - targets: ['host.docker.internal:9090']
9 | - job_name: 'number'
10 | metrics_path: '/q/metrics'
11 | static_configs:
12 | - targets: ['host.docker.internal:8701']
13 | - job_name: 'book'
14 | metrics_path: '/q/metrics'
15 | static_configs:
16 | - targets: ['host.docker.internal:8702']
17 | # end::adocPrometheus[]
18 |
--------------------------------------------------------------------------------
/rest-number/startup-prod.txt:
--------------------------------------------------------------------------------
1 | INFO _ _ _
2 | INFO | \ | | | |
3 | INFO | \| |_ _ _ __ ___ | |__ ___ _ __
4 | INFO | . ` | | | | '_ ` _ \| '_ \ / _ \ '__|
5 | INFO | |\ | |_| | | | | | | |_) | __/ |
6 | INFO \_| \_/\__,_|_| |_| |_|_.__/ \___|_|
7 | INFO Powered by Quarkus
8 | INFO rest-number 2.0.0-SNAPSHOT on JVM started in 0.638s. Listening on: http://0.0.0.0:8701
9 | INFO Profile prod activated.
10 | INFO Installed features: [cdi, resteasy, resteasy-jsonb, smallrye-openapi]
11 |
--------------------------------------------------------------------------------
/rest-number/startup-origin.txt:
--------------------------------------------------------------------------------
1 | __ ____ __ _____ ___ __ ____ ______
2 | --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
3 | -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
4 | --\___\_\____/_/ |_/_/|_/_/|_|\____/___/
5 | INFO rest-number 2.0.0-SNAPSHOT on JVM started in 1.466s. Listening on: http://localhost:8080
6 | INFO Profile dev activated. Live Coding activated.
7 | INFO Installed features: [cdi, resteasy, resteasy-jsonb, smallrye-openapi, swagger-ui]
8 |
9 | --
10 | Tests paused
11 | Press [r] to resume testing, [o] Toggle test output, [h] for more options>
12 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/number/number-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { Routes, RouterModule } from '@angular/router';
3 | import {NumberGenerateComponent} from "./number-generate/number-generate.component";
4 |
5 |
6 | const routes: Routes = [
7 | { path: '', component:NumberGenerateComponent},
8 | { path: 'number-generate', component:NumberGenerateComponent},
9 | ];
10 |
11 | @NgModule({
12 | imports: [RouterModule.forChild(routes)],
13 | exports: [RouterModule]
14 | })
15 | export class NumberRoutingModule { }
16 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/main/resources/default_banner.txt:
--------------------------------------------------------------------------------
1 |
2 | _ _ _____ _ _ _ _ _____ _
3 | | | | |_ _| | | | (_) | | / ___| |
4 | | | | | | | | | | |_ _ __ | |_ __ _ __ _ ___\ `--.| |_ ___ _ __ ___
5 | | | | | | | | | | | | '_ \| __/ _` |/ _` |/ _ \`--. \ __/ _ \| '__/ _ \
6 | | |_| |_| |_ \ \_/ / | | | | || (_| | (_| | __/\__/ / || (_) | | | __/
7 | \___/ \___/ \___/|_|_| |_|\__\__,_|\__, |\___\____/ \__\___/|_| \___|
8 | __/ |
9 | |___/
10 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/book/book-random/book-random.component.html:
--------------------------------------------------------------------------------
1 | {{book?.title | slice:0:50}}
2 |
3 | {{book?.author}}
4 |
5 |
6 | {{book?.description}}
7 |
8 |
9 |
10 |
13 |
17 |
18 |
--------------------------------------------------------------------------------
/rest-number/metrics.json:
--------------------------------------------------------------------------------
1 | {
2 | "NumberResource.countGenerateBookNumber": 23,
3 | "NumberResource.timeGenerateBookNumber": {
4 | "p99": 2.552359,
5 | "min": 2.351004,
6 | "max": 4.142853,
7 | "mean": 2.4475338218611054,
8 | "p50": 2.459645,
9 | "p999": 2.552359,
10 | "stddev": 0.059644582615724376,
11 | "p95": 2.552359,
12 | "p98": 2.552359,
13 | "p75": 2.475044,
14 | "fiveMinRate": 0.0427305308960399,
15 | "fifteenMinRate": 0.018611613176138856,
16 | "meanRate": 0.005087646702440494,
17 | "count": 23,
18 | "oneMinRate": 0.1733913276585504
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/book/book-delete/book-delete.component.html:
--------------------------------------------------------------------------------
1 | {{book?.title | slice:0:50}}
2 |
3 | {{book?.author}}
4 |
5 |
6 | {{book?.description}}
7 |
8 |
9 |
10 |
13 |
16 |
17 |
--------------------------------------------------------------------------------
/rest-book/curl.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": 997,
3 | "author": "Antonio Goncalves",
4 | "description": "In this fascicle, you will learn Java Persistence API, its annotations for mapping entities, as well as the Java Persistence Query Language and entity life cycle",
5 | "isbn13": "9781980399025",
6 | "mediumImageUrl": "https://images-na.ssl-images-amazon.com/images/I/31fHenHChZL.jpg",
7 | "nbOfPages": 129,
8 | "price": 9.99,
9 | "rank": 9,
10 | "smallImageUrl": "https://images-na.ssl-images-amazon.com/images/I/31fHenHChZL._SL160_.jpg",
11 | "title": "Understanding Bean Validation",
12 | "yearOfPublication": 2018
13 | }
14 |
--------------------------------------------------------------------------------
/rest-book/src/main/java/org/agoncal/fascicle/quarkus/book/client/NumberProxy.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.book.client;
2 |
3 | // tag::adocImports[]
4 | import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
5 |
6 | import javax.ws.rs.GET;
7 | import javax.ws.rs.Path;
8 | import javax.ws.rs.Produces;
9 | import javax.ws.rs.core.MediaType;
10 | // end::adocImports[]
11 |
12 | // tag::adocSnippet[]
13 | @Path("/api/numbers")
14 | @Produces(MediaType.APPLICATION_JSON)
15 | @RegisterRestClient
16 | public interface NumberProxy {
17 |
18 | @GET
19 | IsbnNumbers generateNumbers();
20 | }
21 | // end::adocSnippet[]
22 |
--------------------------------------------------------------------------------
/event-inventory/src/test/java/org/agoncal/fascicle/quarkus/inventory/InventoryResourceTest.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.inventory;
2 |
3 | import io.quarkus.test.junit.QuarkusTest;
4 | import org.junit.jupiter.api.Test;
5 |
6 | import static io.restassured.RestAssured.given;
7 | import static org.hamcrest.CoreMatchers.is;
8 |
9 | @QuarkusTest
10 | public class InventoryResourceTest {
11 |
12 | @Test
13 | public void testHelloEndpoint() {
14 | given()
15 | .when().get("/api/inventory")
16 | .then()
17 | .statusCode(200)
18 | .body(is("Hello RESTEasy"));
19 | }
20 |
21 | }
--------------------------------------------------------------------------------
/rest-number/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | # tag::adocConfigPort[]
2 | quarkus.http.port=8701
3 | # end::adocConfigPort[]
4 |
5 | # tag::adocBanner[]
6 | quarkus.banner.enabled=false
7 | # end::adocBanner[]
8 |
9 | # tag::adocConfigProperty[]
10 | number.separator=true
11 | # end::adocConfigProperty[]
12 |
13 | # tag::adocConfigLog[]
14 | quarkus.log.console.enable=true
15 | quarkus.log.console.format=%d{HH:mm:ss} %-3p [%c{1.}] %s%e%n
16 | quarkus.log.console.level=DEBUG
17 | quarkus.log.console.darken=5
18 | # end::adocConfigLog[]
19 |
20 | # tag::adocCors[]
21 | quarkus.http.cors=true
22 | # end::adocCors[]
23 |
24 | seconds.sleep=0
25 |
--------------------------------------------------------------------------------
/infrastructure/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 |
6 | org.agoncal.fascicle
7 | quarkus-practising
8 | 2.0.0-SNAPSHOT
9 |
10 |
11 | org.agoncal.fascicle.quarkus-practising
12 | infrastructure
13 | 2.0.0-SNAPSHOT
14 | Practising Quarkus :: Infrastructure
15 |
16 |
17 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/number/number.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 |
4 | import { NumberRoutingModule } from './number-routing.module';
5 | import { NumberGenerateComponent } from './number-generate/number-generate.component';
6 | import { NumberEndpointService } from "../shared/api/numberEndpoint.service";
7 | import {HttpClientModule} from "@angular/common/http";
8 |
9 |
10 | @NgModule({
11 | declarations: [NumberGenerateComponent],
12 | imports: [
13 | CommonModule,
14 | NumberRoutingModule,
15 | HttpClientModule
16 | ],
17 | providers:[NumberEndpointService]
18 | })
19 | export class NumberModule { }
20 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/book/book-list/book-list.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 |
3 | import {BookEndpointService} from "../../shared/api/bookEndpoint.service";
4 | import {IBook} from "../../shared/model/book";
5 |
6 | @Component({
7 | templateUrl: './book-list.component.html',
8 | styles: []
9 | })
10 | export class BookListComponent implements OnInit {
11 |
12 | books?: IBook[];
13 |
14 | constructor(private numberEndpointService: BookEndpointService) {
15 | }
16 |
17 | ngOnInit(): void {
18 | this.listBooks();
19 | }
20 |
21 | listBooks(): void {
22 | this.numberEndpointService.getAllBooks().subscribe(books => this.books = books);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/book/book-random/book-random.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import {IBook} from "../../shared/model/book";
3 | import {BookEndpointService} from "../../shared/api/bookEndpoint.service";
4 |
5 | @Component({
6 | templateUrl: './book-random.component.html',
7 | styles: []
8 | })
9 | export class BookRandomComponent implements OnInit {
10 |
11 | book?: IBook;
12 |
13 | constructor(private bookEndpointService: BookEndpointService) { }
14 |
15 | ngOnInit(): void {
16 | this.load();
17 | }
18 |
19 | load() {
20 | this.bookEndpointService.getRandomBook().subscribe((book) => {
21 | this.book = book;
22 | });
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/rest-book/src/main/docker/Dockerfile.native-distroless:
--------------------------------------------------------------------------------
1 | ####
2 | # This Dockerfile is used in order to build a distroless container that runs the Quarkus application in native (no JVM) mode
3 | #
4 | # Before building the container image run:
5 | #
6 | # ./mvnw package -Pnative
7 | #
8 | # Then, build the image with:
9 | #
10 | # docker build -f src/main/docker/Dockerfile.native-distroless -t quarkus/rest-book .
11 | #
12 | # Then run the container using:
13 | #
14 | # docker run -i --rm -p 8080:8080 quarkus/rest-book
15 | #
16 | ###
17 | FROM quay.io/quarkus/quarkus-distroless-image:1.0
18 | COPY target/*-runner /application
19 |
20 | EXPOSE 8702
21 | USER nonroot
22 |
23 | CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
24 |
--------------------------------------------------------------------------------
/rest-number/src/main/docker/Dockerfile.native-distroless:
--------------------------------------------------------------------------------
1 | ####
2 | # This Dockerfile is used in order to build a distroless container that runs the Quarkus application in native (no JVM) mode
3 | #
4 | # Before building the container image run:
5 | #
6 | # ./mvnw package -Pnative
7 | #
8 | # Then, build the image with:
9 | #
10 | # docker build -f src/main/docker/Dockerfile.native-distroless -t quarkus/rest-number .
11 | #
12 | # Then run the container using:
13 | #
14 | # docker run -i --rm -p 8080:8080 quarkus/rest-number
15 | #
16 | ###
17 | FROM quay.io/quarkus/quarkus-distroless-image:1.0
18 | COPY target/*-runner /application
19 |
20 | EXPOSE 8701
21 | USER nonroot
22 |
23 | CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
24 |
--------------------------------------------------------------------------------
/rest-book/src/test/java/org/agoncal/fascicle/quarkus/book/client/MockNumberProxy.java:
--------------------------------------------------------------------------------
1 | // tag::adocTest[]
2 | package org.agoncal.fascicle.quarkus.book.client;
3 |
4 | import io.quarkus.test.Mock;
5 | import org.eclipse.microprofile.rest.client.inject.RestClient;
6 |
7 | import javax.enterprise.context.ApplicationScoped;
8 |
9 | // tag::adocSnippet[]
10 | @Mock
11 | @ApplicationScoped
12 | @RestClient
13 | public class MockNumberProxy implements NumberProxy {
14 |
15 | @Override
16 | public IsbnNumbers generateNumbers() {
17 | IsbnNumbers isbnNumbers = new IsbnNumbers();
18 | isbnNumbers.isbn13 = "Dummy Isbn 13";
19 | isbnNumbers.isbn10 = "Dummy Isbn 10";
20 | return isbnNumbers;
21 | }
22 | }
23 | // end::adocSnippet[]
24 |
--------------------------------------------------------------------------------
/event-inventory/src/main/docker/Dockerfile.native-distroless:
--------------------------------------------------------------------------------
1 | ####
2 | # This Dockerfile is used in order to build a distroless container that runs the Quarkus application in native (no JVM) mode
3 | #
4 | # Before building the container image run:
5 | #
6 | # ./mvnw package -Pnative
7 | #
8 | # Then, build the image with:
9 | #
10 | # docker build -f src/main/docker/Dockerfile.native-distroless -t quarkus/event-inventory .
11 | #
12 | # Then run the container using:
13 | #
14 | # docker run -i --rm -p 8080:8080 quarkus/event-inventory
15 | #
16 | ###
17 | FROM quay.io/quarkus/quarkus-distroless-image:1.0
18 | COPY target/*-runner /application
19 |
20 | EXPOSE 8080
21 | USER nonroot
22 |
23 | CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
24 |
--------------------------------------------------------------------------------
/rest-book/src/test/java/org/agoncal/fascicle/quarkus/book/BookTest.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.book;
2 |
3 | import java.util.List;
4 |
5 | public class BookTest {
6 |
7 | private Long id;
8 |
9 | public void shouldCRUD() {
10 | // tag::adocSnippet[]
11 | // creating a book
12 | Book book = new Book();
13 | book.title = "H2G2";
14 | book.rank = 9;
15 |
16 | // persist it
17 | book.persist();
18 |
19 | // getting a list of all Book entities
20 | List books = Book.listAll();
21 |
22 | // finding a specific book by ID
23 | book = Book.findById(id);
24 |
25 | // counting all books
26 | long countAll = Book.count();
27 | // end::adocSnippet[]
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { BrowserModule } from '@angular/platform-browser';
2 | import { NgModule } from '@angular/core';
3 |
4 | import { AppRoutingModule } from './app-routing.module';
5 | import { AppComponent } from './app.component';
6 | import { BookModule } from './book/book.module';
7 | import { NumberModule } from './number/number.module';
8 | import { InventoryModule } from './inventory/inventory.module';
9 |
10 | @NgModule({
11 | declarations: [
12 | AppComponent
13 | ],
14 | imports: [
15 | BrowserModule,
16 | AppRoutingModule,
17 | BookModule,
18 | NumberModule,
19 | InventoryModule
20 | ],
21 | providers: [],
22 | bootstrap: [AppComponent]
23 | })
24 | export class AppModule { }
25 |
--------------------------------------------------------------------------------
/bootstrap-event-inventory.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # tag::adocBootstrap[]
3 | mvn io.quarkus:quarkus-maven-plugin:2.5.0.Final:create \
4 | -DplatformVersion=2.5.0.Final \
5 | -DprojectGroupId=org.agoncal.fascicle.quarkus-practising \
6 | -DprojectArtifactId=event-inventory \
7 | -DprojectVersion=2.0.0-SNAPSHOT \
8 | -DclassName="org.agoncal.fascicle.quarkus.inventory.InventoryResource" \
9 | -Dpath="/api/inventory" \
10 | -Dextensions="resteasy, resteasy-jsonb, mongodb-panache, smallrye-openapi, kafka"
11 | # end::adocBootstrap[]
12 |
13 | cd event-inventory
14 |
15 | # tag::adocDependencyFaultTolerance[]
16 | ./mvnw quarkus:add-extension -Dextensions="rest-client, smallrye-fault-tolerance"
17 | # end::adocDependencyFaultTolerance[]
18 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false
7 | };
8 |
9 | /*
10 | * For easier debugging in development mode, you can import the following file
11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
12 | *
13 | * This import should be commented out in production mode because it will have a negative impact
14 | * on performance if an error is thrown.
15 | */
16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI.
17 |
--------------------------------------------------------------------------------
/rest-number/startup.txt:
--------------------------------------------------------------------------------
1 | INFO _ _ _
2 | INFO | \ | | | |
3 | INFO | \| |_ _ _ __ ___ | |__ ___ _ __
4 | INFO | . ` | | | | '_ ` _ \| '_ \ / _ \ '__|
5 | INFO | |\ | |_| | | | | | | |_) | __/ |
6 | INFO \_| \_/\__,_|_| |_| |_|_.__/ \___|_|
7 | INFO Powered by Quarkus
8 | INFO rest-number 2.0.0-SNAPSHOT on JVM started in 1.466s. Listening on: http://localhost:8080
9 | INFO Profile dev activated. Live Coding activated.
10 | INFO Installed features: [cdi, resteasy, resteasy-jsonb, smallrye-openapi, swagger-ui]
11 |
12 | --
13 | Tests paused
14 | Press [r] to resume testing, [o] Toggle test output, [h] for more options>
15 | (...)
16 | INFO The application Number is stopping...
17 | INFO Quarkus stopped in 0.002s
18 |
--------------------------------------------------------------------------------
/ui-vintagestore/tsconfig.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "compileOnSave": false,
4 | "compilerOptions": {
5 | "baseUrl": "./",
6 | "outDir": "./dist/out-tsc",
7 | "forceConsistentCasingInFileNames": true,
8 | "noImplicitReturns": true,
9 | "noFallthroughCasesInSwitch": true,
10 | "sourceMap": true,
11 | "declaration": false,
12 | "downlevelIteration": true,
13 | "experimentalDecorators": true,
14 | "moduleResolution": "node",
15 | "importHelpers": true,
16 | "target": "es2015",
17 | "module": "es2020",
18 | "lib": [
19 | "es2018",
20 | "dom"
21 | ]
22 | },
23 | "angularCompilerOptions": {
24 | "fullTemplateTypeCheck": true,
25 | "strictInjectionParameters": true
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/number/number-generate/number-generate.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit } from '@angular/core';
2 | import {NumberEndpointService} from "../../shared/api/numberEndpoint.service";
3 | import {BookNumbers} from "../../shared/model/bookNumbers";
4 |
5 | // tag::adocSnippet[]
6 | @Component({
7 | templateUrl: 'number-generate.component.html'
8 | })
9 | export class NumberGenerateComponent implements OnInit {
10 |
11 | bookNumbers?: BookNumbers;
12 |
13 | constructor(private numberEndpointService: NumberEndpointService) { }
14 |
15 | ngOnInit(): void {
16 | this.generateBookNumber();
17 | }
18 |
19 | generateBookNumber() {
20 | this.numberEndpointService.generatesBookNumbers().subscribe(bookNumbers => this.bookNumbers = bookNumbers);
21 | }
22 | }
23 | // end::adocSnippet[]
24 |
--------------------------------------------------------------------------------
/rest-number/src/main/docker/Dockerfile.native:
--------------------------------------------------------------------------------
1 | ####
2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode
3 | #
4 | # Before building the container image run:
5 | #
6 | # ./mvnw package -Pnative
7 | #
8 | # Then, build the image with:
9 | #
10 | # docker build -f src/main/docker/Dockerfile.native -t quarkus/rest-number .
11 | #
12 | # Then run the container using:
13 | #
14 | # docker run -i --rm -p 8080:8080 quarkus/rest-number
15 | #
16 | ###
17 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4
18 | WORKDIR /work/
19 | RUN chown 1001 /work \
20 | && chmod "g+rwX" /work \
21 | && chown 1001:root /work
22 | COPY --chown=1001:root target/*-runner /work/application
23 |
24 | EXPOSE 8701
25 | USER 1001
26 |
27 | CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
28 |
--------------------------------------------------------------------------------
/event-inventory/src/main/docker/Dockerfile.native:
--------------------------------------------------------------------------------
1 | ####
2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode
3 | #
4 | # Before building the container image run:
5 | #
6 | # ./mvnw package -Pnative
7 | #
8 | # Then, build the image with:
9 | #
10 | # docker build -f src/main/docker/Dockerfile.native -t quarkus/event-inventory .
11 | #
12 | # Then run the container using:
13 | #
14 | # docker run -i --rm -p 8080:8080 quarkus/event-inventory
15 | #
16 | ###
17 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4
18 | WORKDIR /work/
19 | RUN chown 1001 /work \
20 | && chmod "g+rwX" /work \
21 | && chown 1001:root /work
22 | COPY --chown=1001:root target/*-runner /work/application
23 |
24 | EXPOSE 8080
25 | USER 1001
26 |
27 | CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
28 |
--------------------------------------------------------------------------------
/rest-number/startup-profile.txt:
--------------------------------------------------------------------------------
1 | INFO _ _ _
2 | INFO | \ | | | |
3 | INFO | \| |_ _ _ __ ___ | |__ ___ _ __
4 | INFO | . ` | | | | '_ ` _ \| '_ \ / _ \ '__|
5 | INFO | |\ | |_| | | | | | | |_) | __/ |
6 | INFO \_| \_/\__,_|_| |_| |_|_.__/ \___|_|
7 | INFO Powered by Quarkus
8 | INFO The application Number is starting with profile dev
9 | INFO rest-number 2.0.0-SNAPSHOT on JVM started in 1.466s. Listening on: http://localhost:8080
10 | INFO Profile dev activated. Live Coding activated.
11 | INFO Installed features: [cdi, resteasy, resteasy-jsonb, smallrye-openapi, swagger-ui]
12 |
13 | --
14 | Tests paused
15 | Press [r] to resume testing, [o] Toggle test output, [h] for more options>
16 | (...)
17 | INFO The application Number is stopping...
18 | INFO Quarkus stopped in 0.002s
19 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/app-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { Routes, RouterModule } from '@angular/router';
3 |
4 | const routes: Routes = [
5 | { path: '', loadChildren: () => import('./book/book.module').then(m => m.BookModule) },
6 | { path: 'book-random', loadChildren: () => import('./book/book.module').then(m => m.BookModule) },
7 | { path: 'inventory', loadChildren: () => import('./inventory/inventory.module').then(m => m.InventoryModule) },
8 | { path: 'number-generate', loadChildren: () => import('./number/number.module').then(m => m.NumberModule) },
9 | { path: '**', loadChildren: () => import('./book/book.module').then(m => m.BookModule) },
10 | ];
11 |
12 | @NgModule({
13 | imports: [RouterModule.forRoot(routes)],
14 | exports: [RouterModule]
15 | })
16 | export class AppRoutingModule { }
17 |
--------------------------------------------------------------------------------
/rest-book/src/main/docker/Dockerfile.native:
--------------------------------------------------------------------------------
1 | ####
2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode
3 | #
4 | # Before building the container image run:
5 | #
6 | # ./mvnw package -Pnative
7 | #
8 | # Then, build the image with:
9 | #
10 | # docker build -f src/main/docker/Dockerfile.native -t quarkus/rest-book .
11 | #
12 | # Then run the container using:
13 | #
14 | # docker run -i --rm -p 8080:8080 quarkus/rest-book
15 | #
16 | ###
17 | # tag::adocSnippet[]
18 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4
19 | WORKDIR /work/
20 | RUN chown 1001 /work \
21 | && chmod "g+rwX" /work \
22 | && chown 1001:root /work
23 | COPY --chown=1001:root target/*-runner /work/application
24 |
25 | EXPOSE 8702
26 | USER 1001
27 |
28 | CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
29 | # end::adocSnippet[]
30 |
--------------------------------------------------------------------------------
/rest-book/src/main/java/org/agoncal/fascicle/quarkus/book/health/PingBookResourceHealthCheck.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.book.health;
2 |
3 | import org.agoncal.fascicle.quarkus.book.BookResource;
4 | import org.eclipse.microprofile.health.HealthCheck;
5 | import org.eclipse.microprofile.health.HealthCheckResponse;
6 | import org.eclipse.microprofile.health.Liveness;
7 |
8 | import javax.enterprise.context.ApplicationScoped;
9 | import javax.inject.Inject;
10 |
11 | // tag::adocSnippet[]
12 | @Liveness
13 | @ApplicationScoped
14 | public class PingBookResourceHealthCheck implements HealthCheck {
15 |
16 | @Inject
17 | BookResource bookResource;
18 |
19 | @Override
20 | public HealthCheckResponse call() {
21 | bookResource.hello();
22 | return HealthCheckResponse.named("Ping Book REST Endpoint").up().build();
23 | }
24 | }
25 | // end::adocSnippet[]
26 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/main/docker/Dockerfile.native:
--------------------------------------------------------------------------------
1 | ####
2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode
3 | #
4 | # Before building the container image run:
5 | #
6 | # ./mvnw package -Pnative
7 | #
8 | # Then, build the image with:
9 | #
10 | # docker build -f src/main/docker/Dockerfile.native -t quarkus/ui-vintagestore .
11 | #
12 | # Then run the container using:
13 | #
14 | # docker run -i --rm -p 8080:8080 quarkus/ui-vintagestore
15 | #
16 | ###
17 | # tag::adocSnippet[]
18 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4
19 | WORKDIR /work/
20 | RUN chown 1001 /work \
21 | && chmod "g+rwX" /work \
22 | && chown 1001:root /work
23 | COPY --chown=1001:root target/*-runner /work/application
24 |
25 | EXPOSE 8700
26 | USER 1001
27 |
28 | CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
29 | # end::adocSnippet[]
30 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/book/book-detail/book-detail.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {ActivatedRoute} from "@angular/router";
3 | import {BookEndpointService} from "../../shared/api/bookEndpoint.service";
4 | import {IBook} from "../../shared/model/book";
5 |
6 | @Component({
7 | templateUrl: './book-detail.component.html',
8 | styles: []
9 | })
10 | export class BookDetailComponent implements OnInit {
11 |
12 | book?: IBook;
13 |
14 | constructor(private bookEndpointService: BookEndpointService,
15 | private route: ActivatedRoute) {
16 | }
17 |
18 | ngOnInit(): void {
19 | this.route.params.subscribe((params) => {
20 | this.load(params['id']);
21 | });
22 | }
23 |
24 | load(id: number) {
25 | this.bookEndpointService.getBook(id).subscribe((book: IBook) => {
26 | this.book = book;
27 | });
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/first-step/src/main/java/org/agoncal/fascicle/quarkus/firststep/AuthorResource.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.firststep;
2 |
3 | import javax.ws.rs.GET;
4 | import javax.ws.rs.Path;
5 | import javax.ws.rs.PathParam;
6 | import javax.ws.rs.Produces;
7 | import javax.ws.rs.core.MediaType;
8 |
9 | /**
10 | * @author Antonio Goncalves
11 | * http://www.antoniogoncalves.org
12 | * --
13 | */
14 | // tag::adocSnippet[]
15 | @Path("/authors")
16 | @Produces(MediaType.TEXT_PLAIN)
17 | public class AuthorResource {
18 |
19 | String[] scifiAuthors = {"Isaac Asimov", "Nora Jemisin", "Douglas Adams"};
20 |
21 | @GET
22 | public String getAllScifiAuthors() {
23 | return String.join(", ", scifiAuthors);
24 | }
25 |
26 | @GET
27 | @Path("/{index}")
28 | public String getScifiAuthor(@PathParam("index") int index) {
29 | return scifiAuthors[index];
30 | }
31 | }
32 | // end::adocSnippet[]
33 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/book/book-form/book-form.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {IBook, Book} from "../../shared/model/book";
3 | import {BookEndpointService} from "../../shared/api/bookEndpoint.service";
4 | import {ActivatedRoute, Router} from "@angular/router";
5 |
6 | @Component({
7 | templateUrl: './book-form.component.html',
8 | styles: []
9 | })
10 | export class BookFormComponent implements OnInit {
11 |
12 | book?: IBook;
13 |
14 | constructor(private bookEndpointService: BookEndpointService,
15 | private route: ActivatedRoute,
16 | private router: Router) {
17 | }
18 |
19 | ngOnInit(): void {
20 | this.book = new Book();
21 | }
22 |
23 | save() {
24 | this.bookEndpointService.createBook(this.book).subscribe((response: string) => {
25 | this.router.navigate(['/book-list']);
26 | });
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/shared/model/book.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Book representation
3 | */
4 | export interface IBook {
5 | id?: number;
6 | title?: string;
7 | author?: string;
8 | nbOfPages?: number;
9 | price?: number;
10 | rank?: number;
11 | mediumImageUrl?: string;
12 | smallImageUrl?: string;
13 | yearOfPublication?: number;
14 | description?: string;
15 | isbn10?: string;
16 | isbn13?: string;
17 | }
18 |
19 | export class Book implements IBook {
20 | constructor(
21 | public id?: number,
22 | public title?: string,
23 | public author?: string,
24 | public nbOfPages?: number,
25 | public price?: number,
26 | public rank?: number,
27 | public mediumImageUrl?: string,
28 | public smallImageUrl?: string,
29 | public yearOfPublication?: number,
30 | public description?: string,
31 | public isbn10?: string,
32 | public isbn13?: string
33 | ) {
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | *dummy*
5 | dummy/
6 | dist/
7 | tmp/
8 | target/
9 | maven-wrapper.jar
10 | book-*.json
11 |
12 | # dependencies
13 | node/
14 | node_modules/
15 | ui-vintagestore/src/main/resources/META-INF/resources/ui-vintagestore/*
16 |
17 | # profiling files
18 | chrome-profiler-events*.json
19 | speed-measure-plugin*.json
20 |
21 | # IDEs and editors
22 | *.iml
23 | /.idea
24 | .project
25 | .classpath
26 | .c9/
27 | *.launch
28 | .settings/
29 | *.sublime-workspace
30 |
31 | # IDE - VSCode
32 | .vscode/*
33 | !.vscode/settings.json
34 | !.vscode/tasks.json
35 | !.vscode/launch.json
36 | !.vscode/extensions.json
37 | .history/*
38 |
39 | # misc
40 | /.sass-cache
41 | /connect.lock
42 | /coverage
43 | /libpeerconnection.log
44 | npm-debug.log
45 | yarn-error.log
46 | testem.log
47 | /typings
48 |
49 | # System Files
50 | .DS_Store
51 | Thumbs.db
52 |
--------------------------------------------------------------------------------
/rest-number/src/main/java/org/agoncal/fascicle/quarkus/number/health/PingNumberResourceHealthCheck.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.number.health;
2 |
3 | import org.agoncal.fascicle.quarkus.number.NumberResource;
4 | // tag::adocImports[]
5 | import org.eclipse.microprofile.health.HealthCheck;
6 | import org.eclipse.microprofile.health.HealthCheckResponse;
7 | import org.eclipse.microprofile.health.Liveness;
8 | // end::adocImports[]
9 |
10 | import javax.enterprise.context.ApplicationScoped;
11 | import javax.inject.Inject;
12 |
13 | // tag::adocSnippet[]
14 | @Liveness
15 | @ApplicationScoped
16 | public class PingNumberResourceHealthCheck implements HealthCheck {
17 |
18 | @Inject
19 | NumberResource numberResource;
20 |
21 | @Override
22 | public HealthCheckResponse call() {
23 | numberResource.hello();
24 | return HealthCheckResponse.named("Ping Number REST Endpoint").up().build();
25 | }
26 | }
27 | // end::adocSnippet[]
28 |
--------------------------------------------------------------------------------
/bootstrap-rest-number.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # tag::adocBootstrap[]
3 | mvn -U io.quarkus:quarkus-maven-plugin:2.5.0.Final:create \
4 | -DplatformVersion=2.5.0.Final \
5 | -DprojectGroupId=org.agoncal.fascicle.quarkus-practising \
6 | -DprojectArtifactId=rest-number \
7 | -DprojectVersion=2.0.0-SNAPSHOT \
8 | -DclassName="org.agoncal.fascicle.quarkus.number.NumberResource" \
9 | -Dpath="/api/numbers" \
10 | -Dextensions="resteasy, resteasy-jsonb, smallrye-openapi"
11 | # end::adocBootstrap[]
12 |
13 | cd rest-number
14 |
15 | # tag::adocDependencyFaultTolerance[]
16 | ./mvnw quarkus:add-extension -Dextensions="smallrye-fault-tolerance"
17 | # end::adocDependencyFaultTolerance[]
18 |
19 | # tag::adocDependencyObservability[]
20 | ./mvnw quarkus:add-extension -Dextensions="smallrye-health, smallrye-metrics"
21 | # end::adocDependencyObservability[]
22 |
23 | # tag::adocDependencyDocker[]
24 | ./mvnw quarkus:add-extension -Dextensions="container-image-docker"
25 | # end::adocDependencyDocker[]
26 |
--------------------------------------------------------------------------------
/rest-number/test.txt:
--------------------------------------------------------------------------------
1 | [INFO] -------------------------------------------------
2 | [INFO] T E S T S
3 | [INFO] -------------------------------------------------
4 | [INFO] Running org.agoncal.fascicle.quarkus.number.NumberResourceTest
5 |
6 | [INFO] _ _ _
7 | [INFO] | \ | | | |
8 | [INFO] | \| |_ _ _ __ ___ | |__ ___ _ __
9 | [INFO] | . ` | | | | '_ ` _ \| '_ \ / _ \ '__|
10 | [INFO] | |\ | |_| | | | | | | |_) | __/ |
11 | [INFO] \_| \_/\__,_|_| |_| |_|_.__/ \___|_|
12 | [INFO] Powered by Quarkus
13 | [INFO] Quarkus started in 1.729s. Listening on: http://localhost:8081
14 | [INFO] Profile test activated.
15 | [INFO] Generating book numbers
16 |
17 | [INFO] The application Number is stopping...
18 | [INFO] Quarkus stopped in 0.027s
19 |
20 | [INFO] Results:
21 | [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
22 | [INFO]
23 | [INFO] -------------------------------------------------
24 | [INFO] BUILD SUCCESS
25 | [INFO] -------------------------------------------------
26 |
--------------------------------------------------------------------------------
/rest-book/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | # tag::adocConfigPort[]
2 | quarkus.http.port=8702
3 | # end::adocConfigPort[]
4 |
5 | # tag::adocDatasource[]
6 | %prod.quarkus.datasource.db-kind=postgresql
7 | %prod.quarkus.datasource.username=book
8 | %prod.quarkus.datasource.password=book
9 | %prod.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/books_database
10 | %prod.quarkus.datasource.jdbc.min-size=2
11 | %prod.quarkus.datasource.jdbc.max-size=8
12 | # end::adocDatasource[]
13 |
14 | # tag::adocHibernate[]
15 | quarkus.hibernate-orm.database.generation=drop-and-create
16 | quarkus.hibernate-orm.log.sql=true
17 | quarkus.hibernate-orm.sql-load-script=import.sql
18 | # end::adocHibernate[]
19 |
20 | # tag::adocCors[]
21 | quarkus.http.cors=true
22 | # end::adocCors[]
23 |
24 | # tag::adocRestClient[]
25 | quarkus.rest-client."org.agoncal.fascicle.quarkus.book.client.NumberProxy".url=http://localhost:8701
26 | quarkus.rest-client."org.agoncal.fascicle.quarkus.book.client.NumberProxy".scope=javax.inject.Singleton
27 | # end::adocRestClient[]
28 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/book/book-routing.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { Routes, RouterModule } from '@angular/router';
3 | import { BookRandomComponent } from "./book-random/book-random.component";
4 | import { BookListComponent } from "./book-list/book-list.component";
5 | import {BookDeleteComponent} from "./book-delete/book-delete.component";
6 | import {BookDetailComponent} from "./book-detail/book-detail.component";
7 | import {BookFormComponent} from "./book-form/book-form.component";
8 |
9 |
10 | const routes: Routes = [
11 | { path: '', component:BookRandomComponent},
12 | { path: 'book-delete/:id', component:BookDeleteComponent},
13 | { path: 'book-detail/:id', component:BookDetailComponent},
14 | { path: 'book-form', component:BookFormComponent},
15 | { path: 'book-list', component:BookListComponent},
16 | { path: 'book-random', component:BookRandomComponent},
17 | ];
18 |
19 | @NgModule({
20 | imports: [RouterModule.forChild(routes)],
21 | exports: [RouterModule]
22 | })
23 | export class BookRoutingModule { }
24 |
--------------------------------------------------------------------------------
/bootstrap-rest-book.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # tag::adocBootstrap[]
3 | mvn -U io.quarkus:quarkus-maven-plugin:2.5.0.Final:create \
4 | -DplatformVersion=2.5.0.Final \
5 | -DprojectGroupId=org.agoncal.fascicle.quarkus-practising \
6 | -DprojectArtifactId=rest-book \
7 | -DprojectVersion=2.0.0-SNAPSHOT \
8 | -DclassName="org.agoncal.fascicle.quarkus.book.BookResource" \
9 | -Dpath="/api/books" \
10 | -Dextensions="resteasy, resteasy-jsonb, hibernate-orm-panache, jdbc-postgresql, hibernate-validator, smallrye-openapi"
11 | # end::adocBootstrap[]
12 |
13 | cd rest-book
14 |
15 | # tag::adocDependencyFaultTolerance[]
16 | ./mvnw quarkus:add-extension -Dextensions="rest-client, smallrye-fault-tolerance"
17 | # end::adocDependencyFaultTolerance[]
18 |
19 | # tag::adocDependencyObservability[]
20 | ./mvnw quarkus:add-extension -Dextensions="smallrye-health, smallrye-metrics"
21 | # end::adocDependencyObservability[]
22 |
23 | # tag::adocDependencyDocker[]
24 | ./mvnw quarkus:add-extension -Dextensions="container-image-docker"
25 | # end::adocDependencyDocker[]
26 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/book/book.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { FormsModule } from "@angular/forms";
4 | import { HttpClientModule} from "@angular/common/http";
5 |
6 | import { BookRoutingModule } from './book-routing.module';
7 | import { BookListComponent } from './book-list/book-list.component';
8 | import { BookFormComponent } from './book-form/book-form.component';
9 | import { BookDetailComponent } from './book-detail/book-detail.component';
10 | import { BookDeleteComponent } from './book-delete/book-delete.component';
11 | import { BookRandomComponent } from './book-random/book-random.component';
12 | import { BookEndpointService} from "../shared/api/bookEndpoint.service";
13 |
14 |
15 | @NgModule({
16 | declarations: [BookListComponent, BookFormComponent, BookDetailComponent, BookDeleteComponent, BookRandomComponent],
17 | imports: [
18 | CommonModule,
19 | FormsModule,
20 | BookRoutingModule,
21 | HttpClientModule
22 | ],
23 | providers:[BookEndpointService]
24 | })
25 | export class BookModule { }
26 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/book/book-delete/book-delete.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, OnInit} from '@angular/core';
2 | import {ActivatedRoute, Router} from "@angular/router";
3 | import {BookEndpointService} from "../../shared/api/bookEndpoint.service";
4 | import {IBook} from "../../shared/model/book";
5 |
6 | @Component({
7 | templateUrl: './book-delete.component.html',
8 | styles: []
9 | })
10 | export class BookDeleteComponent implements OnInit {
11 |
12 | book?: IBook;
13 |
14 | constructor(private bookEndpointService: BookEndpointService,
15 | private route: ActivatedRoute,
16 | private router: Router) {
17 | }
18 |
19 | ngOnInit(): void {
20 | this.route.params.subscribe((params) => {
21 | this.load(params['id']);
22 | });
23 | }
24 |
25 | load(id: number) {
26 | this.bookEndpointService.getBook(id).subscribe((book) => {
27 | this.book = book;
28 | });
29 | }
30 |
31 | delete(id: number) {
32 | this.bookEndpointService.deleteBook(id).subscribe((response) => {
33 | this.router.navigate(['/book-list']);
34 | });
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Antonio Goncalves
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/ui-vintagestore/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ui-vintagestore",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "ng": "ng",
6 | "start": "ng serve",
7 | "build": "ng build",
8 | "test": "ng test",
9 | "lint": "ng lint"
10 | },
11 | "private": true,
12 | "dependencies": {
13 | "@angular/animations": "~10.2.0",
14 | "@angular/common": "~10.2.0",
15 | "@angular/compiler": "~10.2.0",
16 | "@angular/core": "~10.2.0",
17 | "@angular/forms": "~10.2.0",
18 | "@angular/platform-browser": "~10.2.0",
19 | "@angular/platform-browser-dynamic": "~10.2.0",
20 | "@angular/router": "~10.2.0",
21 | "bootstrap": "^4.5.2",
22 | "font-awesome": "^4.7.0",
23 | "jquery": "^3.5.1",
24 | "ngx-bootstrap": "^5.6.2",
25 | "popper": "^1.0.1",
26 | "rxjs": "~6.6.0",
27 | "tslib": "^2.0.0",
28 | "zone.js": "~0.10.2"
29 | },
30 | "devDependencies": {
31 | "@angular-devkit/build-angular": "~0.1002.0",
32 | "@angular/cli": "~10.2.0",
33 | "@angular/compiler-cli": "~10.2.0",
34 | "@types/node": "^12.11.1",
35 | "ts-node": "~8.3.0",
36 | "tslint": "~6.1.0",
37 | "typescript": "~4.0.2"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/rest-book/src/main/java/org/agoncal/fascicle/quarkus/book/BookApplication.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.book;
2 |
3 | import org.eclipse.microprofile.openapi.annotations.ExternalDocumentation;
4 | import org.eclipse.microprofile.openapi.annotations.OpenAPIDefinition;
5 | import org.eclipse.microprofile.openapi.annotations.info.Contact;
6 | import org.eclipse.microprofile.openapi.annotations.info.Info;
7 | import org.eclipse.microprofile.openapi.annotations.tags.Tag;
8 |
9 | import javax.ws.rs.ApplicationPath;
10 | import javax.ws.rs.core.Application;
11 |
12 | // tag::adocSnippet[]
13 | @ApplicationPath("/")
14 | @OpenAPIDefinition(
15 | info = @Info(title = "Book API",
16 | description = "This API allows CRUD operations on books",
17 | version = "2.0",
18 | contact = @Contact(name = "@agoncal", url = "https://twitter.com/agoncal")),
19 | externalDocs = @ExternalDocumentation(url = "https://github.com/agoncal/agoncal-fascicle-quarkus-pract", description = "All the Practising Quarkus code"),
20 | tags = {
21 | @Tag(name = "api", description = "Public API that can be used by anybody"),
22 | @Tag(name = "books", description = "Anybody interested in books")
23 | }
24 | )
25 | public class BookApplication extends Application {
26 | }
27 | // end::adocSnippet[]
28 |
--------------------------------------------------------------------------------
/first-step/src/test/java/org/agoncal/fascicle/quarkus/firststep/AuthorResourceTest.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.firststep;
2 |
3 | import io.quarkus.test.junit.QuarkusTest;
4 | import org.junit.jupiter.api.Test;
5 |
6 | import static io.restassured.RestAssured.given;
7 | import static javax.ws.rs.core.HttpHeaders.ACCEPT;
8 | import static javax.ws.rs.core.MediaType.TEXT_PLAIN;
9 | import static org.hamcrest.core.Is.is;
10 |
11 | /**
12 | * @author Antonio Goncalves
13 | * http://www.antoniogoncalves.org
14 | * --
15 | */
16 | // @formatter:off
17 | // tag::adocSnippet[]
18 | @QuarkusTest
19 | public class AuthorResourceTest {
20 |
21 | @Test
22 | public void shouldGetAllAuthors() {
23 | given()
24 | .header(ACCEPT, TEXT_PLAIN).
25 | when()
26 | .get("/authors").
27 | then()
28 | .assertThat()
29 | .statusCode(is(200))
30 | .and()
31 | .body(is("Isaac Asimov, Nora Jemisin, Douglas Adams"));
32 | }
33 |
34 | @Test
35 | public void shouldGetAnAuthor() {
36 | given()
37 | .header(ACCEPT, TEXT_PLAIN)
38 | .pathParam("index", 0).
39 | when()
40 | .get("/authors/{index}").
41 | then()
42 | .assertThat()
43 | .statusCode(is(200))
44 | .and()
45 | .body(is("Isaac Asimov"));
46 | }
47 | }
48 | // end::adocSnippet[]
49 |
--------------------------------------------------------------------------------
/rest-book/src/main/java/org/agoncal/fascicle/quarkus/book/health/DatabaseConnectionHealthCheck.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.book.health;
2 |
3 | import org.agoncal.fascicle.quarkus.book.Book;
4 | import org.agoncal.fascicle.quarkus.book.BookService;
5 | import org.eclipse.microprofile.health.HealthCheck;
6 | import org.eclipse.microprofile.health.HealthCheckResponse;
7 | import org.eclipse.microprofile.health.HealthCheckResponseBuilder;
8 | import org.eclipse.microprofile.health.Readiness;
9 |
10 | import javax.enterprise.context.ApplicationScoped;
11 | import javax.inject.Inject;
12 | import java.util.List;
13 |
14 | // tag::adocSnippet[]
15 | @Readiness
16 | @ApplicationScoped
17 | public class DatabaseConnectionHealthCheck implements HealthCheck {
18 |
19 | @Inject
20 | BookService bookService;
21 |
22 | @Override
23 | public HealthCheckResponse call() {
24 | HealthCheckResponseBuilder responseBuilder = HealthCheckResponse
25 | .named("Book Datasource connection health check");
26 |
27 | try {
28 | List books = bookService.findAllBooks();
29 | responseBuilder.withData("Number of books in the database", books.size()).up();
30 | } catch (IllegalStateException e) {
31 | responseBuilder.down();
32 | }
33 |
34 | return responseBuilder.build();
35 | }
36 | }
37 | // end::adocSnippet[]
38 |
--------------------------------------------------------------------------------
/rest-number/src/main/java/org/agoncal/fascicle/quarkus/number/NumberApplication.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.number;
2 |
3 | // tag::adocImports[]
4 | import org.eclipse.microprofile.openapi.annotations.ExternalDocumentation;
5 | import org.eclipse.microprofile.openapi.annotations.OpenAPIDefinition;
6 | import org.eclipse.microprofile.openapi.annotations.info.Contact;
7 | import org.eclipse.microprofile.openapi.annotations.info.Info;
8 | import org.eclipse.microprofile.openapi.annotations.tags.Tag;
9 |
10 | import javax.ws.rs.ApplicationPath;
11 | import javax.ws.rs.core.Application;
12 | // end::adocImports[]
13 |
14 | // tag::adocSnippet[]
15 | @ApplicationPath("/")
16 | @OpenAPIDefinition(
17 | info = @Info(title = "Number API",
18 | description = "This API allows to generate all sorts of numbers",
19 | version = "2.0",
20 | contact = @Contact(name = "@agoncal", url = "https://twitter.com/agoncal")),
21 | externalDocs = @ExternalDocumentation(url = "https://github.com/agoncal/agoncal-fascicle-quarkus-pract", description = "All the Practising Quarkus code"),
22 | tags = {
23 | @Tag(name = "api", description = "Public API that can be used by anybody"),
24 | @Tag(name = "numbers", description = "Anybody interested in numbers")
25 | }
26 | )
27 | public class NumberApplication extends Application {
28 | }
29 | // end::adocSnippet[]
30 |
--------------------------------------------------------------------------------
/rest-number/src/main/java/org/agoncal/fascicle/quarkus/number/BookNumbers.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.number;
2 |
3 | import org.eclipse.microprofile.openapi.annotations.media.Schema;
4 |
5 | // tag::adocImportJSonB[]
6 | import javax.json.bind.annotation.JsonbProperty;
7 | import javax.json.bind.annotation.JsonbTransient;
8 | // end::adocImportJSonB[]
9 | import java.time.Instant;
10 |
11 | // tag::adocSnippet[]
12 | // tag::adocOpenAPI[]
13 | @Schema(description = "Several formats of book numbers")
14 | // end::adocOpenAPI[]
15 | public class BookNumbers {
16 |
17 | // tag::adocOpenAPI[]
18 | @Schema(required = true)
19 | // end::adocOpenAPI[]
20 | // tag::adocJSonB[]
21 | @JsonbProperty("isbn_10")
22 | // end::adocJSonB[]
23 | public String isbn10;
24 | // tag::adocOpenAPI[]
25 | @Schema(required = true)
26 | // end::adocOpenAPI[]
27 | // tag::adocJSonB[]
28 | @JsonbProperty("isbn_13")
29 | // end::adocJSonB[]
30 | public String isbn13;
31 | public String asin;
32 | // tag::adocJSonB[]
33 | @JsonbProperty("ean_8")
34 | // end::adocJSonB[]
35 | public String ean8;
36 | // tag::adocJSonB[]
37 | @JsonbProperty("ean_13")
38 | // end::adocJSonB[]
39 | public String ean13;
40 | // tag::adocJSonB[]
41 | @JsonbTransient
42 | // end::adocJSonB[]
43 | public Instant generationDate;
44 | }
45 | // end::adocSnippet[]
46 |
--------------------------------------------------------------------------------
/rest-number/openapi.yaml:
--------------------------------------------------------------------------------
1 | openapi: 3.0.3
2 | info:
3 | title: Number API
4 | description: This API allows to generate all sorts of numbers
5 | contact:
6 | name: '@agoncal'
7 | url: https://twitter.com/agoncal
8 | version: "2.0"
9 | externalDocs:
10 | description: 'All the Practising Quarkus code'
11 | url: https://github.com/agoncal/agoncal-fascicle-quarkus-pract
12 | tags:
13 | - name: api
14 | description: Public API that can be used by anybody
15 | - name: numbers
16 | description: Anybody interested in numbers
17 | - name: Number Endpoint
18 | paths:
19 | /api/numbers:
20 | get:
21 | tags:
22 | - Number Endpoint
23 | summary: Generates book numbers
24 | description: "These book numbers have several formats: ISBN, ASIN and EAN"
25 | responses:
26 | "200":
27 | description: OK
28 | content:
29 | application/json:
30 | schema:
31 | $ref: '#/components/schemas/BookNumbers'
32 | components:
33 | schemas:
34 | BookNumbers:
35 | description: Several formats of book numbers
36 | required:
37 | - isbn_10
38 | - isbn_13
39 | type: object
40 | properties:
41 | asin:
42 | type: string
43 | ean_13:
44 | type: string
45 | ean_8:
46 | type: string
47 | isbn_10:
48 | type: string
49 | isbn_13:
50 | type: string
51 |
--------------------------------------------------------------------------------
/rest-number/src/main/java/org/agoncal/fascicle/quarkus/number/NumberApplicationLifeCycle.java:
--------------------------------------------------------------------------------
1 | package org.agoncal.fascicle.quarkus.number;
2 | //@formatter:off
3 |
4 | // tag::adocImports[]
5 | import org.jboss.logging.Logger;
6 | import io.quarkus.runtime.ShutdownEvent;
7 | import io.quarkus.runtime.StartupEvent;
8 | import io.quarkus.runtime.configuration.ProfileManager;
9 | import javax.enterprise.context.ApplicationScoped;
10 | import javax.enterprise.event.Observes;
11 | import javax.inject.Inject;
12 | // end::adocImports[]
13 |
14 | // tag::adocSnippet[]
15 | @ApplicationScoped
16 | class NumberApplicationLifeCycle {
17 |
18 | @Inject
19 | Logger LOGGER;
20 |
21 | void onStart(@Observes StartupEvent ev) {
22 | LOGGER.info(" _ _ _ ");
23 | LOGGER.info("| \\ | | | | ");
24 | LOGGER.info("| \\| |_ _ _ __ ___ | |__ ___ _ __");
25 | LOGGER.info("| . ` | | | | '_ ` _ \\| '_ \\ / _ \\ '__|");
26 | LOGGER.info("| |\\ | |_| | | | | | | |_) | __/ | ");
27 | LOGGER.info("\\_| \\_/\\__,_|_| |_| |_|_.__/ \\___|_| ");
28 | LOGGER.info(" Powered by Quarkus");
29 | // tag::adocProfile[]
30 | LOGGER.info("The application Number is starting with profile " + ProfileManager.getActiveProfile());
31 | // end::adocProfile[]
32 | }
33 |
34 | void onStop(@Observes ShutdownEvent ev) {
35 | LOGGER.info("The application Number is stopping...");
36 | }
37 | }
38 | // end::adocSnippet[]
39 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/book/book-list/book-list.component.html:
--------------------------------------------------------------------------------
1 |
2 | Books
3 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | | ID |
14 | Isbn |
15 | Title |
16 | Author |
17 | ISBN |
18 | |
19 |
20 |
21 |
22 |
23 |
24 | | {{book.id}} |
25 | {{book.isbn13}} |
26 | {{book.title | slice:0:50}} |
27 | {{book.author}} |
28 | {{book.isbn13}} |
29 |
30 |
31 |
35 |
39 |
40 | |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/load-vintagestore/src/main/java/org/agoncal/fascicle/quarkus/load/WeightedRandomResult.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package org.agoncal.fascicle.quarkus.load;
18 |
19 | import java.util.ArrayList;
20 | import java.util.Collection;
21 | import java.util.List;
22 | import java.util.Random;
23 | import java.util.function.Supplier;
24 |
25 | public class WeightedRandomResult implements Supplier {
26 | private final Random random = new Random();
27 | private final List results = new ArrayList<>();
28 |
29 | public WeightedRandomResult(final Collection results) {
30 | this.results.addAll(results);
31 | }
32 |
33 | public T get() {
34 | return this.results.get(random.nextInt(this.results.size()));
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/infrastructure/vintage-store-app.yaml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | # tag::adocSnippet[]
3 | services:
4 | ui-vintagestore:
5 | image: "agoncal/ui-vintagestore:2.0.0-SNAPSHOT"
6 | container_name: "vintage_store_ui"
7 | ports:
8 | - "8700:8700"
9 | depends_on:
10 | - rest-number
11 | - rest-book
12 | rest-number:
13 | image: "agoncal/rest-number:2.0.0-SNAPSHOT"
14 | container_name: "vintage_store_rest_number"
15 | ports:
16 | - "8701:8701"
17 | rest-book:
18 | image: "agoncal/rest-book:2.0.0-SNAPSHOT"
19 | container_name: "vintage_store_rest_book"
20 | ports:
21 | - "8702:8702"
22 | depends_on:
23 | database:
24 | condition: service_healthy
25 | environment:
26 | - QUARKUS_DATASOURCE_JDBC_URL=jdbc:postgresql://database:5432/books_database
27 | - ORG_AGONCAL_FASCICLE_QUARKUS_BOOK_CLIENT_NUMBERPROXY_MP_REST_URL=http://rest-number:8701
28 | database:
29 | image: "postgres:14.1"
30 | container_name: "vintage_store_books_database"
31 | ports:
32 | - "5432:5432"
33 | environment:
34 | - POSTGRES_DB=books_database
35 | - POSTGRES_USER=book
36 | - POSTGRES_PASSWORD=book
37 | healthcheck:
38 | test: ["CMD-SHELL", "pg_isready -U postgres"]
39 | interval: 5s
40 | timeout: 5s
41 | retries: 5
42 | monitoring:
43 | image: "prom/prometheus:v2.31.1"
44 | container_name: "vintage_store_monitoring"
45 | ports:
46 | - 9090:9090
47 | volumes:
48 | - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml
49 | # end::adocSnippet[]
50 |
--------------------------------------------------------------------------------
/pom_to_be_renamed.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | org.agoncal.fascicle
6 | quarkus-practising
7 | 2.0.0-SNAPSHOT
8 | pom
9 | Practising Quarkus
10 |
11 |
12 | first-step
13 | infrastructure
14 | load-vintagestore
15 | ui-vintagestore
16 |
17 |
18 |
19 |
20 |
21 |
22 | org.apache.maven.plugins
23 | maven-assembly-plugin
24 | 3.2.0
25 |
26 |
27 |
28 |
29 |
30 | org.apache.maven.plugins
31 | maven-assembly-plugin
32 |
33 | agoncal-fascicle-quarkus-practising-${project.version}
34 | false
35 | true
36 | false
37 |
38 | assembly.xml
39 |
40 | dist
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/shared/api/numberEndpoint.service.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Number API
3 | * This API allows to generate all sorts of numbers
4 | *//* tslint:disable:no-unused-variable member-ordering */
5 |
6 | import {Injectable} from '@angular/core';
7 | import {HttpClient, HttpHeaders} from '@angular/common/http';
8 | import {Observable} from 'rxjs';
9 | import {BookNumbers} from '../model/bookNumbers';
10 |
11 | // tag::adocSnippet[]
12 | @Injectable()
13 | export class NumberEndpointService {
14 |
15 | protected basePath = 'http://localhost:8701';
16 |
17 | constructor(protected httpClient: HttpClient) {
18 | }
19 |
20 | // tag::adocSkip[]
21 |
22 | public defaultHeaders = new HttpHeaders();
23 |
24 | /**
25 | * Generates book numbers
26 | * These book numbers have several formats: ISBN, ASIN and EAN
27 | * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
28 | * @param reportProgress flag to report request and response progress.
29 | */
30 | // end::adocSkip[]
31 | public generatesBookNumbers(observe: any = 'body', reportProgress: boolean = false): Observable {
32 |
33 | let headers = this.defaultHeaders;
34 |
35 | // to determine the Accept header
36 | let httpHeaderAccepts: string[] = [
37 | 'application/json'
38 | ];
39 | headers = headers.set('Accept', httpHeaderAccepts);
40 |
41 | return this.httpClient.request('get', `${this.basePath}/api/numbers`,
42 | {
43 | headers: headers,
44 | observe: observe,
45 | reportProgress: reportProgress
46 | }
47 | );
48 | }
49 | }
50 | // end::adocSnippet[]
51 |
--------------------------------------------------------------------------------
/ui-vintagestore/src/app/number/number-generate/number-generate.component.html:
--------------------------------------------------------------------------------
1 |
2 | Book Numbers
3 |
7 |
8 |
9 |
41 |
--------------------------------------------------------------------------------
/load-vintagestore/src/main/java/org/agoncal/fascicle/quarkus/load/ScenarioNumber.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package org.agoncal.fascicle.quarkus.load;
18 |
19 | import java.util.Collections;
20 | import java.util.List;
21 | import java.util.stream.Stream;
22 |
23 | import static org.agoncal.fascicle.quarkus.load.Endpoint.endpoint;
24 | import static java.util.stream.Collectors.collectingAndThen;
25 | import static java.util.stream.Collectors.toList;
26 |
27 | public class ScenarioNumber extends ScenarioInvoker {
28 |
29 | // tag::adocSnippet[]
30 | private static final String targetUrl = "http://localhost:8701";
31 |
32 | private static final String contextRoot = "/api/numbers";
33 |
34 | @Override
35 | protected String getTargetUrl() {
36 | return targetUrl;
37 | }
38 |
39 | @Override
40 | protected List getEndpoints() {
41 | return Stream.of(
42 | endpoint(contextRoot, "GET"),
43 | endpoint(contextRoot + "/ping", "GET")
44 | )
45 | .collect(collectingAndThen(toList(), Collections::unmodifiableList));
46 | }
47 | // end::adocSnippet[]
48 | }
49 |
--------------------------------------------------------------------------------
/assembly.xml:
--------------------------------------------------------------------------------
1 |
4 | agoncal-fascicle-quarkus-pract
5 |
6 | zip
7 |
8 | true
9 |
10 |
11 |
12 | first-step
13 | true
14 |
15 | **/target/**
16 | *.iml
17 |
18 |
19 |
20 | infrastructure
21 | true
22 |
23 | **/target/**
24 | *.iml
25 |
26 |
27 |
28 | load-vintagestore
29 | true
30 |
31 | **/target/**
32 | *.iml
33 |
34 |
35 |
36 | ui-vintagestore
37 | true
38 |
39 | *.iml
40 | package-lock.json
41 | README.md
42 | **/dist/**
43 | **/target/**
44 | **/node/**
45 | **/node_modules/**
46 |
47 |
48 |
49 | ${basedir}
50 | false
51 |
52 | .dockerignore
53 | .editorconfig
54 | .gitignore
55 | pom.xml
56 | README.md
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/rest-book/src/main/docker/Dockerfile.legacy-jar:
--------------------------------------------------------------------------------
1 | ####
2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
3 | #
4 | # Before building the container image run:
5 | #
6 | # ./mvnw package -Dquarkus.package.type=legacy-jar
7 | #
8 | # Then, build the image with:
9 | #
10 | # docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/rest-book-legacy-jar .
11 | #
12 | # Then run the container using:
13 | #
14 | # docker run -i --rm -p 8080:8080 quarkus/rest-book-legacy-jar
15 | #
16 | # If you want to include the debug port into your docker image
17 | # you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5005
18 | #
19 | # Then run the container using :
20 | #
21 | # docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/rest-book-legacy-jar
22 | #
23 | ###
24 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4
25 |
26 | ARG JAVA_PACKAGE=java-11-openjdk-headless
27 | ARG RUN_JAVA_VERSION=1.3.8
28 | ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
29 | # Install java and the run-java script
30 | # Also set up permissions for user `1001`
31 | RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \
32 | && microdnf update \
33 | && microdnf clean all \
34 | && mkdir /deployments \
35 | && chown 1001 /deployments \
36 | && chmod "g+rwX" /deployments \
37 | && chown 1001:root /deployments \
38 | && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
39 | && chown 1001 /deployments/run-java.sh \
40 | && chmod 540 /deployments/run-java.sh \
41 | && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/conf/security/java.security
42 |
43 | # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
44 | ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
45 | COPY target/lib/* /deployments/lib/
46 | COPY target/*-runner.jar /deployments/app.jar
47 |
48 | EXPOSE 8702
49 | USER 1001
50 |
51 | ENTRYPOINT [ "/deployments/run-java.sh" ]
52 |
--------------------------------------------------------------------------------
/rest-number/src/main/docker/Dockerfile.legacy-jar:
--------------------------------------------------------------------------------
1 | ####
2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
3 | #
4 | # Before building the container image run:
5 | #
6 | # ./mvnw package -Dquarkus.package.type=legacy-jar
7 | #
8 | # Then, build the image with:
9 | #
10 | # docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/rest-number-legacy-jar .
11 | #
12 | # Then run the container using:
13 | #
14 | # docker run -i --rm -p 8080:8080 quarkus/rest-number-legacy-jar
15 | #
16 | # If you want to include the debug port into your docker image
17 | # you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5005
18 | #
19 | # Then run the container using :
20 | #
21 | # docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/rest-number-legacy-jar
22 | #
23 | ###
24 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4
25 |
26 | ARG JAVA_PACKAGE=java-11-openjdk-headless
27 | ARG RUN_JAVA_VERSION=1.3.8
28 | ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
29 | # Install java and the run-java script
30 | # Also set up permissions for user `1001`
31 | RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \
32 | && microdnf update \
33 | && microdnf clean all \
34 | && mkdir /deployments \
35 | && chown 1001 /deployments \
36 | && chmod "g+rwX" /deployments \
37 | && chown 1001:root /deployments \
38 | && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
39 | && chown 1001 /deployments/run-java.sh \
40 | && chmod 540 /deployments/run-java.sh \
41 | && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/conf/security/java.security
42 |
43 | # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
44 | ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
45 | COPY target/lib/* /deployments/lib/
46 | COPY target/*-runner.jar /deployments/app.jar
47 |
48 | EXPOSE 8701
49 | USER 1001
50 |
51 | ENTRYPOINT [ "/deployments/run-java.sh" ]
52 |
--------------------------------------------------------------------------------
/event-inventory/src/main/docker/Dockerfile.legacy-jar:
--------------------------------------------------------------------------------
1 | ####
2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
3 | #
4 | # Before building the container image run:
5 | #
6 | # ./mvnw package -Dquarkus.package.type=legacy-jar
7 | #
8 | # Then, build the image with:
9 | #
10 | # docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/event-inventory-legacy-jar .
11 | #
12 | # Then run the container using:
13 | #
14 | # docker run -i --rm -p 8080:8080 quarkus/event-inventory-legacy-jar
15 | #
16 | # If you want to include the debug port into your docker image
17 | # you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5005
18 | #
19 | # Then run the container using :
20 | #
21 | # docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/event-inventory-legacy-jar
22 | #
23 | ###
24 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4
25 |
26 | ARG JAVA_PACKAGE=java-11-openjdk-headless
27 | ARG RUN_JAVA_VERSION=1.3.8
28 | ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
29 | # Install java and the run-java script
30 | # Also set up permissions for user `1001`
31 | RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \
32 | && microdnf update \
33 | && microdnf clean all \
34 | && mkdir /deployments \
35 | && chown 1001 /deployments \
36 | && chmod "g+rwX" /deployments \
37 | && chown 1001:root /deployments \
38 | && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
39 | && chown 1001 /deployments/run-java.sh \
40 | && chmod 540 /deployments/run-java.sh \
41 | && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/conf/security/java.security
42 |
43 | # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
44 | ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
45 | COPY target/lib/* /deployments/lib/
46 | COPY target/*-runner.jar /deployments/app.jar
47 |
48 | EXPOSE 8080
49 | USER 1001
50 |
51 | ENTRYPOINT [ "/deployments/run-java.sh" ]
52 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.agoncal.fascicle
7 | quarkus-practising
8 | 2.0.0-SNAPSHOT
9 | pom
10 | Practising Quarkus
11 |
12 |
13 |
14 |
15 | event-inventory
16 |
17 | first-step
18 | infrastructure
19 | load-vintagestore
20 |
21 | rest-book
22 |
23 |
24 | rest-number
25 |
26 | ui-vintagestore
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | org.apache.maven.plugins
36 | maven-assembly-plugin
37 | 3.2.0
38 |
39 |
40 |
41 |
42 |
43 | org.apache.maven.plugins
44 | maven-assembly-plugin
45 |
46 | agoncal-fascicle-quarkus-practising-${project.version}
47 | false
48 | true
49 | false
50 |
51 | assembly.xml
52 |
53 | dist
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/rest-book/src/main/docker/Dockerfile.jvm:
--------------------------------------------------------------------------------
1 | ####
2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
3 | #
4 | # Before building the container image run:
5 | #
6 | # ./mvnw package
7 | #
8 | # Then, build the image with:
9 | #
10 | # docker build -f src/main/docker/Dockerfile.jvm -t quarkus/rest-book-jvm .
11 | #
12 | # Then run the container using:
13 | #
14 | # docker run -i --rm -p 8080:8080 quarkus/rest-book-jvm
15 | #
16 | # If you want to include the debug port into your docker image
17 | # you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5005
18 | #
19 | # Then run the container using :
20 | #
21 | # docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/rest-book-jvm
22 | #
23 | ###
24 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4
25 |
26 | ARG JAVA_PACKAGE=java-11-openjdk-headless
27 | ARG RUN_JAVA_VERSION=1.3.8
28 | ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
29 | # Install java and the run-java script
30 | # Also set up permissions for user `1001`
31 | RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \
32 | && microdnf update \
33 | && microdnf clean all \
34 | && mkdir /deployments \
35 | && chown 1001 /deployments \
36 | && chmod "g+rwX" /deployments \
37 | && chown 1001:root /deployments \
38 | && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
39 | && chown 1001 /deployments/run-java.sh \
40 | && chmod 540 /deployments/run-java.sh \
41 | && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/conf/security/java.security
42 |
43 | # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
44 | ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
45 | # We make four distinct layers so if there are application changes the library layers can be re-used
46 | COPY --chown=1001 target/quarkus-app/lib/ /deployments/lib/
47 | COPY --chown=1001 target/quarkus-app/*.jar /deployments/
48 | COPY --chown=1001 target/quarkus-app/app/ /deployments/app/
49 | COPY --chown=1001 target/quarkus-app/quarkus/ /deployments/quarkus/
50 |
51 | EXPOSE 8702
52 | USER 1001
53 |
54 | ENTRYPOINT [ "/deployments/run-java.sh" ]
55 |
--------------------------------------------------------------------------------
/event-inventory/src/main/docker/Dockerfile.jvm:
--------------------------------------------------------------------------------
1 | ####
2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
3 | #
4 | # Before building the container image run:
5 | #
6 | # ./mvnw package
7 | #
8 | # Then, build the image with:
9 | #
10 | # docker build -f src/main/docker/Dockerfile.jvm -t quarkus/event-inventory-jvm .
11 | #
12 | # Then run the container using:
13 | #
14 | # docker run -i --rm -p 8080:8080 quarkus/event-inventory-jvm
15 | #
16 | # If you want to include the debug port into your docker image
17 | # you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5005
18 | #
19 | # Then run the container using :
20 | #
21 | # docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/event-inventory-jvm
22 | #
23 | ###
24 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4
25 |
26 | ARG JAVA_PACKAGE=java-11-openjdk-headless
27 | ARG RUN_JAVA_VERSION=1.3.8
28 | ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
29 | # Install java and the run-java script
30 | # Also set up permissions for user `1001`
31 | RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \
32 | && microdnf update \
33 | && microdnf clean all \
34 | && mkdir /deployments \
35 | && chown 1001 /deployments \
36 | && chmod "g+rwX" /deployments \
37 | && chown 1001:root /deployments \
38 | && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
39 | && chown 1001 /deployments/run-java.sh \
40 | && chmod 540 /deployments/run-java.sh \
41 | && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/conf/security/java.security
42 |
43 | # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
44 | ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
45 | # We make four distinct layers so if there are application changes the library layers can be re-used
46 | COPY --chown=1001 target/quarkus-app/lib/ /deployments/lib/
47 | COPY --chown=1001 target/quarkus-app/*.jar /deployments/
48 | COPY --chown=1001 target/quarkus-app/app/ /deployments/app/
49 | COPY --chown=1001 target/quarkus-app/quarkus/ /deployments/quarkus/
50 |
51 | EXPOSE 8080
52 | USER 1001
53 |
54 | ENTRYPOINT [ "/deployments/run-java.sh" ]
55 |
56 |
--------------------------------------------------------------------------------
/rest-number/src/main/docker/Dockerfile.jvm:
--------------------------------------------------------------------------------
1 | ####
2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
3 | #
4 | # Before building the container image run:
5 | #
6 | # ./mvnw package
7 | #
8 | # Then, build the image with:
9 | #
10 | # docker build -f src/main/docker/Dockerfile.jvm -t quarkus/rest-number-jvm .
11 | #
12 | # Then run the container using:
13 | #
14 | # docker run -i --rm -p 8080:8080 quarkus/rest-number-jvm
15 | #
16 | # If you want to include the debug port into your docker image
17 | # you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5005
18 | #
19 | # Then run the container using :
20 | #
21 | # docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/rest-number-jvm
22 | #
23 | ###
24 | # tag::adocSnippet[]
25 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.4
26 |
27 | ARG JAVA_PACKAGE=java-11-openjdk-headless
28 | ARG RUN_JAVA_VERSION=1.3.8
29 | ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
30 | # Install java and the run-java script
31 | # Also set up permissions for user `1001`
32 | RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \
33 | && microdnf update \
34 | && microdnf clean all \
35 | && mkdir /deployments \
36 | && chown 1001 /deployments \
37 | && chmod "g+rwX" /deployments \
38 | && chown 1001:root /deployments \
39 | && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
40 | && chown 1001 /deployments/run-java.sh \
41 | && chmod 540 /deployments/run-java.sh \
42 | && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/conf/security/java.security
43 |
44 | # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
45 | ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
46 | # We make four distinct layers so if there are application changes the library layers can be re-used
47 | COPY --chown=1001 target/quarkus-app/lib/ /deployments/lib/
48 | COPY --chown=1001 target/quarkus-app/*.jar /deployments/
49 | COPY --chown=1001 target/quarkus-app/app/ /deployments/app/
50 | COPY --chown=1001 target/quarkus-app/quarkus/ /deployments/quarkus/
51 |
52 | EXPOSE 8701
53 | USER 1001
54 |
55 | ENTRYPOINT [ "/deployments/run-java.sh" ]
56 | # end::adocSnippet[]
57 |
--------------------------------------------------------------------------------
/load-vintagestore/src/main/java/org/agoncal/fascicle/quarkus/load/ScenarioInvoker.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package org.agoncal.fascicle.quarkus.load;
18 |
19 | import com.github.javafaker.Faker;
20 |
21 | import javax.ws.rs.client.ClientBuilder;
22 | import javax.ws.rs.client.WebTarget;
23 | import javax.ws.rs.core.Response;
24 | import java.util.List;
25 | import java.util.concurrent.TimeUnit;
26 | import java.util.logging.Logger;
27 |
28 | import static java.lang.String.format;
29 |
30 | public abstract class ScenarioInvoker implements Runnable {
31 |
32 | private static Logger LOGGER = Logger.getLogger(ScenarioInvoker.class.getName());
33 |
34 | protected Faker faker = new Faker();
35 |
36 | private WeightedRandomResult endpointsToExecute = new WeightedRandomResult<>(getEndpoints());
37 |
38 | protected abstract String getTargetUrl();
39 |
40 | protected abstract List getEndpoints();
41 |
42 | @Override
43 | public void run() {
44 | while (true) {
45 | try {
46 | final Endpoint endpoint = endpointsToExecute.get();
47 | final WebTarget webTarget = ClientBuilder.newClient().target(getTargetUrl())
48 | .path(endpoint.getPath())
49 | .resolveTemplates(endpoint.getTemplates());
50 | final Response response = webTarget.request().method(endpoint.getMethod(), endpoint.getEntity());
51 | LOGGER.info(format("%s - %s - %d", endpoint.getMethod(), webTarget.getUri(), response.getStatus()));
52 | response.close();
53 | sleep();
54 | } catch (final Exception e) {
55 | e.printStackTrace();
56 | }
57 | }
58 | }
59 |
60 | private void sleep() {
61 | try {
62 | TimeUnit.MILLISECONDS.sleep(500);
63 | } catch (InterruptedException e) {
64 | e.printStackTrace();
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/load-vintagestore/src/main/java/org/agoncal/fascicle/quarkus/load/Endpoint.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package org.agoncal.fascicle.quarkus.load;
18 |
19 | import javax.ws.rs.client.Entity;
20 | import java.util.HashMap;
21 | import java.util.Map;
22 | import java.util.Optional;
23 | import java.util.function.Supplier;
24 |
25 | public class Endpoint {
26 | private String path;
27 | private String method;
28 | private Supplier