update to quarkus 1.0.0.CR1 and improve instructions (#4)

This commit is contained in:
James Falkner
2019-11-07 16:41:05 -06:00
committed by GitHub
parent 46013a74e7
commit 4c08324e61
31 changed files with 147 additions and 118 deletions

View File

@@ -1,6 +1,6 @@
---
id: quarkus-lab
name: Quarkus Hands-on Lab
name: Quarkus Hands-on Lab (Lab Version 2019-11-07)
vars:
ROUTE_SUBDOMAIN:

View File

@@ -90,7 +90,7 @@ There are two types of probes in Quarkus apps (and Kubernetes):
Readiness and liveness probes can be used in parallel for the same container. Using both can ensure that traffic does not reach a container that is not ready for it, and that containers are restarted when they fail. There are various https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/[Configuration Paramters, window=_blank] you can set, such as the timeout period, frequency, and other parameters that can be tuned to expected application behavior.
====
THanks to Live Coding mode, simply open a Terminal window and run:
Thanks to Live Coding mode, simply open a Terminal window and run:
[source, sh, role="copypaste"]
----
@@ -443,6 +443,8 @@ Next, let's re-build the app as an executable JAR (which will run with the `prod
Build an executable JAR just as before using the command palette and choosing **Create Executable JAR**.
image:createexec.png[create,600]
Next, open a new Terminal window and run the the app:
[source,sh,role="copypaste"]

View File

@@ -17,6 +17,7 @@ Open up the `GreetingResource.java` class again, and add another RESTful endpoin
public String lastLetter(@PathParam("name") String name) {
int len = name.length();
String lastLetter = name.substring(len);
log.info("Got last letter: " + lastLetter);
return lastLetter;
}
----
@@ -28,7 +29,7 @@ A a bug has been reported where the last letter is not working. To reproduce the
curl http://localhost:8080/hello/lastletter/Foo
----
Due to the bug, nothing is returned. It should have given us back an `o`.
Due to the bug, nothing is returned. It should have given us back an `o`. You'll also see `Got last letter:` and then no letter.
You can probably spot the bug right away but let's see how you could find this with the debugger, and more importantly fix it and re-test very quickly.
@@ -50,6 +51,8 @@ image::buttons.png[buttons, 600]
To debug the app, let's step through our function that has the bug. In the left gutter of the code, where the line numbers are shown, click once on the line number next to `int len = name.length();` to set a breakpoint. The line number will be highlighted and the breakpoint will be registered in the debug pane:
> **NOTE** - your line numbers may be different depending on where you placed this code in the file.
image::break.png[breakpoint,800]
== Trigger the bug
@@ -87,7 +90,7 @@ Click **Step Over** again, which executes the line to grab the last letter using
We need to pass an offset that is one _before_ the end, to get the last letter.
Click the **Resume** button to let the method continue and return the value (your `curl` command has probably timed out by now).
Click the **Resume** button to let the method continue, log the erroneous value to the console, and return the value (your `curl` command has probably timed out by now).
== Fix the bug
@@ -105,7 +108,7 @@ With the bug fixed, re-trigger the method by running the `curl` command again in
curl http://localhost:8080/hello/lastletter/foo
----
The breakpoint will be hit once again. Step over the lines to verify the value of `lastLetter` is correct before the method returns. You've fixed the bug!
The breakpoint will be hit once again. Step over the lines to verify the value of `lastLetter` is correct and you see a proper `Got last letter: o` on the console. before the method returns. You've fixed the bug!
[WARNING]
====

View File

@@ -80,18 +80,11 @@ oc start-build people --from-file target/*-runner --follow
This step will combine the native binary with a base OS image, create a new container image, and push it to an internal image registry.
Once that's done, deploy the new image as an OpenShift application:
Once that's done, deploy the new image as an OpenShift application and expose its HTTP endpoint to the outside world:
[source,sh,role="copypaste"]
----
oc new-app people
----
and expose it to the world:
[source,sh,role="copypaste"]
----
oc expose svc/people
oc new-app people && oc expose svc/people
----
Finally, make sure it's actually done rolling out:

View File

@@ -30,40 +30,6 @@ Apache Tika quarkus-tika
Adding an extension is simiarly easy. With Maven, you can add extensions using `mvn quarkus:add-extension -Dextensions="extension1,extension2,..."`. The extension name can be the maven groupId/artifactId name of the extension: e.g. `io.quarkus:quarkus-agroal`. But you can pass a partial name and Quarkus will do its best to find the right extension. For example, `agroal`, `Agroal` or `agro` will expand to `io.quarkus:quarkus-agroal`. If no extension is found or if more than one extensions match, you will see a warning and a list of possible matches in the command result.
== Add an extension
Later on in this lab we'll be using MicroProfile metrics, so let's add that extension here. In the Terminal, run the following command to add the _MicroProfile Metrics_ extension to your project:
[source,sh,role="copypaste"]
----
mvn quarkus:add-extension -Dextensions="metrics"
----
Notice we are using the "short" name `metrics` instead of the fully qualified name `io.quarkus:quarkus-smallrye-metrics`.
The result of this command is a new `<dependency>` added to our `pom.xml` which you can see by looking at the differences using the following command:
[source,sh,role="copypaste"]
----
git --no-pager diff pom.xml
----
You will see all the changes to `pom.xml` since you started:
[source, none]
----
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-smallrye-health</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-smallrye-metrics</artifactId>
+ </dependency>
----
The `quarkus-smallrye-health` was added in a previous exercise, and shows up here as well.
When you run Quarkus applications, the list of extensions enabled are shown in the output, such as:
[source, none]
@@ -76,6 +42,34 @@ INFO [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, jdbc-
In Live Coding mode, Quarkus will monitor the state of `pom.xml` and bring in new dependencies. No need to stop and restart!
====
== Add an extension
Later on in this lab we'll be using MicroProfile metrics, so let's add that extension here. In the Terminal, run the following command to add the _MicroProfile Metrics_ extension to your project:
[source,sh,role="copypaste"]
----
mvn quarkus:add-extension -Dextensions="metrics"
----
Notice we are using the "short" name `metrics` instead of the fully qualified name `io.quarkus:quarkus-smallrye-metrics`.
The result of this command is a new `<dependency>` added to our `pom.xml` which you can see by looking at the differences you've made up till now.
Right-click on your `pom.xml` and select _Git > Compare with latest repository version_:
image::gitdiff.png[login,600]
You'll see all the changes to `pom.xml` since you started:
image::gitdiffcode.png[login,700]
You may see other apparent differences due to whitespace and/or the re-shuffling of XML elements when you ran `mvn quarkus:add-extension`.
There are many other git and GitHub operations like this one that you can perform directly in the IDE for real projects (e.g. committing, branching, merging, push/pull, log viewing, etc).
Close the _diff_ window by clicking **Close**.
== Writing your own extension
Quarkus extensions add a new developer focused behavior to the core offering, and consist of two distinct parts, buildtime augmentation and runtime container. The augmentation part is responsible for all metadata processing, such as reading annotations, XML descriptors etc. The output of this augmentation phase is recorded bytecode which is responsible for directly instantiating the relevant runtime services.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 KiB

After

Width:  |  Height:  |  Size: 215 KiB

BIN
docs/images/gitdiff.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 KiB

BIN
docs/images/gitdiffcode.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 KiB

BIN
docs/images/grafclickds.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 169 KiB

After

Width:  |  Height:  |  Size: 443 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 249 KiB

BIN
docs/images/grafrefresh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

After

Width:  |  Height:  |  Size: 301 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 145 KiB

View File

@@ -57,7 +57,7 @@ image::createkafkatopic.png[createkafka,800]
We'll need to create a topic for our application to stream to and from, so in the YAML:
* Change the _metadata > names_ value from `my-topic` to `names`.
* Change the _metadata > name_ value from `my-topic` to `names`.
* Change the vale of the `strimzi.io/cluster` label from `my-cluster` to `names-cluster`
Then click **Create**.
@@ -187,13 +187,14 @@ Finally, lets bind our stream to a JAX-RS resource. Create a new Java class i
----
package org.acme.people.stream;
import io.smallrye.reactive.messaging.annotations.Stream;
import io.smallrye.reactive.messaging.annotations.Channel;
import org.reactivestreams.Publisher;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jboss.resteasy.annotations.SseElementType;
/**
* A simple resource retrieving the in-memory "my-data-stream" and sending the items as server-sent events.
@@ -202,19 +203,21 @@ import javax.ws.rs.core.MediaType;
public class NameResource {
@Inject
@Stream("my-data-stream") Publisher<String> names; // <1>
@Channel("my-data-stream") Publisher<String> names; // <1>
@GET
@Path("/stream")
@Produces(MediaType.SERVER_SENT_EVENTS) // <2>
public Publisher<String> stream() { // <3>
@Produces(MediaType.SERVER_SENT_EVENTS)// <2>
@SseElementType("text/plain") // <3>
public Publisher<String> stream() { // <4>
return names;
}
}
----
<1> Injects the `my-data-stream` stream using the `@Stream` qualifier
<1> Injects the `my-data-stream` stream using the `@Channel` qualifier
<2> Indicates that the content is sent using _Server Sent Events_
<3> Returns the stream (Reactive Stream)
<3> Indicates that the data contained within the server sent events is of type `text/plain`
<4> Returns the stream (Reactive Stream)
[NOTE]
====
@@ -256,17 +259,17 @@ Add the following values to the `application.properties`:
[source,none,role="copypaste"]
----
# Configure the Kafka sink (we write to it)
%prod.mp.messaging.outgoing.generated-name.bootstrap.servers=names-cluster-kafka-bootstrap:9092
%prod.mp.messaging.outgoing.generated-name.bootstrap.servers=names-cluster-kafka-bootstrap:9092<1>
%prod.mp.messaging.outgoing.generated-name.connector=smallrye-kafka
%prod.mp.messaging.outgoing.generated-name.topic=names
%prod.mp.messaging.outgoing.generated-name.value.serializer=org.apache.kafka.common.serialization.StringSerializer
# Configure the Kafka source (we read from it)
%prod.mp.messaging.incoming.names.bootstrap.servers=names-cluster-kafka-bootstrap:9092
%prod.mp.messaging.incoming.names.bootstrap.servers=names-cluster-kafka-bootstrap:9092<1>
%prod.mp.messaging.incoming.names.connector=smallrye-kafka
%prod.mp.messaging.incoming.names.value.deserializer=org.apache.kafka.common.serialization.StringDeserializer
----
We have prefixed these with `%prod` to avoid our app trying to connect when in `dev` or `test` mode.
<1> The hostnames you see here will only make sense (be resolvable via DNS) when this app is run in the same Kubernetes namespace as the Kafka cluster you created earlier. So you'll see this and other config values above prefixed with `%prod` which will not try to initialize Kafka when in `dev` 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,window=_blank] section from the Kafka documentation.
@@ -301,7 +304,11 @@ If some of them are still starting, you'll need to wait for them! Run the `oc ge
== Rebuild Executable JAR
Using the command palette, select **Create Executable JAR**. You should see a bunch of log output that ends with a `SUCCESS` message.
Using the command palette, select **Create Executable JAR**.
image:createexec.png[create,600]
You should see a bunch of log output that ends with a `SUCCESS` message.
== Deploy to OpenShift

View File

@@ -89,10 +89,10 @@ With our endpoint, confirm it fails using the Terminal to execute:
[source,sh,role="copypaste"]
----
curl -X POST http://localhost:8080/person/joe
curl -i -X POST http://localhost:8080/person/joe
----
**This will fail** with an `Internal Server Error`. If you look at the Live Coding terminal, you'll also see the reason:
**This will fail** with an `500 Internal Server Error`. If you look at the Live Coding terminal, you'll also see the reason:
[source,none]
----
@@ -122,7 +122,7 @@ import io.quarkus.vertx.ConsumeEvent;
@ApplicationScoped
public class PersonService {
@ConsumeEvent("add-person")
@ConsumeEvent(value = "add-person", blocking = true) // <1>
@Transactional
public String addPerson(String name) {
LocalDate birth = LocalDate.now().plusWeeks(Math.round(Math.floor(Math.random() * 20 * 52 * -1)));
@@ -131,14 +131,15 @@ public class PersonService {
p.birth = birth;
p.eyes = color;
p.name = name;
Person.persist(p); // <1>
return p.name; // <2>
Person.persist(p); // <2>
return p.name; // <3>
}
}
----
<1> A new Person entity is created and persisted
<2> The return value of a method annotated with `@ConsumeEvent` is used as response to the incoming message.
<1> By default, the code consuming the event _must_ be non-blocking, as its called on the Vert.x event loop. Since our method will block to wait for the transaction, we use `blocking = true` to force this consumer to be run in a _worker thread_.
<2> A new Person entity is created and persisted
<3> The return value of a method annotated with `@ConsumeEvent` is used as response to the incoming message.
This bean receives the name, and creates a new `Person` entity and persists it, and then echos back the name (or a well defined failure if things go wrong).
@@ -163,10 +164,11 @@ You should get back Joe!
{
"id": 1004,
"birth": "2000-03-15",
"eyes": "BROWN",
"eyes": "BROWN",<1>
"name": "joe"
}
----
<1> The eye color you see here may be difference, since it's randomly generated in the `addPerson()` method you added!
To better understand, lets detail how the HTTP request/response has been handled:

View File

@@ -161,7 +161,11 @@ Don't forget to import the correct classes as before.
== Rebuild Executable JAR
Now we are ready to run our application on the cluster and look at the generated metrics. Using the command palette, select **Create Executable JAR**. You should see a bunch of log output that ends with a `SUCCESS` message.
Now we are ready to run our application on the cluster and look at the generated metrics. Using the command palette, select **Create Executable JAR**.
image:createexec.png[create,600]
You should see a bunch of log output that ends with a `SUCCESS` message.
== Deploy to OpenShift
@@ -206,9 +210,9 @@ If you do not see any `acme` metrics when querying, wait 15 seconds, reload the
image:prom.png[Prometheus,800]
These are the metrics exposed by our application, both raw numbers (like number of converted names in the `application:org_acme_people_stream_name_converter_converted_names` metric) along with quantiles of the same data across different time periods (e.g. `application:org_acme_people_stream_name_converter_converter_rate_per_second`).
These are the metrics exposed by our application, both raw numbers (like number of converted names in the `application_org_acme_people_stream_NameConverter_convertedNames_total` metric) along with quantiles of the same data across different time periods (e.g. `application_org_acme_people_stream_NameConverter_converter_rate_per_second`).
Select `application:org_acme_people_stream_name_converter_converted_names` in the box, and click **Execute**. This will fetch the values from our metric showing the number of converted names:
Select `application:application_org_acme_people_stream_NameConverter_convertedNames_total` in the box, and click **Execute**. This will fetch the values from our metric showing the number of converted names:
image:promnames.png[names,800]
@@ -268,7 +272,13 @@ At the password change prompt, use any password you wish.
== Add Prometheus as a data source
You'll land on the Data Source screen. Click **Add Data Source**, and select **Prometheus** as the _Data Source Type_. In the URL box, type `http://prometheus:9090` (this is the hostname and port of our running Prometheus in our namespace):
You'll land on the Home screen. Click **Add Data Source**:
image:grafclickds.png[names,600]
and then select **Prometheus** as the _Data Source Type_.
In the URL box, type `http://prometheus:9090` (this is the hostname and port of our running Prometheus in our namespace):
image::grafds.png[datasource, 700]
@@ -290,7 +300,11 @@ Click **Add Query**. In the Query box, type `acme` to again get an autocompleted
image::grafquery.png[query,600]
Choose the first one `application:org_acme_people_stream_name_converter_converted_names`. The metrics should immediately begin to show in the graph above:
Look for the one ending in `convertedNames_total` and select it. Click the **Refresh** button in the upper right:
image::grafrefresh.png[query,400]
The metrics should immediately begin to show in the graph above:
image::grafgraf.png[graf,800]
@@ -304,15 +318,15 @@ image::grafgen.png[graf,800]
There is an _Alerts_ tab you can configure to send alerts (email, etc) when conditions are met for this and other queries. We'll skip this for now.
Click the _Save_ icon at the top to save our new dashboard (you can enter a change comment if you want):
Click the _Save_ icon at the top to save our new dashboard, enter `Quarkus Metrics Dashboard` as its name (you can actually name it any name you want, it will show up in a list of dashboards later on).
image::grafsave.png[graf,800]
image::grafdashsave.png[graf,800]
Give your new dashboard a name and click **Save**.
Click **Save**.
== Add more Panels
See if you can add additional Panels. Use the **Add Panel** button to add a new Panel:
See if you can add additional Panels to your new Dashboard. Use the **Add Panel** button to add a new Panel:
image::grafmorepanels.png[graf,800]
@@ -320,7 +334,7 @@ Follow the same steps as before to create a few more panels, and **don't forget
Add Panels for:
* The different quantiles of time it takes to process names `application:org_acme_people_stream_name_converter_converter_seconds` (configure it to _stack_ its values on the _Visualization_ tab, and name it "Converter Performance" on the _General_ tab).
* The different quantiles of time it takes to process names `application_org_acme_people_stream_NameConverter_converter_seconds` (configure it to _stack_ its values on the _Visualization_ tab, and name it "Converter Performance" on the _General_ tab).
* The JVM RSS Value `process_resident_memory_bytes` (set the visualization type to `Gauge` and the Field Units to `bytes` on the _Visualization_ tab, and the title to `Memory` on the _General_ tab.
image::grafjvm.png[jvm,500]

View File

@@ -48,7 +48,7 @@ We use a profile because, you will see very soon, packaging the native image tak
Create a native executable by once again opening the command palette and choose **Build Native Quarkus App**. This will execute `mvn package -Pnative` behind the scenes. The `-Pnative` argument selects the `native` maven profile which invokes the Graal compiler.
**This will take about 3-4 minutes to finish. Wait for it!**
**This will take about 2-3 minutes to finish. Wait for it!**
[NOTE]
====
@@ -115,7 +115,7 @@ Nice!
== Cleanup
Go to the Terminal in which you ran the native app and press kbd:[CTRL+C] to stop our native app (or close the Terminal window with the `X` button next to its title).
Go to the Terminal in which you ran the native app and press kbd:[CTRL+C] to stop our native app (or close the Terminal window with the `X` button next to its title). **Be sure to leave your Live Coding Terminal open!**
== Congratulations!

View File

@@ -19,10 +19,10 @@ We need to add another extension for OpenAPI. Run the following command:
[source,sh,role="copypaste"]
----
mvn quarkus:add-extension -Dextensions="openapi,swagger"
mvn quarkus:add-extension -Dextensions="openapi"
----
This will add the necessary extension for using OpenAPI, and a graphical frontend extension called `swagger` which we'll discuss later. It also enables a new RESTful endpoint in the app accessible at `/openapi`.
This will add the necessary extension for using OpenAPI, and a graphical frontend extension called *Swagger* which we'll discuss later. It also enables a new RESTful endpoint in the app accessible at `/openapi`.
Access the new endpoint using the following command in a Terminal:

View File

@@ -553,6 +553,8 @@ In previous steps we deployed our sample application as a native binary. Now let
Re-build the application as an executable JAR using the command palette and selecting **Create Executable JAR**.
image:createexec.png[create,600]
Next, re-define the container build to use the OpenJDK image using these commands:
[source,sh,role="copypaste"]

View File

@@ -20,9 +20,9 @@ Some configuration of the extension is required. Add this to your `application.p
[source,properties,role="copypaste"]
----
mp.jwt.verify.publickey.location={{KEYCLOAK_URL}}/auth/realms/quarkus/protocol/openid-connect/certs # <1>
mp.jwt.verify.issuer={{KEYCLOAK_URL}}/auth/realms/quarkus # <2>
quarkus.smallrye-jwt.auth-mechanism=MP-JWT # <3>
mp.jwt.verify.publickey.location={{KEYCLOAK_URL}}/auth/realms/quarkus/protocol/openid-connect/certs<1>
mp.jwt.verify.issuer={{KEYCLOAK_URL}}/auth/realms/quarkus<2>
quarkus.smallrye-jwt.auth-mechanism=MP-JWT<3>
quarkus.smallrye-jwt.realm-name=quarkus
quarkus.smallrye-jwt.enabled=true
----
@@ -106,7 +106,11 @@ public class JWTResource {
== Rebuild and redeploy app
First, re-build the app using the command palette and selecting **Create Executable JAR**. Once that's done, run the following command to re-deploy:
First, re-build the app using the command palette and selecting **Create Executable JAR**.
image:createexec.png[create,600]
Once that's done, run the following command to re-deploy:
[source,sh,role="copypaste"]
----
@@ -326,36 +330,35 @@ import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.keycloak.KeycloakSecurityContext;
import io.quarkus.security.identity.SecurityIdentity;
@Path("/secured")
@Path("/secured") // <1>
public class KeycloakResource {
@Inject
KeycloakSecurityContext keycloakSecurityContext; // <1>
SecurityIdentity identity; // <2>
@GET
@Path("/confidential") // <2>
@Path("/confidential") // <1>
@Produces(MediaType.TEXT_PLAIN)
public String confidential() {
return ("confidential access for: " + keycloakSecurityContext.getToken().getPreferredUsername() +
" from issuer:" + keycloakSecurityContext.getToken().getIssuer());
return ("confidential access for: " + identity.getPrincipal().getName() +
" with attributes:" + identity.getAttributes());
}
}
----
<1> The `KeycloakSecurityContext` is an object produced by the Keycloak extension that you can use to obtain information from tokens sent to your application.
<2> Note that we do not use any `@RolesAllowed` or any other instrumentation on the endpoint to specify access policy. It looks like an ordinary endpoint.
[NOTE]
====
There are other APIs you can use if you try to auto-complete the method name using Che, e.g. `getBirthDate()` or `getPicture()`. Place the cursor just after `keycloakSecurityContext.getToken().get` and press kbd:[Ctrl+Space] to see them:
image::secapis.png[apis, 800]
====
<1> Note that we do not use any `@RolesAllowed` or any other instrumentation on the endpoint to specify access policy. It looks like an ordinary endpoint. Keycloak (the server) is the one enforcing access here, not Quarkus directly.
<2> The `SecurityIdentity` is a generic object produced by the Keycloak extension that you can use to obtain information about the security principals and attributes embedded in the request.
=== Rebuild and redeploy app
First, re-build the app using the command palette and selecting **Create Executable JAR**. Once that's done, run the following command to re-deploy:
First, re-build the app using the command palette and selecting **Create Executable JAR**.
image:createexec.png[create,600]
Once that's done, run the following command to re-deploy:
[source,sh,role="copypaste"]
----

View File

@@ -52,10 +52,10 @@ Next, open the `application.properties` file (in the `src/main/resources` direct
[source,none,role="copypaste"]
----
quarkus.jaeger.service-name=people # <1>
quarkus.jaeger.sampler-type=const # <2>
quarkus.jaeger.sampler-param=1 # <2>
quarkus.jaeger.endpoint=http://jaeger-collector:14268/api/traces # <3>
quarkus.jaeger.service-name=people<1>
quarkus.jaeger.sampler-type=const<2>
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,window=_blank] to tune the performance.
@@ -65,7 +65,11 @@ quarkus.jaeger.endpoint=http://jaeger-collector:14268/api/traces # <3>
Like many other Quarkus frameworks, sensible defaults and out of the box functionality means you can get immediate value out of Quarkus without changing any code. By default, all JAX-RS endpoints (like our `/hello` and others) are automatically traced. Let's see that in action by re-deploying our traced app.
First, re-build the app using the command palette and selecting **Create Executable JAR**. Once that's done, run the following command to re-deploy:
First, re-build the app using the command palette and selecting **Create Executable JAR**.
image:createexec.png[create,600]
Once that's done, run the following command to re-deploy:
[source,sh,role="copypaste"]
----
@@ -258,11 +262,15 @@ public List<StarWarsPerson> getCharacters() {
<3> For each of the integers, call the `StarWarsService::getPerson` method
<4> Collect the results into a list and return it
Don't forget to _Assistant > Organize Imports_ to import the new classes.
**Don't forget to _Assistant > Organize Imports_ **to import the new classes.
== Test it out
First, re-build the app using the command palette and selecting **Create Executable JAR**. Once that's done, run the following command to re-deploy:
First, re-build the app using the command palette and selecting **Create Executable JAR**.
image:createexec.png[create,600]
Once that's done, run the following command to re-deploy:
[source,sh,role="copypaste"]
----

View File

@@ -4,8 +4,8 @@
"notBefore" : 0,
"revokeRefreshToken" : false,
"refreshTokenMaxReuse" : 0,
"accessTokenLifespan" : 300,
"accessTokenLifespanForImplicitFlow" : 900,
"accessTokenLifespan" : 3000,
"accessTokenLifespanForImplicitFlow" : 9000,
"ssoSessionIdleTimeout" : 1800,
"ssoSessionMaxLifespan" : 36000,
"ssoSessionIdleTimeoutRememberMe" : 0,

View File

@@ -13,5 +13,5 @@ spec:
version: "1.0"
from:
kind: DockerImage
name: docker.io/schtool/che-quarkus-workshop:0.27.0
name: docker.io/schtool/che-quarkus-workshop:1.0.0.CR1
name: "1.0"

View File

@@ -356,4 +356,4 @@ EOF
#
# then:
# DOCKER_BUILDKIT=1 docker build --progress=plain --secret id=rhsm,src=rhsm.secret -t docker.io/username/che-quarkus-workshop:latest -f stack.Dockerfile .
# docker push docker.io/username/che-quarkus-workshop:0.27.0
# docker push docker.io/username/che-quarkus-workshop:1.0.0.CR1

View File

@@ -7,6 +7,7 @@ USER root
RUN wget -O /tmp/oc.tar.gz https://mirror.openshift.com/pub/openshift-v4/clients/oc/4.1/linux/oc.tar.gz && cd /usr/bin && tar -xvzf /tmp/oc.tar.gz && chmod a+x /usr/bin/oc && rm -f /tmp/oc.tar.gz
ENV GRAALVM_VERSION=19.2.1
ENV QUARKUS_VERSION=1.0.0.CR1
ENV MVN_VERSION=3.6.2
ENV GRAALVM_HOME="/usr/local/graalvm-ce-${GRAALVM_VERSION}"
ENV MAVEN_OPTS="-Xmx4G -Xss128M -XX:MetaspaceSize=1G -XX:MaxMetaspaceSize=2G -XX:+CMSClassUnloadingEnabled"
@@ -20,9 +21,9 @@ RUN --mount=type=secret,id=rhsm username="$(grep RH_USERNAME /run/secrets/rhsm|c
USER jboss
RUN cd /tmp && mkdir project && cd project && mvn io.quarkus:quarkus-maven-plugin:0.27.0:create -DprojectGroupId=org.acme -DprojectArtifactId=footest -Dextensions="quarkus-agroal,quarkus-arc,quarkus-hibernate-orm,quarkus-hibernate-orm-panache,quarkus-jdbc-h2,quarkus-jdbc-postgresql,quarkus-kubernetes,quarkus-scheduler,quarkus-smallrye-fault-tolerance,quarkus-smallrye-health,quarkus-smallrye-opentracing" && mvn -f footest clean compile package && cd / && rm -rf /tmp/project
RUN cd /tmp && mkdir project && cd project && mvn io.quarkus:quarkus-maven-plugin:${QUARKUS_VERSION}:create -DprojectGroupId=org.acme -DprojectArtifactId=footest -Dextensions="quarkus-agroal,quarkus-arc,quarkus-hibernate-orm,quarkus-hibernate-orm-panache,quarkus-jdbc-h2,quarkus-jdbc-postgresql,quarkus-kubernetes,quarkus-scheduler,quarkus-smallrye-fault-tolerance,quarkus-smallrye-health,quarkus-smallrye-opentracing" && mvn -f footest clean compile package && cd / && rm -rf /tmp/project
RUN cd /tmp && mkdir project && cd project && mvn io.quarkus:quarkus-maven-plugin:0.27.0:create -DprojectGroupId=org.acme -DprojectArtifactId=footest -Dextensions="quarkus-smallrye-reactive-streams-operators,quarkus-smallrye-reactive-messaging,quarkus-smallrye-reactive-messaging-kafka,quarkus-swagger-ui,quarkus-vertx,quarkus-kafka-client, quarkus-smallrye-metrics,quarkus-smallrye-openapi" && mvn -f footest clean compile package -Pnative && cd / && rm -rf /tmp/project
RUN cd /tmp && mkdir project && cd project && mvn io.quarkus:quarkus-maven-plugin:${QUARKUS_VERSION}:create -DprojectGroupId=org.acme -DprojectArtifactId=footest -Dextensions="quarkus-smallrye-reactive-streams-operators,quarkus-smallrye-reactive-messaging,quarkus-smallrye-reactive-messaging-kafka,quarkus-swagger-ui,quarkus-vertx,quarkus-kafka-client, quarkus-smallrye-metrics,quarkus-smallrye-openapi" && mvn -f footest clean compile package -Pnative && cd / && rm -rf /tmp/project
RUN siege && sed -i 's/^connection = close/connection = keep-alive/' $HOME/.siege/siege.conf && sed -i 's/^benchmark = false/benchmark = true/' $HOME/.siege/siege.conf