Test jax-rs on wildfly
ADD
instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-wildfly-testing/jaxrs-2.0-wildfly-testing.gradle
+ext.skipPublish = true
+apply from: "$rootDir/gradle/instrumentation.gradle"
+
+configurations {
+ testServer
+}
+
+dependencies {
+ api "javax:javaee-api:7.0"
+
+ def arquillianVersion = '1.4.0.Final'
+ testImplementation "org.jboss.arquillian.junit:arquillian-junit-container:${arquillianVersion}"
+ testImplementation "org.jboss.arquillian.protocol:arquillian-protocol-servlet:${arquillianVersion}"
+ testImplementation "org.wildfly.arquillian:wildfly-arquillian-container-embedded:2.2.0.Final"
+ testImplementation 'org.jboss.arquillian.spock:arquillian-spock-container:1.0.0.CR1'
+ testImplementation "org.jboss.shrinkwrap.resolver:shrinkwrap-resolver-gradle-depchain:3.1.3"
+ testImplementation "org.glassfish.jersey.core:jersey-client:2.8"
+
+ testInstrumentation project(':instrumentation:servlet:servlet-3.0:javaagent')
+ testInstrumentation project(':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-common:javaagent')
+
+ // wildfly version used to run tests
+ testServer "org.wildfly:wildfly-dist:18.0.0.Final@zip"
+}
+
+// extract wildfly dist, path is used from arquillian.xml
+task setupServer(type: Copy) {
+ from zipTree(configurations.testServer.singleFile)
+ into file('build/server/')
+}
+
+// logback-classic contains /META-INF/services/javax.servlet.ServletContainerInitializer
+// that breaks deploy on embedded wildfly
+// create a copy of logback-classic jar that does not have this file
+task modifyLogbackJar(type: Jar) {
+ doFirst {
+ configurations.configureEach {
+ if (it.name.toLowerCase().endsWith('testruntimeclasspath')) {
+ def logbackJar = it.find { it.name.contains('logback-classic') }
+ from zipTree(logbackJar)
+ exclude(
+ "/META-INF/services/javax.servlet.ServletContainerInitializer"
+ )
+ destinationDirectory = file("$buildDir/tmp")
+ archiveFileName = "logback-classic-modified.jar"
+ }
+ }
+ }
+}
+
+test.dependsOn modifyLogbackJar, setupServer
+
+test {
+ doFirst {
+ // --add-modules is unrecognized on jdk8, ignore it instead of failing
+ jvmArgs "-XX:+IgnoreUnrecognizedVMOptions"
+ // needed for java 11 to avoid org.jboss.modules.ModuleNotFoundException: java.se
+ jvmArgs "--add-modules=java.se"
+ // add offset to default port values
+ jvmArgs "-Djboss.socket.binding.port-offset=100"
+
+ // remove logback-classic from classpath
+ classpath = classpath.filter {
+ return !it.absolutePath.contains("logback-classic")
+ }
+ // add modified copy of logback-classic to classpath
+ classpath += files("$buildDir/tmp/logback-classic-modified.jar")
+ }
+}
\ No newline at end of file

ADD
instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-wildfly-testing/src/test/groovy/WildflyRestTest.groovy
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
+import javax.ws.rs.client.Client
+import javax.ws.rs.client.WebTarget
+import org.glassfish.jersey.client.JerseyClientBuilder
+import org.jboss.arquillian.container.test.api.Deployment
+import org.jboss.arquillian.container.test.api.RunAsClient
+import org.jboss.arquillian.spock.ArquillianSputnik
+import org.jboss.arquillian.test.api.ArquillianResource
+import org.jboss.shrinkwrap.api.ShrinkWrap
+import org.jboss.shrinkwrap.api.asset.EmptyAsset
+import org.jboss.shrinkwrap.api.spec.WebArchive
+import org.junit.runner.RunWith
+import test.CdiRestResource
+import test.EjbRestResource
+import test.RestApplication
+
+@RunWith(ArquillianSputnik)
+@RunAsClient
+class WildflyRestTest extends AgentInstrumentationSpecification {
+
+ @ArquillianResource
+ static URI url
+
+ @Deployment
+ static WebArchive createDeployment() {
+ return ShrinkWrap.create(WebArchive)
+ .addClass(RestApplication)
+ .addClass(CdiRestResource)
+ .addClass(EjbRestResource)
+ .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
+ }
+
+ def getContextRoot() {
+ return url.getPath()
+ }
+
+ def "test #path"() {
+ when:
+ Client client = JerseyClientBuilder.newClient()
+ WebTarget webTarget = client.target(url)
+
+ String result = webTarget.path(path)
+ .request()
+ .get()
+ .readEntity(String)
+
+ then:
+ result == "hello"
+
+ and:
+ assertTraces(1) {
+ trace(0, 2) {
+ span(0) {
+ name getContextRoot() + path
+ hasNoParent()
+ }
+ span(1) {
+ name className + ".hello"
+ childOf span(0)
+ }
+ }
+ }
+
+ where:
+ path | className
+ "cdiHello" | "CdiRestResource"
+ "ejbHello" | "EjbRestResource"
+ }
+}

ADD
instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-wildfly-testing/src/test/java/test/CdiRestResource.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package test;
+
+import javax.inject.Named;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+@Path("/cdiHello")
+@Named("cdiHello")
+public class CdiRestResource {
+
+ @GET
+ public String hello() {
+ return "hello";
+ }
+}

ADD
instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-wildfly-testing/src/test/java/test/EjbRestResource.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package test;
+
+import javax.ejb.Stateless;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+@Path("/ejbHello")
+@Stateless
+public class EjbRestResource {
+
+ @GET
+ public String hello() {
+ return "hello";
+ }
+}

ADD
instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-wildfly-testing/src/test/java/test/RestApplication.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package test;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+@ApplicationPath("/")
+public class RestApplication extends Application {
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ return new HashSet<>(Arrays.asList(CdiRestResource.class, EjbRestResource.class));
+ }
+}

ADD
instrumentation/jaxrs/jaxrs-2.0/jaxrs-2.0-wildfly-testing/src/test/resources/arquillian.xml
+<arquillian xmlns="http://jboss.org/schema/arquillian"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://jboss.org/schema/arquillian
+ http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
+
+ <defaultProtocol type="Servlet 3.0" />
+
+ <container qualifier="wildfly-embedded" default="true">
+ <configuration>
+ <property name="jbossHome">build/server/wildfly-18.0.0.Final</property>
+ <property name="modulePath">build/server/wildfly-18.0.0.Final/modules</property>
+ </configuration>
+ </container>
+</arquillian>
\ No newline at end of file

MODIFY
javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/matcher/GlobalIgnoresMatcher.java
javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/matcher/GlobalIgnoresMatcher.java
@@ -170,6 +170,15 @@ public class GlobalIgnoresMatcher<T extends TypeDescription>
return true;
}
+ // bytecode proxies typically have $$ in their name
+ if (name.contains("$$")) {
+ // scala anonymous classes
+ if (name.contains("$$anon$")) {
+ return false;
+ }
+ return true;
+ }
+
if (name.contains("$JaxbAccessor")
|| name.contains("CGLIB$$")
|| name.contains("javassist")

MODIFY
settings.gradle
settings.gradle
@@ -118,6 +118,7 @@ include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-jersey-2.0:javaagent'
include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-resteasy-3.0:javaagent'
include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-resteasy-3.1:javaagent'
include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-testing'
+include ':instrumentation:jaxrs:jaxrs-2.0:jaxrs-2.0-wildfly-testing'
include ':instrumentation:jaxrs-client:jaxrs-client-1.1:javaagent'
include ':instrumentation:jaxrs-client:jaxrs-client-2.0:jaxrs-client-2.0-common:javaagent'
include ':instrumentation:jaxrs-client:jaxrs-client-2.0:jaxrs-client-2.0-cxf-3.0:javaagent'

Test jax-rs on wildfly (#2242)