diff --git a/tracing-example/README.adoc b/tracing-example/README.adoc
index ff175240..2f642527 100644
--- a/tracing-example/README.adoc
+++ b/tracing-example/README.adoc
@@ -1,4 +1,4 @@
-== Usage
+= RESTEasy Tracing Example
This is a demonstration of the resteasy tracing feature.
@@ -9,11 +9,14 @@ To run the example, you can simply run it with WildFly:
$ mvn wildfly:run
----
+== Usage
+
After server started, we can access the server and get the tracing info:
+=== Command Line
[source,bash]
----
-$ curl -i http://localhost:8080/tracing-example/level
+$ curl -i http://localhost:8080/tracing-example/trace/level
----
And here is the sample output:
@@ -34,4 +37,9 @@ X-RESTEasy-Tracing-189: org.jboss.resteasy.plugins.server.servlet.Servlet3AsyncH
X-RESTEasy-Tracing-190: org.jboss.resteasy.plugins.server.servlet.Servlet3AsyncHttpRequest@5c54713c MBW [ ---- / 90378.04 ms | ---- %] Find MBW for type=[java.lang.String] genericType=[java.lang.String] mediaType=[[jakarta.ws.rs.core.MediaType @45b9c1ef]] annotations=[@jakarta.ws.rs.GET(), @jakarta.ws.rs.Path(value="/level")]
----
-Above is the basic usage of the sample. You should also see output on the console WildFly is running in as well.
\ No newline at end of file
+Above is the basic usage of the sample. You should also see output on the console WildFly is running in as well.
+
+=== Web
+
+Navigate to http://localhost:8080/tracing-example. From there you should see a web page which can be used to execute
+HTTP requests through a client returning the tracing headers.
\ No newline at end of file
diff --git a/tracing-example/pom.xml b/tracing-example/pom.xml
index d008b981..a6b422ad 100644
--- a/tracing-example/pom.xml
+++ b/tracing-example/pom.xml
@@ -47,16 +47,6 @@
-
-
- wildfly27
-
- 27.0.1.Final
- compile
-
-
-
-
@@ -196,16 +186,47 @@
${version.wildfly-maven-plugin}${jboss.home}
+ ${jboss.home}
+
+
+ org.wildfly
+ wildfly-ee-galleon-pack
+ ${version.org.wildfly}
+
+
+
+ true
+
- provision-test-server
+ provision-serverprocess-test-classesprovision
+
+
+
+
+
+
+
+
+ wildfly27
+
+ 27.0.1.Final
+ compile
+
+
+
+
+
+ org.wildfly.plugins
+ wildfly-maven-plugin
+ ${version.wildfly-maven-plugin}
- ${jboss.home}
+ ${jboss.home}
@@ -224,13 +245,19 @@
${version.org.jboss.resteasy}
-
- true
-
-
-
-
-
-
+
+
+ provision-server
+ process-test-classes
+
+ provision
+
+
+
+
+
+
+
+
diff --git a/tracing-example/src/main/java/dev/resteasy/examples/tracing/TraceMethodResource.java b/tracing-example/src/main/java/dev/resteasy/examples/tracing/TraceMethodResource.java
new file mode 100644
index 00000000..0240ba9b
--- /dev/null
+++ b/tracing-example/src/main/java/dev/resteasy/examples/tracing/TraceMethodResource.java
@@ -0,0 +1,57 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ *
+ * Copyright 2023 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dev.resteasy.examples.tracing;
+
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+
+/**
+ * @author James R. Perkins
+ */
+@Path("/headers")
+@RequestScoped
+@Consumes(MediaType.TEXT_PLAIN)
+@Produces(MediaType.TEXT_PLAIN)
+public class TraceMethodResource {
+
+ @GET
+ @Path("get")
+ public String get() {
+ return "GET trace";
+ }
+
+ @POST
+ @Path("post")
+ public String post(final String value) {
+ return String.format("POST trace: %s", value);
+ }
+
+ @PUT
+ @Path("put")
+ public String put(final String value) {
+ return String.format("PUT trace: %s", value);
+ }
+}
diff --git a/tracing-example/src/main/java/dev/resteasy/examples/tracing/TracingApp.java b/tracing-example/src/main/java/dev/resteasy/examples/tracing/TracingApp.java
index 485a4b76..cfcedc73 100644
--- a/tracing-example/src/main/java/dev/resteasy/examples/tracing/TracingApp.java
+++ b/tracing-example/src/main/java/dev/resteasy/examples/tracing/TracingApp.java
@@ -3,6 +3,6 @@
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;
-@ApplicationPath("/")
+@ApplicationPath("/trace")
public class TracingApp extends Application {
}
diff --git a/tracing-example/src/main/webapp/WEB-INF/beans.xml b/tracing-example/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 00000000..ac9e52bb
--- /dev/null
+++ b/tracing-example/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,20 @@
+
+
+
\ No newline at end of file
diff --git a/tracing-example/src/main/webapp/index.html b/tracing-example/src/main/webapp/index.html
new file mode 100644
index 00000000..d95db8ed
--- /dev/null
+++ b/tracing-example/src/main/webapp/index.html
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+ Contacts
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ HTTP Method:
+
+
+ Invoked:
+
+
+ Response:
+
+
+
+
+
+
Header Name
+
Header Value
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tracing-example/src/main/webapp/resources/main.js b/tracing-example/src/main/webapp/resources/main.js
new file mode 100644
index 00000000..23effe26
--- /dev/null
+++ b/tracing-example/src/main/webapp/resources/main.js
@@ -0,0 +1,146 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ *
+ * Copyright 2023 Red Hat, Inc., and individual contributors
+ * as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(() => {
+ "use strict";
+
+ window.addEventListener("load", () => {
+ // Enable tooltips
+ const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
+ [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl, {
+ trigger: "hover",
+ delay: 500
+ }));
+ // Add the functions to the buttons
+ const submitButton = document.querySelector("#submit");
+ submitButton.addEventListener("click", () => {
+ const radioButtons = document.querySelectorAll("input[name='httpMethod']");
+ let httpMethod;
+ for (const radioButton of radioButtons) {
+ if (radioButton.checked) {
+ httpMethod = radioButton.value;
+ break;
+ }
+ }
+ loadTable(httpMethod);
+ });
+ const clearButton = document.querySelector("#clear");
+ clearButton.addEventListener("click", () => {
+ // Clear the elements we want to be reset
+ const link = document.querySelector("#url");
+ clearElement(link);
+ link.classList.remove("placeholder", "col-5", "bg-secondary");
+ clearElement(document.querySelector("#sentHttpMethod"));
+ clearElement(document.querySelector("#response"));
+ clearElement(document.querySelector("#output"));
+ });
+ });
+
+ function loadTable(httpMethod) {
+ const link = document.querySelector("#url");
+ document.querySelector("#sentHttpMethod").textContent = httpMethod.toUpperCase();
+ clearElement(link);
+ link.classList.add("placeholder", "col-5", "bg-secondary");
+
+ // Get the table body for the output
+ const tbody = document.querySelector("#output");
+ // Clear the table
+ clearElement(tbody);
+ // Add a temporary row to the table to indicate we are loading
+ const trTemp = tbody.insertRow();
+ const col1Temp = trTemp.insertCell();
+ const spinnerDiv = document.createElement("div");
+ spinnerDiv.classList.add("spinner-border");
+ spinnerDiv.setAttribute("role", "status");
+ const spinner = document.createElement("span");
+ spinner.classList.add("visually-hidden");
+ spinner.textContent = "Loading...";
+ spinnerDiv.append(spinner);
+ col1Temp.append(spinnerDiv);
+ trTemp.insertCell();
+
+ const url = "trace/headers/" + httpMethod;
+ // Create potential data
+ let config = {};
+ if (httpMethod === "post" || httpMethod === "put") {
+ config = {
+ method: httpMethod.toUpperCase(),
+ body: `${httpMethod} data`
+ };
+ }
+ fetch(url, config)
+ .then((r) => {
+ // Create a link to the resource we just invoked
+ const a = document.createElement("a");
+ a.setAttribute("href", r.url);
+ a.setAttribute("target", "_");
+ a.textContent = r.url;
+ link.classList.remove("placeholder", "col-5", "bg-secondary");
+ link.append(a);
+ r.text().then((text) => {
+ clearElement(tbody);
+ document.querySelector("#response").textContent = text;
+ // Add a table entry for each header value
+ const headers = r.headers;
+ for (let header of headers.entries()) {
+ const tr = tbody.insertRow();
+ const name = tr.insertCell();
+ name.textContent = header[0];
+ const value = tr.insertCell();
+ value.textContent = header[1];
+ }
+ });
+ }).catch(err => {
+ error("Request has failed: " + err);
+ });
+ }
+
+ /**
+ * Clears the children of the element.
+ * @param e the element to clear
+ */
+ function clearElement(e) {
+ while (e.firstChild) {
+ e.removeChild(e.firstChild);
+ }
+ }
+
+ function success(message) {
+ showAlert(message);
+ }
+
+ function error(message) {
+ showAlert(message, "danger");
+ }
+
+ function showAlert(message, type = "success", autoHide = "true") {
+ const alertPlaceholder = document.querySelector("#liveAlertPlaceholder");
+ const alert = document.querySelector("#alert").content.cloneNode(true).querySelector("div.toast");
+ alert.setAttribute("data-bs-autohide", autoHide);
+ alert.classList.add("text-bg-" + type);
+ const body = alert.querySelector(".toast-body");
+ body.textContent = message;
+ alert.addEventListener("hidden.bs.toast", () => {
+ alertPlaceholder.removeChild(alert);
+ });
+ const toast = new bootstrap.Toast(alert);
+ toast.show();
+ alertPlaceholder.append(alert);
+ }
+})()
\ No newline at end of file
diff --git a/tracing-example/src/test/java/dev/resteasy/examples/tracing/TracingTest.java b/tracing-example/src/test/java/dev/resteasy/examples/tracing/TracingTest.java
index da244f8d..83091676 100644
--- a/tracing-example/src/test/java/dev/resteasy/examples/tracing/TracingTest.java
+++ b/tracing-example/src/test/java/dev/resteasy/examples/tracing/TracingTest.java
@@ -56,13 +56,13 @@ public static WebArchive deployment() {
@Test
public void basicTest() {
try (Client client = ClientBuilder.newClient()) {
- WebTarget target = client.target(uriBuilder().path("type"));
+ WebTarget target = client.target(uriBuilder().path("trace/type"));
assertEquals(ResteasyContextParameters.RESTEASY_TRACING_TYPE_ALL, target.request().get(String.class));
- target = client.target(uriBuilder().path("level"));
+ target = client.target(uriBuilder().path("trace/level"));
assertEquals(ResteasyContextParameters.RESTEASY_TRACING_LEVEL_VERBOSE, target.request().get(String.class));
- target = client.target(uriBuilder().path("logger"));
+ target = client.target(uriBuilder().path("trace/logger"));
assertEquals(RESTEasyTracingLogger.class.getName(), target.request().get(String.class));
}
}