This commit is contained in:
jamesfalkner
2019-07-27 10:38:31 -04:00
parent 0cda1a374c
commit b488b0b3c4
13 changed files with 48 additions and 48 deletions

View File

@@ -1,7 +1,7 @@
= Dependency Injection
:experimental:
In the previous step you created a basic RESTful Java application with Quarkus. In this step we'll add a custom bean using dependency injection (DI). Quarkus DI solution is based on the http://docs.jboss.org/cdi/spec/2.0/cdi-spec.html[Contexts and Dependency Injection for Java 2.0 specification,target=_blank]. Because of the dynamic nature of some CDI APIs which conflict with native compilation, only a subset of the CDI features are implemented - see also the https://quarkus.io/guides/cdi-reference#supported_features[list,target=_blank] of supported features.
In the previous step you created a basic RESTful Java application with Quarkus. In this step we'll add a custom bean using dependency injection (DI). Quarkus DI solution is based on the http://docs.jboss.org/cdi/spec/2.0/cdi-spec.html[Contexts and Dependency Injection for Java 2.0 specification,window=_blank]. Because of the dynamic nature of some CDI APIs which conflict with native compilation, only a subset of the CDI features are implemented - see also the https://quarkus.io/guides/cdi-reference#supported_features[list,window=_blank] of supported features.
== Add Custom Bean

View File

@@ -14,9 +14,9 @@ There are of course a category of issues that can't be resolved by restarting th
=== Add Extension
Let's build a simple REST application endpoint exposes https://microprofile.io[MicroProfile,target=_blank] Health checks at the `/health` endpoint according to the specification. It will also provide several other REST endpoints to allow us to dynamically query the health of our Quarkus application.
Let's build a simple REST application endpoint exposes https://microprofile.io[MicroProfile,window=_blank] Health checks at the `/health` endpoint according to the specification. It will also provide several other REST endpoints to allow us to dynamically query the health of our Quarkus application.
We'll need to add a https://quarkus.io/extensions[Quarkus Extension,target=_blank] to enable this feature in our app. Fortunately, adding a Quarkus extension is super easy. We'll cover extensions in more depth in other sections of this workshop but for now, open a Terminal and execute the following command to add the extension to our project's `pom.xml`:
We'll need to add a https://quarkus.io/extensions[Quarkus Extension,window=_blank] to enable this feature in our app. Fortunately, adding a Quarkus extension is super easy. We'll cover extensions in more depth in other sections of this workshop but for now, open a Terminal and execute the following command to add the extension to our project's `pom.xml`:
[source, sh, role="copypaste"]
----
@@ -254,7 +254,7 @@ Later, when we deploy this to our Kubernetes cluster, we'll configure it to use
Hardcoded values in your code is a no go (even if we all did it at some point ;-)). In this step, we learn how to configure your application to externalize configuration.
Quarkus uses https://microprofile.io/project/eclipse/microprofile-config[MicroProfile Config,target=_blank] to inject the configuration into the application. The injection uses the `@ConfigProperty` annotation, for example:
Quarkus uses https://microprofile.io/project/eclipse/microprofile-config[MicroProfile Config,window=_blank] to inject the configuration into the application. The injection uses the `@ConfigProperty` annotation, for example:
[source, java]
----
@@ -264,7 +264,7 @@ String message;
[NOTE]
====
When injecting a configured value, you can use `@Inject @ConfigProperty` or just `@ConfigProperty`. The `@Inject` annotation is not necessary for members annotated with `@ConfigProperty`, a behavior which differs from https://microprofile.io/project/eclipse/microprofile-config[MicroProfile Config,target=_blank].
When injecting a configured value, you can use `@Inject @ConfigProperty` or just `@ConfigProperty`. The `@Inject` annotation is not necessary for members annotated with `@ConfigProperty`, a behavior which differs from https://microprofile.io/project/eclipse/microprofile-config[MicroProfile Config,window=_blank].
====
=== Add some external config
@@ -376,7 +376,7 @@ You can override these runtime properties with the following mechanisms (in decr
[NOTE]
====
Environment variables names are following the conversion rules of https://github.com/eclipse/microprofile-config/blob/master/spec/src/main/asciidoc/configsources.asciidoc#default-configsources[Eclipse MicroProfile Config sources,target=_blank]
Environment variables names are following the conversion rules of https://github.com/eclipse/microprofile-config/blob/master/spec/src/main/asciidoc/configsources.asciidoc#default-configsources[Eclipse MicroProfile Config sources,window=_blank]
====
=== Configuration Profiles
@@ -443,7 +443,7 @@ What did you get? You should get `hello production quarkus!` indicating that the
[NOTE]
====
In this example we read configuration properties from `application.properties`. You can also introduce custom configuration sources in the standard MicroProfile Config manner. To do this, you must provide a class which implements either `org.eclipse.microprofile.config.spi.ConfigSource` or `org.eclipse.microprofile.config.spi.ConfigSourceProvider`. Create a service file for the class and it will be detected and installed at application startup. https://microprofile.io/project/eclipse/microprofile-config[More Info,target=_blank]. This would be useful, for example, to read directly from **Kubernetes ConfigMap**s.
In this example we read configuration properties from `application.properties`. You can also introduce custom configuration sources in the standard MicroProfile Config manner. To do this, you must provide a class which implements either `org.eclipse.microprofile.config.spi.ConfigSource` or `org.eclipse.microprofile.config.spi.ConfigSourceProvider`. Create a service file for the class and it will be detected and installed at application startup. https://microprofile.io/project/eclipse/microprofile-config[More Info,window=_blank]. This would be useful, for example, to read directly from **Kubernetes ConfigMap**s.
====
== Cleanup

View File

@@ -3,7 +3,7 @@
With our app fully ready for its first cloud native deployment, let's package it up for deployment to our Kubernetes platform as a native image. We'll use some OpenShift tooling to accomplish this.
OpenShift is a commercially supported distribution of Kubernetes from Red Hat. The platform is also available as open source, in the form of https://www.okd.io/[OKD,target=_blank], the Origin Community Distribution of Kubernetes that powers Red Hat OpenShift.
OpenShift is a commercially supported distribution of Kubernetes from Red Hat. The platform is also available as open source, in the form of https://www.okd.io/[OKD,window=_blank], the Origin Community Distribution of Kubernetes that powers Red Hat OpenShift.
== Build native image
@@ -49,7 +49,7 @@ Congratulations, you are now authenticated to the OpenShift server.
The login session might timeout after long periods of inactivity. If this happens, you'll get messages like `Error from server (Forbidden): xxxxx is forbidden: User "system:anonymous" cannot xxxxx`. Simply re-issue the above login command to re-establish a session.
====
https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/[Namespaces,target=_blank]
https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/[Namespaces,window=_blank]
are a top level concept to help you organize your deployments and teams of developers. A
namespace allows a community of users (or a user) to organize and manage
their content in isolation from other communities. OpenShift _projects_ provide additional functionality for managing Kubernetes namespaces.
@@ -68,7 +68,7 @@ You should get a `--> Success` message at the end.
[NOTE]
====
This build uses the new https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux_atomic_host/7/html/getting_started_with_containers/using_red_hat_base_container_images_standard_and_minimal[Red Hat Universal Base Image,target=_blank], providing foundational software needed to run most applications, while staying at a reasonable size.
This build uses the new https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux_atomic_host/7/html/getting_started_with_containers/using_red_hat_base_container_images_standard_and_minimal[Red Hat Universal Base Image,window=_blank], providing foundational software needed to run most applications, while staying at a reasonable size.
====
And then start and watch the build, which will take about a minute to complete:

View File

@@ -5,7 +5,7 @@ One of the main goals of Quarkus is ease of extensibility and to build a vibrant
Think of Quarkus extensions as your project dependencies. Extensions configure, boot and integrate a framework or technology into your Quarkus application. They also do all of the heavy lifting of providing the right information to GraalVM for your application to compile natively.
Quarkus aims to provide a support for a full https://quarkus.io/extensions/[extension ecosystem,target=_blank], to make it easy to discover and consume 3rd party extensions, as well as providing easier version management.
Quarkus aims to provide a support for a full https://quarkus.io/extensions/[extension ecosystem,window=_blank], to make it easy to discover and consume 3rd party extensions, as well as providing easier version management.
== List extensions
@@ -80,10 +80,10 @@ Quarkus extensions add a new developer focused behavior to the core offering, an
This means that metadata is only processed once at build time, which both saves on startup time, and also on memory usage as the classes etc that are used for processing are not loaded (or even present) in the runtime JVM.
Writing a Quarkus extension is beyond the scope of this lab, so consult the https://quarkus.io/guides/extension-authors-guide[Extension Author's Guide,target=_blank] for more detail on writing your own extension.
Writing a Quarkus extension is beyond the scope of this lab, so consult the https://quarkus.io/guides/extension-authors-guide[Extension Author's Guide,window=_blank] for more detail on writing your own extension.
== Congratulations
Quarkus aims to provide a support for a full https://quarkus.io/extensions/[extension ecosystem,target=_blank], to make it easy to discover and consume 3rd party extensions, as well as providing easier version management.
Quarkus aims to provide a support for a full https://quarkus.io/extensions/[extension ecosystem,window=_blank], to make it easy to discover and consume 3rd party extensions, as well as providing easier version management.
We'll be adding additional extensions as we go along in other sections of this workshop.

View File

@@ -1,7 +1,7 @@
= Reactive Streams with Quarkus and Kafka
:experimental:
In this exercise, you will use the Quarkus Kafka extension to build a streaming application using MicroProfile Reative Streams Messaging and https://kafka.apache.org[Apache Kafka,target=_blank], a distributed streaming platform. You will also use https://strimzi.io/[Strimzi,target=_blank], which provides an easy way to run an Apache Kafka cluster on Kubernetes using https://operatorhub.io/what-is-an-operator[Operators,target=_blank].
In this exercise, you will use the Quarkus Kafka extension to build a streaming application using MicroProfile Reative Streams Messaging and https://kafka.apache.org[Apache Kafka,window=_blank], a distributed streaming platform. You will also use https://strimzi.io/[Strimzi,window=_blank], which provides an easy way to run an Apache Kafka cluster on Kubernetes using https://operatorhub.io/what-is-an-operator[Operators,window=_blank].
== What is Apache Kafka?
@@ -30,7 +30,7 @@ Strimzi provides three operators:
== The Goal
In this exercise, we are going to generate (random) names in one component. These names are written in a Kafka topic (`names`). A second component reads from the `names` Kafka topic and applies some magic conversion to the name (adding an honorific). The result is sent to an _in-memory stream_ consumed by a JAX-RS resource. The data is sent to a browser using https://www.w3.org/TR/eventsource/[_server-sent events_,target=_blank] and displayed in the browser. It will look like this:
In this exercise, we are going to generate (random) names in one component. These names are written in a Kafka topic (`names`). A second component reads from the `names` Kafka topic and applies some magic conversion to the name (adding an honorific). The result is sent to an _in-memory stream_ consumed by a JAX-RS resource. The data is sent to a browser using https://www.w3.org/TR/eventsource/[_server-sent events_,window=_blank] and displayed in the browser. It will look like this:
image::names.png[names,800]
@@ -218,7 +218,7 @@ public class NameResource {
[NOTE]
====
There is a pre-created `names.html` page for you to use (in the `src/main/resources/META-INF/resources` directory) which will make a request to this `/names/stream` endpoint using standard JavaScript running in the browser and draw the resulting names using the https://d3js.org/[D3.js library,target=_blank]. The JavaScript that makes this call looks like this (do not copy this into anything!):
There is a pre-created `names.html` page for you to use (in the `src/main/resources/META-INF/resources` directory) which will make a request to this `/names/stream` endpoint using standard JavaScript running in the browser and draw the resulting names using the https://d3js.org/[D3.js library,window=_blank]. The JavaScript that makes this call looks like this (do not copy this into anything!):
[source,javascript]
----
@@ -267,7 +267,7 @@ Add the following values to the `application.properties`:
----
We have prefixed these with `%prod` to avoid our app trying to connect when in `dev` or `test` mode.
More details about this configuration is available on the https://kafka.apache.org/documentation/#producerconfigs[Producer configuration] and https://kafka.apache.org/documentation/#consumerconfigs[Consumer configuration,target=_blank] section from the Kafka documentation.
More details about this configuration is available on the https://kafka.apache.org/documentation/#producerconfigs[Producer configuration] and https://kafka.apache.org/documentation/#consumerconfigs[Consumer configuration,window=_blank] section from the Kafka documentation.
[NOTE]
====
@@ -308,5 +308,5 @@ These are the original names streamed through Kafka, altered to add a random hon
This guide has shown how you can interact with Kafka using Quarkus. It utilizes MicroProfile Reactive Messaging to build data streaming applications.
If you want to go further check the documentation of https://smallrye.io/smallrye-reactive-messaging[SmallRye Reactive Messaging,target=_blank], the implementation used in Quarkus.
If you want to go further check the documentation of https://smallrye.io/smallrye-reactive-messaging[SmallRye Reactive Messaging,window=_blank], the implementation used in Quarkus.

View File

@@ -18,7 +18,7 @@ The asynchronous message passing feature in Quarkus allows _replying_ to message
== Add extension
This mechanism uses the https://vertx.io/docs/vertx-core/java/#event_bus[Vert.x EventBus,target=_blank], so you need to enable the `vertx` extension to use this feature. Add the extension in the Terminal using this command:
This mechanism uses the https://vertx.io/docs/vertx-core/java/#event_bus[Vert.x EventBus,window=_blank], so you need to enable the `vertx` extension to use this feature. Add the extension in the Terminal using this command:
[source,sh,role="copypaste"]
----
@@ -27,7 +27,7 @@ mvn quarkus:add-extension -Dextensions="vertx"
[NOTE]
====
https://vertx.io/[Eclipse Vert.x,target=_blank] is a toolkit for building reactive applications. It is designed to be lightweight and embeddable. Vert.x defines a reactive execution model and provides a large ecosystem. Quarkus integrates Vert.x to implement different reactive features, such as asynchronous message passing (the subject of this exercise), and non-blocking HTTP client. Basically, Quarkus uses Vert.x as its reactive engine. While lots of reactive features from Quarkus dont show Vert.x, its used underneath. But you can also access the managed Vert.x instance and benefit from the Vert.x ecosystem.
https://vertx.io/[Eclipse Vert.x,window=_blank] is a toolkit for building reactive applications. It is designed to be lightweight and embeddable. Vert.x defines a reactive execution model and provides a large ecosystem. Quarkus integrates Vert.x to implement different reactive features, such as asynchronous message passing (the subject of this exercise), and non-blocking HTTP client. Basically, Quarkus uses Vert.x as its reactive engine. While lots of reactive features from Quarkus dont show Vert.x, its used underneath. But you can also access the managed Vert.x instance and benefit from the Vert.x ecosystem.
====
Quarkus provides 3 Vert.x APIs:

View File

@@ -1,18 +1,18 @@
= Monitoring Quarkus Apps using MicroProfile Metrics
:experimental:
This exercise demonstrates how your Quarkus application can utilize the https://github.com/eclipse/microprofile-metrics[MicroProfile Metrics,target=_blank] specification through the SmallRye Metrics extension.
This exercise demonstrates how your Quarkus application can utilize the https://github.com/eclipse/microprofile-metrics[MicroProfile Metrics,window=_blank] specification through the SmallRye Metrics extension.
MicroProfile Metrics allows applications to gather various metrics and statistics that provide insights into what is happening inside the application. They ey serve to pinpoint issues, provide long term trend data for capacity planning and pro-active discovery of issues (e.g. disk usage growing without bounds). Metrics can also help those scheduling systems decide when to scale the application to run on more or fewer machines.
The metrics can be read remotely using JSON format or the https://prometheus.io/docs/instrumenting/exposition_formats/#text-based-format[OpenMetrics text format,target=_blank], so that they can be processed by additional tools such as Prometheus, and stored for analysis and visualisation. You can then use tools like http://prometheus.io[Prometheus,target=_blank] and http://grafana.com[Grafana,target=_blank] to collect and display metrics for your Quarkus apps.
The metrics can be read remotely using JSON format or the https://prometheus.io/docs/instrumenting/exposition_formats/#text-based-format[OpenMetrics text format,window=_blank], so that they can be processed by additional tools such as Prometheus, and stored for analysis and visualisation. You can then use tools like http://prometheus.io[Prometheus,window=_blank] and http://grafana.com[Grafana,window=_blank] to collect and display metrics for your Quarkus apps.
== Install Prometheus
First, let's install Prometheus. Prometheus is an open-source systems monitoring and alerting toolkit featuring:
* a multi-dimensional https://prometheus.io/docs/concepts/data_model/[data model,target=_blank] with time series data identified by metric name and key/value pairs
* https://prometheus.io/docs/prometheus/latest/querying/basics/[PromQL,target=_blank], a flexible query language to leverage this dimensionality
* a multi-dimensional https://prometheus.io/docs/concepts/data_model/[data model,window=_blank] with time series data identified by metric name and key/value pairs
* https://prometheus.io/docs/prometheus/latest/querying/basics/[PromQL,window=_blank], a flexible query language to leverage this dimensionality
* time series collection happens via a pull model over HTTP
To install it, first create a Kubernetes ConfigMap that will hold the Prometheus configuration. In the Terminal, run the following:
@@ -228,7 +228,7 @@ Of course Quarkus apps use very little memory, even for apps stuffed with all so
== Visualizing with Grafana
https://grafana.com/[Grafana,target=_blank] is commonly used to visualize metrics and provides a flexible, graphical frontend which has support for Prometheus (and many other data sources) and can display https://prometheus.io/docs/visualization/grafana/[customized, realtime dashboards,target=_blank]:
https://grafana.com/[Grafana,window=_blank] is commonly used to visualize metrics and provides a flexible, graphical frontend which has support for Prometheus (and many other data sources) and can display https://prometheus.io/docs/visualization/grafana/[customized, realtime dashboards,window=_blank]:
image::https://grafana.com/api/dashboards/3308/images/2099/image[Grafana dashboard,800]
@@ -349,6 +349,6 @@ Go to the first Terminal tab and press kbd:[CTRL+C] to stop our locally running
== Congratulations!
This exercise demonstrates how your Quarkus application can utilize the https://github.com/eclipse/microprofile-metrics[MicroProfile Metrics,target=_blank] specification through the SmallRye Metrics extension. You also consumed these metrics using a popular monitoring stack with Prometheus and Grafana.
This exercise demonstrates how your Quarkus application can utilize the https://github.com/eclipse/microprofile-metrics[MicroProfile Metrics,window=_blank] specification through the SmallRye Metrics extension. You also consumed these metrics using a popular monitoring stack with Prometheus and Grafana.
There are many more possibilities for application metrics, and it's a useful way to not only gather metrics, but act on them through alerting and other features of the monitoring stack you may be using.

View File

@@ -1,7 +1,7 @@
= Building Native Images
:experimental:
Lets now produce a native executable for our application. It improves the startup time of the application, and produces a minimal disk and memory footprint. The executable would have everything to run the application including the "JVM" (shrunk to be just enough to run the application), and the application. This is accomplished using https://graalvm.org[GraalVM,target=_blank].
Lets now produce a native executable for our application. It improves the startup time of the application, and produces a minimal disk and memory footprint. The executable would have everything to run the application including the "JVM" (shrunk to be just enough to run the application), and the application. This is accomplished using https://graalvm.org[GraalVM,window=_blank].
GraalVM is a universal virtual machine for compiling and running applications written in JavaScript, Python, Ruby, R, JVM-based languages like Java, Scala, Groovy, Kotlin, Clojure, and LLVM-based languages such as C and C++. It includes ahead-of-time compilation, aggressive dead code elimination, and optimal packaging as native binaries that moves a lot of startup logic to _build-time_, thereby reducing startup time and memory resource requirements significantly.
@@ -96,7 +96,7 @@ You should see something like:
```
----
This shows that our process is taking around 13.8 MB of memory (https://en.wikipedia.org/wiki/Resident_set_size[Resident Set Size,target=_blank], or RSS). Pretty compact!
This shows that our process is taking around 13.8 MB of memory (https://en.wikipedia.org/wiki/Resident_set_size[Resident Set Size,window=_blank], or RSS). Pretty compact!
[NOTE]
====

View File

@@ -7,7 +7,7 @@ This guide explains how your Quarkus application can expose its API description
An OpenAPI definition can then be used by documentation generation tools to display the API, code generation tools to generate servers and clients in various programming languages, testing tools, and many other use cases.
Quarkus implements the https://github.com/eclipse/microprofile-open-api/[MicroProfile Open API Specification,target=_blank] and as such exposes several developer APIs for documenting your application's APIs.
Quarkus implements the https://github.com/eclipse/microprofile-open-api/[MicroProfile Open API Specification,window=_blank] and as such exposes several developer APIs for documenting your application's APIs.
The MicroProfile OpenAPI specification requires vendors to produce a valid OpenAPI document from pure JAX-RS 2.0 applications, without the developer adding any special annotations for OpenAPI. This means that vendors must process all the relevant JAX-RS annotations (such as `@Path` and `@Consumes`) as well as Java objects (POJOs) used as input or output to JAX-RS operations.
@@ -128,11 +128,11 @@ OpenAPI and Swagger are useful tools but they become even more useful to 3rd par
You as an application developer have a few choices in documenting your APIs:
. Augment your JAX-RS annotations with the OpenAPI https://github.com/eclipse/microprofile-open-api/blob/master/spec/src/main/asciidoc/microprofile-openapi-spec.adoc#annotations[Annotations,target=_blank]. Using annotations means you dont have to re-write the portions of the OpenAPI document that are already covered by the JAX-RS framework (e.g. the HTTP method of an operation).
. Take the initial output from `/openapi` as a starting point to document your APIs via https://github.com/eclipse/microprofile-open-api/blob/master/spec/src/main/asciidoc/microprofile-openapi-spec.adoc#static-openapi-files[Static OpenAPI files,target=_blank] (and then check those into source code repositories and update when APIs change). Its worth mentioning that these static files can also be written before any code, which is an approach often adopted by enterprises that want to lock-in the contract of the API. In this case, we refer to the OpenAPI document as the "source of truth", by which the client and provider must abide.
. Use the https://github.com/eclipse/microprofile-open-api/blob/master/spec/src/main/asciidoc/microprofile-openapi-spec.adoc#programming-model[Programming model,target=_blank] to provide a bootstrap (or complete) OpenAPI model tree.
. Augment your JAX-RS annotations with the OpenAPI https://github.com/eclipse/microprofile-open-api/blob/master/spec/src/main/asciidoc/microprofile-openapi-spec.adoc#annotations[Annotations,window=_blank]. Using annotations means you dont have to re-write the portions of the OpenAPI document that are already covered by the JAX-RS framework (e.g. the HTTP method of an operation).
. Take the initial output from `/openapi` as a starting point to document your APIs via https://github.com/eclipse/microprofile-open-api/blob/master/spec/src/main/asciidoc/microprofile-openapi-spec.adoc#static-openapi-files[Static OpenAPI files,window=_blank] (and then check those into source code repositories and update when APIs change). Its worth mentioning that these static files can also be written before any code, which is an approach often adopted by enterprises that want to lock-in the contract of the API. In this case, we refer to the OpenAPI document as the "source of truth", by which the client and provider must abide.
. Use the https://github.com/eclipse/microprofile-open-api/blob/master/spec/src/main/asciidoc/microprofile-openapi-spec.adoc#programming-model[Programming model,window=_blank] to provide a bootstrap (or complete) OpenAPI model tree.
Additionally, a https://github.com/eclipse/microprofile-open-api/blob/master/spec/src/main/asciidoc/microprofile-openapi-spec.adoc#filter[Filter,target=_blank] is described which can update the OpenAPI model after it has been built from the previously described documentation mechanisms.
Additionally, a https://github.com/eclipse/microprofile-open-api/blob/master/spec/src/main/asciidoc/microprofile-openapi-spec.adoc#filter[Filter,window=_blank] is described which can update the OpenAPI model after it has been built from the previously described documentation mechanisms.
So let's add a bit more documentation to our `/person/birth/before/{year}` endpoint using the first option (annotations). Open the `PersonResource` class, and find the `getBeforeYear` method -- this method implements our endpoint.

View File

@@ -42,7 +42,7 @@ This causes the `%dev` properties (using H2 database) to be active in developmen
[NOTE]
====
These names are known to Quarkus, and you can introduce your own profiles and use them in a similar way for other environments (and can be overridden at runtime). You can read more about externalized config in the https://quarkus.io/guides/application-configuration-guide[Quarkus Application Configuration Guide,target=_blank].
These names are known to Quarkus, and you can introduce your own profiles and use them in a similar way for other environments (and can be overridden at runtime). You can read more about externalized config in the https://quarkus.io/guides/application-configuration-guide[Quarkus Application Configuration Guide,window=_blank].
====
== Create Entity
@@ -350,11 +350,11 @@ In the previous step you added a few more custom queries to your entity and the
Earlier we used `curl` to access our data, which is very useful for testing, but for real applications you will usually surface the data in other ways, like on web pages using tables, with options for searching, sorting, filtering, paging, etc. Quarkus and Panache make this easy to adapt your application for any display library or framework.
Let's use a popular jQuery-based plugin called https://www.datatables.net[DataTables,target=_blank]. It features a *server-side* processing mode where it depends on the server (in this case our Quarkus app) to do searching, filtering, sorting, and paging. This is useful for very large datasets, on the order of hundreds of thousands of records or more. Transmitting the entire data set to the client browser is ineffecient at best, and will crash browsers, increase networking usage, and frustrate users at worst. So let's just return the exact data needed to be shown.
Let's use a popular jQuery-based plugin called https://www.datatables.net[DataTables,window=_blank]. It features a *server-side* processing mode where it depends on the server (in this case our Quarkus app) to do searching, filtering, sorting, and paging. This is useful for very large datasets, on the order of hundreds of thousands of records or more. Transmitting the entire data set to the client browser is ineffecient at best, and will crash browsers, increase networking usage, and frustrate users at worst. So let's just return the exact data needed to be shown.
=== Add Datatables endpoint
https://www.datatables.net/manual/server-side[DataTables documentation,target=_blank] shows that its frontend will call an endpoint on the backend to retrieve some amount of data. It will pass several query parameters to tell the server what to sort, filter, search, and which data to return based on the page size and current page the user is viewing. For this example, we'll only support a subset:
https://www.datatables.net/manual/server-side[DataTables documentation,window=_blank] shows that its frontend will call an endpoint on the backend to retrieve some amount of data. It will pass several query parameters to tell the server what to sort, filter, search, and which data to return based on the page size and current page the user is viewing. For this example, we'll only support a subset:
* `start` - The index of the first element needed
* `length` - Total number records to return (or less, if there are less records that meet criteria)

View File

@@ -1,7 +1,7 @@
= Securing Quarkus APIs
:experimental:
Bearer Token Authorization is the process of authorizing HTTP requests based on the existence and validity of a bearer token representing a subject and her access context, where the token provides valuable information to determine the subject of the call as well whether or not a HTTP resource can be accessed. This is commonly used in OAuth-based identity and access management systems like https://keycloak.org[Keycloak,target=_blank], a popular open source project. In this exercise we'll show you how to use https://github.com/eclipse/microprofile-jwt-auth/releases/download/1.1.1/microprofile-jwt-auth-spec.pdf[Microprofile JSON Web Token (JWT) RBAC,target=_blank], https://keyloak.org[Keycloak,target=_blank] and https://en.wikipedia.org/wiki/OAuth[OAuth,target=_blank] to secure your Quarkus applications.
Bearer Token Authorization is the process of authorizing HTTP requests based on the existence and validity of a bearer token representing a subject and her access context, where the token provides valuable information to determine the subject of the call as well whether or not a HTTP resource can be accessed. This is commonly used in OAuth-based identity and access management systems like https://keycloak.org[Keycloak,window=_blank], a popular open source project. In this exercise we'll show you how to use https://github.com/eclipse/microprofile-jwt-auth/releases/download/1.1.1/microprofile-jwt-auth-spec.pdf[Microprofile JSON Web Token (JWT) RBAC,window=_blank], https://keyloak.org[Keycloak,window=_blank] and https://en.wikipedia.org/wiki/OAuth[OAuth,window=_blank] to secure your Quarkus applications.
== Add JWT to Quarkus
@@ -219,7 +219,7 @@ Alice is not an admin. Let's try with admin!
[WARNING]
====
Access Tokens have a defined lifespan that's typically short (e.g. 5 minutes), so if you wait too long, the token will expire and you'll get denied access. In this case, just re-fetch a new token using the same `curl` command used the first time. Full-fledged applications can take advantage of things like https://oauth.net/2/grant-types/refresh-token/[_Refresh Tokens_,target=_blank] to do this automatically to ensure a good user experience even for slow users.
Access Tokens have a defined lifespan that's typically short (e.g. 5 minutes), so if you wait too long, the token will expire and you'll get denied access. In this case, just re-fetch a new token using the same `curl` command used the first time. Full-fledged applications can take advantage of things like https://oauth.net/2/grant-types/refresh-token/[_Refresh Tokens_,window=_blank] to do this automatically to ensure a good user experience even for slow users.
====
=== Test Admin
@@ -300,7 +300,7 @@ quarkus.keycloak.policy-enforcer.enable=true
quarkus.keycloak.policy-enforcer.enforcement-mode=PERMISSIVE
----
This configures the extension with the necessary configuration ( https://www.keycloak.org/docs/latest/securing_apps/index.html#_java_adapter_config[read more,target=_blank] about what these do).
This configures the extension with the necessary configuration ( https://www.keycloak.org/docs/latest/securing_apps/index.html#_java_adapter_config[read more,window=_blank] about what these do).
=== Create Keycloak endpoints
@@ -368,7 +368,7 @@ The `/secured/confidential` endpoint is protected with a policy defined in the K
[NOTE]
====
Keycloak caches the resource paths that it is protecting, so that every access doesn't cause a roundtrip back to the server to check whether the user is authorized to access the resource. The lifespan of these cached entries can be controlled through https://www.keycloak.org/docs/latest/authorization_services/index.html#_enforcer_filter[Policy Enforcer Configuration,target=_blank].
Keycloak caches the resource paths that it is protecting, so that every access doesn't cause a roundtrip back to the server to check whether the user is authorized to access the resource. The lifespan of these cached entries can be controlled through https://www.keycloak.org/docs/latest/authorization_services/index.html#_enforcer_filter[Policy Enforcer Configuration,window=_blank].
====
First make sure even `admin` can't access the endpoint:

View File

@@ -278,6 +278,6 @@ This confirms that our `MockGreetingService` is being used instead of the origin
== Congratulations!
In this section we covered basic testing of Quarkus Apps using the `@QuarkusTest` and supporting annotations. This is an important part of any software engineering project and with Quarkus, testing has never been easier. For more information on testing with Quarkus, be sure to review the https://quarkus.io/guides/getting-started-testing[Quarkus Testing Guide,target=_blank].
In this section we covered basic testing of Quarkus Apps using the `@QuarkusTest` and supporting annotations. This is an important part of any software engineering project and with Quarkus, testing has never been easier. For more information on testing with Quarkus, be sure to review the https://quarkus.io/guides/getting-started-testing[Quarkus Testing Guide,window=_blank].
In the next section we'll talk about how to effectively debug Quarkus applications. On with the show!

View File

@@ -1,13 +1,13 @@
= Tracing with MicroProfile OpenTracing
:experimental:
This exercise shows how your Quarkus application can utilize https://github.com/eclipse/microprofile-opentracing/blob/master/spec/src/main/asciidoc/microprofile-opentracing.asciidoc[Eclipse MicroProfile OpenTracing,target=_blank] to provide distributed tracing for interactive web applications.
This exercise shows how your Quarkus application can utilize https://github.com/eclipse/microprofile-opentracing/blob/master/spec/src/main/asciidoc/microprofile-opentracing.asciidoc[Eclipse MicroProfile OpenTracing,window=_blank] to provide distributed tracing for interactive web applications.
In a distributed cloud-native application, multiple microservices are collaborating to deliver the expected functionality. If you have hundreds of services, how do you debug an individual request as it travels through a distributed system? For Java enterprise developers, the Eclipse MicroProfile OpenTracing specification makes it easier. Let's find out how.
== Install Jaeger
https://www.jaegertracing.io/[Jaeger,target=_blank], inspired by Dapper and OpenZipkin, is a distributed tracing system released as open source by Uber Technologies. It is used for monitoring and troubleshooting microservices-based distributed systems, including:
https://www.jaegertracing.io/[Jaeger,window=_blank], inspired by Dapper and OpenZipkin, is a distributed tracing system released as open source by Uber Technologies. It is used for monitoring and troubleshooting microservices-based distributed systems, including:
* Distributed context propagation
* Distributed transaction monitoring
@@ -58,7 +58,7 @@ quarkus.jaeger.sampler-param=1 # <2>
quarkus.jaeger.endpoint=http://jaeger-collector:14268/api/traces # <3>
----
<1> The name of our service from the perspective of Jaeger (useful when multiple apps report to the same Jaeger instance)
<2> How Jaeger samples traces. https://www.jaegertracing.io/docs/1.7/sampling/#client-sampling-configuration[Other options exist,target=_blank] to tune the performance.
<2> How Jaeger samples traces. https://www.jaegertracing.io/docs/1.7/sampling/#client-sampling-configuration[Other options exist,window=_blank] to tune the performance.
<3> This is the default HTTP-based collector exposed by Jaeger
== Test it out
@@ -119,14 +119,14 @@ You can see that this trace (along with the others) shows the incoming HTTP GET
[NOTE]
====
Service Mesh technologies like https://istio.io[Istio,target=_blank] can provide even more tracing prowess as the calls across different services are traced at the network level, not requiring _any_ frameworks or developer instrumentation to be enabled for tracing.
Service Mesh technologies like https://istio.io[Istio,window=_blank] can provide even more tracing prowess as the calls across different services are traced at the network level, not requiring _any_ frameworks or developer instrumentation to be enabled for tracing.
====
== Tracing external calls
This exercise showa how to use the https://github.com/eclipse/microprofile-rest-client[MicroProfile REST Client,target=_blank] with Quarkus in order to trace _external_, outbound requests with very little effort.
This exercise showa how to use the https://github.com/eclipse/microprofile-rest-client[MicroProfile REST Client,window=_blank] with Quarkus in order to trace _external_, outbound requests with very little effort.
We will use the publicly available https://swapi.co[Star Wars API,target=_blank] to fetch some characters from the Star Wars universe. Our first order of business is to setup the model we will be using, in the form of a StarWarsPerson POJO.
We will use the publicly available https://swapi.co[Star Wars API,window=_blank] to fetch some characters from the Star Wars universe. Our first order of business is to setup the model we will be using, in the form of a StarWarsPerson POJO.
=== Create model
@@ -163,7 +163,7 @@ This contains a subset of the full Star Wars model, just enough to demonstrate t
=== Create interface
Using the https://github.com/eclipse/microprofile-rest-client[MicroProfile REST Client,target=_blank] is as simple as creating an interface using the proper JAX-RS and MicroProfile annotations. Create a new Java class in the `org.acme.people.service` package called `StarWarsService` with the following content:
Using the https://github.com/eclipse/microprofile-rest-client[MicroProfile REST Client,window=_blank] is as simple as creating an interface using the proper JAX-RS and MicroProfile annotations. Create a new Java class in the `org.acme.people.service` package called `StarWarsService` with the following content:
[source,java,role="copypaste"]
----