Automatic tracing of Java EE applications with WildFly 14 and Jaeger

You may have heard the news: WildFly 14 has shipped with an initial support for MicroProfile OpenTracing and uses Jaeger as the default tracer. This means that applications being deployed on WildFly 14 are able to get tracing capabilities just by adding one annotation on the classes and methods that need to be traced.

In this blog post, we’ll start from scratch to show you how easy it is to enhance a Java EE application with tracing capabilities.

Let’s start by downloading and starting WildFly:

The Jaeger tracer inside WildFly is configured in the same way as when used in any other service, i.e. via environment variables, with the exception of the service name. Rather than specifying the JAEGER_SERVICE_NAME environment variable, WildFly will automatically configure the service name on a per deployment basis.

Unfortunately, WildFly 14 shipped with a bug that prevents the spans from reaching our Jaeger server. Follow the workaround described in the JIRA or download a nightly build, which should already contain the fix.

Finally, let’s get Jaeger ready as well:

And we kick start our project by running gradle init:

Project bootstrap

Our build.gradle is very minimal, containing only the dependency on the Java EE libraries and on the MicroProfile OpenTracing library, which contains the @Traced annotation that we need:

build.gradle for our project

At this point, we should be able to build a Java Web Archive (WAR) for our project: run ./gradlew war and check your build/lib directory.

Right now, our application isn’t doing anything. Let’s add a simple JAX-RS marker class, so that we are able to create REST endpoints:

src/main/java/io/jaegertracing/examples/wildfly/TracedStoreApplication.java

The next step is to create our endpoint. Note how we add the @Stateless annotation to the JAX-RS endpoint, so that we get EJB features as well. It is common practice to do this in the real world, but at this point for us, the only effect is getting our deployment marked as “CDI archive”, which is enough to trigger the MicroProfile OpenTracing integration.

src/main/java/io/jaegertracing/examples/wildfly/OrderEndpoint.java

Once we build and the deploy completes, we can call this endpoint via curl:

You should be able to see one trace in the Jaeger UI for the service javaee-traced-store-1.0-SNAPSHOT.war, containing one span.

We can make our store fancier by adding a new bean, AccountService:

src/main/java/io/jaegertracing/examples/wildfly/AccountService.java

Our new class is both an EJB and a CDI bean and can be injected as such into our JAX-RS endpoint. Let’s inject it there and call the new method from our bean:

src/main/java/io/jaegertracing/examples/wildfly/OrderEndpoint.java

To see what it looks like now in a trace, let’s build, deploy and run once more:

At this point, we should now see a second trace for our service, but with two spans.

A trace for our service with two spans

Our example is purposefully simple, to demonstrate that a single annotation is all it takes to get tracing information for our Java EE application deployed on WildFly 14. Try this new integration out with your existing applications and send us your feedback!