Skip to content

Commit

Permalink
Merge pull request #32151 from cescoffier/devui-toggle-v2
Browse files Browse the repository at this point in the history
Dev UI Toggle
  • Loading branch information
gsmet authored Apr 4, 2023
2 parents 69acaaf + c20b4bb commit 3864a58
Show file tree
Hide file tree
Showing 61 changed files with 153 additions and 116 deletions.
2 changes: 1 addition & 1 deletion TROUBLESHOOTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ You can also configure the `jvm.args` system property directly inside the `quark
When trying to debug startup performance, it is convenient to log build steps execution time.
This can be achieved by adding the following system property: `-Dquarkus.debug.print-startup-times=true` in dev mode or when launching the JAR.

There is also a nice visualization of build steps available in the Dev UI located here: http://localhost:8080/q/dev/io.quarkus.quarkus-vertx-http/build-steps.
There is also a nice visualization of build steps available in the Dev UI located here: http://localhost:8080/q/dev/build-steps.

If you want to have the same visualization of build steps processing when building your application, you can use the `quarkus.debug.dump-build-metrics=true` property.
For example using `mvn package -Dquarkus.debug.dump-build-metrics=true`, will generate a `build-metrics.json` in your `target` repository that you can process via the quarkus-build-report application available here https://github.com/mkouba/quarkus-build-report.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{#include index-entry}
{#body}<br />&rsaquo; It can be tested in the <a href="/q/dev/io.quarkus.quarkus-grpc/services">Dev UI</a> (available in dev mode only).
{#body}<br />&rsaquo; It can be tested in the <a href="/q/dev-v1/io.quarkus.quarkus-grpc/services">Dev UI</a> (available in dev mode only).
{/include}
9 changes: 8 additions & 1 deletion docs/src/main/asciidoc/dev-mode-differences.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ This mightily important feature needs no introduction and has already been menti

=== Dev UI

Quarkus provides a very useful xref:dev-ui.adoc[UI] accessible from the browser at `/q/dev`. This UI allows a developer to see the state of the application, but
Quarkus provides a very useful xref:dev-ui.adoc[UI] accessible from the browser at `/q/dev-ui`. This UI allows a developer to see the state of the application, but
also provides access to various actions that can change that state (depending on the extensions that are present).
Examples of such operations are:

Expand All @@ -45,6 +45,13 @@ Examples of such operations are:
* Running scheduled operations
* Building a container

[TIP]
====
A new Dev UI has been implemented in Quarkus 3.x.
Not all the features are available yet.
You can still access the previous version of the Dev UI using: http://localhost:8080/q/dev-v1/.
====

=== Error pages

In an effort to make development errors very easy to diagnose, Quarkus provides various detailed error pages when running in dev mode.
Expand Down
15 changes: 11 additions & 4 deletions docs/src/main/asciidoc/dev-ui.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,19 @@ https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
= Dev UI
include::_attributes.adoc[]
:categories: writing-extensions
:summary: Learn how to get your extension contribute features to the Dev UI.
:summary: Learn how to get your extension contribute features to the Dev UI (v1).

[IMPORTANT]
.Dev UI v1
====
This guide covers the Dev UI v1, which has been replaced in Quarkus 3.
You can still access the Dev UI v1 using http://localhost/q/dev-v1/
====

This guide covers the Quarkus Dev UI for xref:building-my-first-extension.adoc[extension authors].

Quarkus now ships with a new experimental Dev UI, which is available in dev mode (when you start
quarkus with `mvn quarkus:dev`) at http://localhost:8080/q/dev[/q/dev] by default. It will show you something like
Quarkus ships with a new experimental Dev UI, which is available in dev mode (when you start
quarkus with `mvn quarkus:dev`) at http://localhost:8080/q/dev-v1[/q/dev-v1] by default. It will show you something like
this:

image::dev-ui-overview.png[alt=Dev UI overview,role="center",width=90%]
Expand Down Expand Up @@ -191,7 +198,7 @@ xref:building-my-first-extension.adoc#description-of-a-quarkus-extension[`deploy

Full-page templates for extensions live under a pre-defined `{devRootAppend}/{groupId}.{artifactId}/` directory
that is referenced using the `urlbase` template parameter. Using configuration defaults, that would resolve to
`/q/dev/io.quarkus.quarkus-cache/`, as an example.
`/q/dev-v1/io.quarkus.quarkus-cache/`, as an example.

Use the `{urlbase}` template parameter to reference this folder in `embedded.html`:

Expand Down
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/grpc-service-implementation.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ public class HelloServiceTest implements Greeter {

== Trying out your services manually
In the dev mode, you can try out your gRPC services in the Quarkus Dev UI.
Just go to http://localhost:8080/q/dev and click on _Services_ under the gRPC tile.
Just go to http://localhost:8080/q/dev-v1 and click on _Services_ under the gRPC tile.

Please note that your application needs to expose the "normal" HTTP port for the Dev UI to be accessible. If your application does not expose any HTTP endpoints, you can create a dedicated profile with a dependency on `quarkus-vertx-http`:
[source,xml]
Expand Down
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/resteasy-reactive-migration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Users are instead encouraged to use the Jakarta REST standard `jakarta.ws.rs.Bea

Although RESTEasy Reactive provides the same spec compliant behavior as RESTEasy Classic does, it does not include the same exact provider implementations at runtime.

The most common case where the difference in providers might result in different behavior, is the included `jakarta.ws.rs.ext.ExceptionMapper` implementations. To see what classes are included in the application, launch the application in dev mode and navigate to http://localhost:8080/q/dev/io.quarkus.quarkus-resteasy-reactive/exception-mappers.
The most common case where the difference in providers might result in different behavior, is the included `jakarta.ws.rs.ext.ExceptionMapper` implementations. To see what classes are included in the application, launch the application in dev mode and navigate to http://localhost:8080/q/dev-ui/io.quarkus.quarkus-resteasy-reactive/exception-mappers.

==== Service Loading

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ include::{includes}/devtools/dev.adoc[]
xref:security-openid-connect-dev-services.adoc[Dev Services for Keycloak] will launch a Keycloak container and import a `quarkus-realm.json`.
Open a xref:dev-ui.adoc[Dev UI] available at http://localhost:8080/q/dev[/q/dev] and click on a `Provider: Keycloak` link in an `OpenID Connect` `Dev UI` card.
Open a xref:dev-ui.adoc[Dev UI] available at http://localhost:8080/q/dev-v1[/q/dev-v1] and click on a `Provider: Keycloak` link in an `OpenID Connect` `Dev UI` card.
You will be asked to log in into a `Single Page Application` provided by `OpenID Connect Dev UI`:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ include::{includes}/devtools/dev.adoc[]

xref:security-openid-connect-dev-services.adoc[Dev Services for Keycloak] will launch a Keycloak container and import a `quarkus-realm.json`.

Open a xref:dev-ui.adoc[Dev UI] available at http://localhost:8080/q/dev[/q/dev] and click on a `Provider: Keycloak` link in an `OpenID Connect` `Dev UI` card.
Open a xref:dev-ui.adoc[Dev UI] available at http://localhost:8080/q/dev-v1[/q/dev-v1] and click on a `Provider: Keycloak` link in an `OpenID Connect` `Dev UI` card.

You will be asked to log in into a `Single Page Application` provided by `OpenID Connect Dev UI`:

Expand Down
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/security-openid-connect-client.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ include::{includes}/devtools/dev.adoc[]

xref:security-openid-connect-dev-services.adoc[Dev Services for Keycloak] will launch a Keycloak container and import a `quarkus-realm.json`.

Open a xref:dev-ui.adoc[Dev UI] available at http://localhost:8080/q/dev[/q/dev] and click on a `Provider: Keycloak` link in an `OpenID Connect` `Dev UI` card.
Open a xref:dev-ui.adoc[Dev UI] available at http://localhost:8080/q/dev-v1[/q/dev-v1] and click on a `Provider: Keycloak` link in an `OpenID Connect` `Dev UI` card.

You will be asked to log in into a `Single Page Application` provided by `OpenID Connect Dev UI`:

Expand Down
12 changes: 6 additions & 6 deletions docs/src/main/asciidoc/security-openid-connect-dev-services.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ It also describes Dev UI for all OpenID Connect providers which have already bee
Quarkus introduces an experimental `Dev Services For Keycloak` feature which is enabled by default when the `quarkus-oidc` extension is started in dev mode and when the integration tests are running in test mode, but only when no `quarkus.oidc.auth-server-url` property is configured.
It starts a Keycloak container for both the dev and/or test modes and initializes them by registering the existing Keycloak realm or creating a new realm with the client and users for you to start developing your Quarkus application secured by Keycloak immediately. It will restart the container when the `application.properties` or the realm file changes have been detected.

Additionally, xref:dev-ui.adoc[Dev UI] available at http://localhost:8080/q/dev[/q/dev] complements this feature with a Dev UI page which helps to acquire the tokens from Keycloak and test your Quarkus application.
Additionally, xref:dev-ui.adoc[Dev UI] available at http://localhost:8080/q/dev-v1[/q/dev-v1] complements this feature with a Dev UI page which helps to acquire the tokens from Keycloak and test your Quarkus application.

If `quarkus.oidc.auth-server-url` is already set then a generic OpenID Connect Dev Console which can be used with all OpenID Connect providers will be activated, please see <<dev-ui-all-oidc-providers,Dev UI for all OpenID Connect Providers>> for more information.

Expand Down Expand Up @@ -53,7 +53,7 @@ include::{includes}/devtools/dev.adoc[]

Note that you can disable sharing the containers with `quarkus.keycloak.devservices.shared=false`.

Now open the main link:http://localhost:8080/q/dev[Dev UI page], and you will see the `OpenID Connect Card` linking to a Keycloak page:
Now open the main link:http://localhost:8080/q/dev-v1[Dev UI (v1) page], and you will see the `OpenID Connect Card` linking to a Keycloak page:

image::dev-ui-oidc-keycloak-card.png[alt=Dev UI OpenID Connect Card,role="center"]

Expand Down Expand Up @@ -128,7 +128,7 @@ You may need to register a redirect URI for the authorization code flow initiate
If Keycloak does enforce it then you will see an authentication error informing you that the `redirect_uri` value is wrong.
In this case select the `Keycloak Admin` option in the right top corner, login as `admin:admin`, select the test realm and the client which Dev UI for Keycloak is configured with and add `http://localhost:8080/q/dev/io.quarkus.quarkus-oidc/provider` to `Valid Redirect URIs`. If you used `-Dquarkus.http.port` when starting Quarkus then change `8080` to the value of `quarkus.http.port`.
In this case select the `Keycloak Admin` option in the right top corner, login as `admin:admin`, select the test realm and the client which Dev UI for Keycloak is configured with and add `http://localhost:8080/q/dev-v1/io.quarkus.quarkus-oidc/provider` to `Valid Redirect URIs`. If you used `-Dquarkus.http.port` when starting Quarkus then change `8080` to the value of `quarkus.http.port`
If the container is shared between multiple applications running on different ports then you will need to register `redirect_uri` values for each of these applications.
Expand Down Expand Up @@ -297,13 +297,13 @@ And you will see the following message:
...
----

If the provider metadata discovery has been successful then, after you open the main link:http://localhost:8080/q/dev[Dev UI page], you will see the `OpenID Connect Card` page linking to `Dev Console`:
If the provider metadata discovery has been successful then, after you open the main link:http://localhost:8080/q/dev-v1[Dev UI page], you will see the `OpenID Connect Card` page linking to `Dev Console`:

image::dev-ui-oidc-devconsole-card.png[alt=Generic Dev UI OpenID Connect Card,role="center"]

Follow the link, and you will be able to log in to your provider, get the tokens and test the application. The experience will be the same as described in the <<keycloak-authorization-code-grant,Authorization Code Grant for Keycloak>> section, where `Dev Services for Keycloak` container has been started, especially if you work with Keycloak.

You will most likely need to configure your OpenId Connect provider to support redirecting back to the `Dev Console`. Add `http://localhost:8080/q/dev/io.quarkus.quarkus-oidc/provider` as one of the supported redirect and logout URLs.
You will most likely need to configure your OpenId Connect provider to support redirecting back to the `Dev Console`. Add `http://localhost:8080/q/dev-v1/io.quarkus.quarkus-oidc/provider` as one of the supported redirect and logout URLs. one of the supported redirect and logout URLs.

If you work with other providers then a Dev UI experience described in the <<keycloak-authorization-code-grant,Authorization Code Grant for Keycloak>> section might differ slightly. For example, an access token may not be in a JWT format, so it won't be possible to show its internal content, though all providers should return an ID Token as JWT.

Expand Down Expand Up @@ -401,7 +401,7 @@ Please follow the xref:dev-ui.adoc[Dev UI] tutorial as well as check the `extens

== Non Application Root Path Considerations

This document refers to the `http://localhost:8080/q/dev` Dev UI URL in several places where `q` is a default non application root path. If you customize `quarkus.http.root-path` and/or `quarkus.http.non-application-root-path` properties then replace `q` accordingly, please see https://quarkus.io/blog/path-resolution-in-quarkus/[Path Resolution in Quarkus] for more information.
This document refers to the `http://localhost:8080/q/dev-v1` Dev UI URL in several places where `q` is a default non application root path. If you customize `quarkus.http.root-path` and/or `quarkus.http.non-application-root-path` properties then replace `q` accordingly, please see https://quarkus.io/blog/path-resolution-in-quarkus/[Path Resolution in Quarkus] for more information.

== References

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public void testGenerateMigrationFromHibernate() {
RestAssured.get("fruit").then().statusCode(200)
.body("[0].name", CoreMatchers.is("Orange"));
RestAssured.given().redirects().follow(false).formParam("datasource", "<default>")
.post("/q/dev/io.quarkus.quarkus-flyway/create-initial-migration").then().statusCode(303);
.post("/q/dev-v1/io.quarkus.quarkus-flyway/create-initial-migration").then().statusCode(303);

config.modifySourceFile(Fruit.class, s -> s.replace("Fruit {", "Fruit {\n" +
" \n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void websocketTest() throws Exception {
List<String> incomingMessages = new CopyOnWriteArrayList<>();
HttpClient client = vertx.createHttpClient();

client.webSocket(8080, "localhost", "/q/dev/io.quarkus.quarkus-grpc/grpc-test", result -> {
client.webSocket(8080, "localhost", "/q/dev-v1/io.quarkus.quarkus-grpc/grpc-test", result -> {
if (result.failed()) {
log.error("failure making a web socket connection", result.cause());
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public void testCleanDatabase() {
RestAssured.when().get("/my-entity/add").then().body(is("MyEntity:added"));
RestAssured.when().get("/my-entity/count").then().body(is("3"));
RestAssured.with()
.redirects().follow(false).formParam("name", "<default>").post("q/dev/io.quarkus.quarkus-datasource/reset")
.redirects().follow(false).formParam("name", "<default>").post("q/dev-v1/io.quarkus.quarkus-datasource/reset")
.then()
.statusCode(303);
RestAssured.when().get("/my-entity/count").then().body(is("2"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ public void test() throws Exception {
when().get("/hello/three").then().statusCode(200);
when().get("/q/dev").then().statusCode(404);
when().get("/q/metrics").then().statusCode(404);
when().get("/dev/resources/images/favicon.ico").then().statusCode(200);
when().get("/dev/resources/css/tests.css").then().statusCode(200);
when().get("/dev-v1/resources/images/favicon.ico").then().statusCode(200);
when().get("/dev-v1/resources/css/tests.css").then().statusCode(200);
when().get("/metrics").then().statusCode(200)
.body(containsString("/goodbye/{message}"))
.body(containsString("/dev"));
Expand All @@ -97,9 +97,9 @@ public void test() throws Exception {
"quarkus.http.non-application-root-path=/bob\nquarkus.http.root-path=/bob"));

when().get("/bob/hello/three").then().statusCode(200);
when().get("/bob/dev").then().statusCode(200);
when().get("/bob/dev/resources/images/favicon.ico").then().statusCode(200);
when().get("/bob/dev/resources/css/tests.css").then().statusCode(200);
when().get("/bob/dev-v1").then().statusCode(200);
when().get("/bob/dev-v1/resources/images/favicon.ico").then().statusCode(200);
when().get("/bob/dev-v1/resources/css/tests.css").then().statusCode(200);
when().get("/bob/metrics").then().statusCode(200)
.body(containsString("/hello/{message}")) // http root prefix is removed in output
.body(containsString("/bob/dev"));
Expand All @@ -115,8 +115,8 @@ public void test() throws Exception {
"quarkus.http.non-application-root-path=/george"));

when().get("/bob/hello/three").then().statusCode(200);
when().get("/george/dev").then().statusCode(200);
when().get("/george/dev/resources/images/favicon.ico").then().statusCode(200);
when().get("/george/dev-v1").then().statusCode(200);
when().get("/george/dev-v1/resources/images/favicon.ico").then().statusCode(200);
when().get("/george/metrics").then().statusCode(200)
.body(containsString("/hello/{message}")); // no longer matches pattern
when().get("/bob/test/requests").then().statusCode(200)
Expand All @@ -131,8 +131,8 @@ public void test() throws Exception {
"quarkus.http.non-application-root-path=george"));

when().get("/bob/hello/three").then().statusCode(200);
when().get("/bob/george/dev").then().statusCode(200);
when().get("/bob/george/dev/resources/images/favicon.ico").then().statusCode(200);
when().get("/bob/george/dev-v1").then().statusCode(200);
when().get("/bob/george/dev-v1/resources/images/favicon.ico").then().statusCode(200);
when().get("/bob/george/metrics").then().statusCode(200)
.body(containsString("/hello/{message}")); // no longer matches pattern, http root removed
when().get("/bob/test/requests").then().statusCode(200)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class DevConsolePreviewTest {
@Test
public void testLoopPreview() {
RestAssured.with().formParam("template-select", "loop.txt").formParam("template-data", "{\"total\": [1 ,2 ,3]}")
.post("q/dev/io.quarkus.quarkus-qute/preview")
.post("q/dev-v1/io.quarkus.quarkus-qute/preview")
.then()
.statusCode(200)
.body(Matchers.equalTo("1:2:3:"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public void testInvokeScheduledTask() {
.body(Matchers.equalTo("true"));
RestAssured.with().formParam("name", "io.quarkus.scheduler.test.devconsole.NeverRunTask#run")
.redirects().follow(false)
.post("q/dev/io.quarkus.quarkus-scheduler/schedules")
.post("q/dev-v1/io.quarkus.quarkus-scheduler/schedules")
.then()
.statusCode(303);
RestAssured.with()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public void testInvokeScheduledTask() {
.body(Matchers.equalTo("true"));
RestAssured.with().formParam("name", "io.quarkus.scheduler.test.devconsole.NeverRunTask#run")
.redirects().follow(false)
.post("q/dev/io.quarkus.quarkus-scheduler/schedules")
.post("q/dev-v1/io.quarkus.quarkus-scheduler/schedules")
.then()
.statusCode(303);
RestAssured.with()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ void registerDevUiHandlers(
.handler(recorder.mvnpmHandler(mvnpmBuildItem.getMvnpmJars()))
.build());

// Redirect /q/dev -> /q/dev-ui
routeProducer.produce(RouteBuildItem.builder()
.route("/q/dev")
.handler(recorder.redirect())
.build());
}

/**
Expand Down
Loading

0 comments on commit 3864a58

Please sign in to comment.