diff --git a/dd-smoke-tests/wildfly/build.gradle b/dd-smoke-tests/wildfly/build.gradle index 970fac8aae2..9fe2f1ae7a7 100644 --- a/dd-smoke-tests/wildfly/build.gradle +++ b/dd-smoke-tests/wildfly/build.gradle @@ -1,6 +1,7 @@ ext { serverName = 'wildfly' - serverModule = 'servlet' + //serverModule = 'servlet' + serverModule = 'wildfly' serverVersion = '15.0.0.Final' serverExtension = 'zip' } @@ -9,7 +10,9 @@ repositories { ivy { url 'https://download.jboss.org/' patternLayout { - artifact '/[organisation]/[revision]/[module]/[organisation]-[module]-[revision].[ext]' + // artifact '/[organisation]/[revision]/[module]/[organisation]-[module]-[revision].[ext]' + // we download the full EE profile and not the servlet minimal one + artifact '/[organisation]/[revision]/[organisation]-[revision].[ext]' metadataSources { artifact() } @@ -80,12 +83,12 @@ spotless { } } -def wildflyDir="${buildDir}/${serverName}-${serverModule}-${serverVersion}" +def wildflyDir="${buildDir}/${serverName}-${serverVersion}" tasks.register("unzip", Copy) { dependsOn tasks.earBuild mustRunAfter tasks.compileTestGroovy - def zipFileNamePrefix = "servlet" + def zipFileNamePrefix = "wildfly" def zipPath = project.configurations.serverFile.find { it.name.startsWith(zipFileNamePrefix) } diff --git a/dd-smoke-tests/wildfly/spring-ear/.gitignore b/dd-smoke-tests/wildfly/spring-ear/.gitignore index 1ec2c548b11..72d30a335be 100644 --- a/dd-smoke-tests/wildfly/spring-ear/.gitignore +++ b/dd-smoke-tests/wildfly/spring-ear/.gitignore @@ -1,5 +1,6 @@ # Ignore all project specific gradle directories/files .gradle +.idea gradle build gradlew diff --git a/dd-smoke-tests/wildfly/spring-ear/war/build.gradle b/dd-smoke-tests/wildfly/spring-ear/war/build.gradle index eb58e0085e6..2ebbfebc77b 100644 --- a/dd-smoke-tests/wildfly/spring-ear/war/build.gradle +++ b/dd-smoke-tests/wildfly/spring-ear/war/build.gradle @@ -7,4 +7,6 @@ repositories { dependencies { compileOnly 'org.springframework:spring-webmvc:5.3.0' + compileOnly group: 'javax', name: 'javaee-api', version: '8.0.1' + implementation group: 'com.datadoghq', name: 'dd-trace-api', version: '1.43.0' } diff --git a/dd-smoke-tests/wildfly/spring-ear/war/src/main/java/com/example/Common.java b/dd-smoke-tests/wildfly/spring-ear/war/src/main/java/com/example/Common.java new file mode 100644 index 00000000000..42cd6cc1ff7 --- /dev/null +++ b/dd-smoke-tests/wildfly/spring-ear/war/src/main/java/com/example/Common.java @@ -0,0 +1,8 @@ +package com.example; + +import java.util.concurrent.atomic.AtomicBoolean; + +public class Common { + // for the sake of this example it avoids boilerplate ton inject an ejb into a spring context + public static final AtomicBoolean ENABLED = new AtomicBoolean(false); +} diff --git a/dd-smoke-tests/wildfly/spring-ear/war/src/main/java/com/example/ejb/ScheduledEjb.java b/dd-smoke-tests/wildfly/spring-ear/war/src/main/java/com/example/ejb/ScheduledEjb.java new file mode 100644 index 00000000000..0550a4e3b1e --- /dev/null +++ b/dd-smoke-tests/wildfly/spring-ear/war/src/main/java/com/example/ejb/ScheduledEjb.java @@ -0,0 +1,23 @@ +package com.example.ejb; + +import static com.example.Common.ENABLED; + +import datadog.trace.api.Trace; +import javax.ejb.Schedule; +import javax.ejb.Stateless; + +@Stateless +public class ScheduledEjb { + + @Schedule(second = "*/1", minute = "*", hour = "*") + public void runIt() { + if (ENABLED.getAndSet(false)) { + generateSomeTrace(); + } + } + + @Trace + private void generateSomeTrace() { + // empty + } +} diff --git a/dd-smoke-tests/wildfly/spring-ear/war/src/main/java/com/example/hello/HelloController.java b/dd-smoke-tests/wildfly/spring-ear/war/src/main/java/com/example/hello/HelloController.java index 891150cc10d..2592edc3ec8 100644 --- a/dd-smoke-tests/wildfly/spring-ear/war/src/main/java/com/example/hello/HelloController.java +++ b/dd-smoke-tests/wildfly/spring-ear/war/src/main/java/com/example/hello/HelloController.java @@ -1,5 +1,9 @@ package com.example.hello; +import static com.example.Common.ENABLED; + +import java.util.concurrent.CompletableFuture; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -10,4 +14,21 @@ public class HelloController { public String hello() { return "hello world"; } + + @RequestMapping("/enableScheduling") + public CompletableFuture> enableScheduling() { + ENABLED.set(true); + return CompletableFuture.supplyAsync( + () -> { + while (!ENABLED.get()) { + try { + Thread.sleep(200); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + break; + } + } + return ResponseEntity.ok().build(); + }); + } } diff --git a/dd-smoke-tests/wildfly/spring-ear/war/src/main/webapp/WEB-INF/beans.xml b/dd-smoke-tests/wildfly/spring-ear/war/src/main/webapp/WEB-INF/beans.xml new file mode 100644 index 00000000000..f0ba505ab81 --- /dev/null +++ b/dd-smoke-tests/wildfly/spring-ear/war/src/main/webapp/WEB-INF/beans.xml @@ -0,0 +1,8 @@ + + + + diff --git a/dd-smoke-tests/wildfly/spring-ear/war/src/main/webapp/WEB-INF/web.xml b/dd-smoke-tests/wildfly/spring-ear/war/src/main/webapp/WEB-INF/web.xml index 36f2c845f1a..9d1fd42e198 100644 --- a/dd-smoke-tests/wildfly/spring-ear/war/src/main/webapp/WEB-INF/web.xml +++ b/dd-smoke-tests/wildfly/spring-ear/war/src/main/webapp/WEB-INF/web.xml @@ -8,6 +8,7 @@ dispatcher org.springframework.web.servlet.DispatcherServlet + true 1 diff --git a/dd-smoke-tests/wildfly/src/test/groovy/datadog/smoketest/WildflySmokeTest.groovy b/dd-smoke-tests/wildfly/src/test/groovy/datadog/smoketest/WildflySmokeTest.groovy index 5da6a415260..f6a3158c2f8 100644 --- a/dd-smoke-tests/wildfly/src/test/groovy/datadog/smoketest/WildflySmokeTest.groovy +++ b/dd-smoke-tests/wildfly/src/test/groovy/datadog/smoketest/WildflySmokeTest.groovy @@ -1,11 +1,13 @@ package datadog.smoketest +import datadog.trace.agent.test.utils.OkHttpUtils import datadog.trace.agent.test.utils.PortUtils -import datadog.trace.test.util.Flaky import okhttp3.Request import spock.lang.Shared +import spock.util.concurrent.PollingConditions + +import java.util.concurrent.atomic.AtomicInteger -@Flaky class WildflySmokeTest extends AbstractServerSmokeTest { @Shared @@ -24,12 +26,42 @@ class WildflySmokeTest extends AbstractServerSmokeTest { *defaultJavaProperties, "-Djboss.http.port=${httpPort}", "-Djboss.https.port=${httpsPort}", - "-Djboss.management.http.port=${managementPort}" + "-Djboss.management.http.port=${managementPort}", + "-Ddd.trace.experimental.jee.split-by-deployment=true", + "-Ddd.writer.type=MultiWriter:TraceStructureWriter:${output.getAbsolutePath()}:includeService,DDAgentWriter", ] - processBuilder.environment().put("JAVA_OPTS", javaOpts.collect({ it.replace(' ', '\\ ')}).join(' ')) + processBuilder.environment().put("JAVA_OPTS", javaOpts.collect({ it.replace(' ', '\\ ') }).join(' ')) return processBuilder } + @Override + File createTemporaryFile() { + def ret = File.createTempFile("trace-structure-docs", "out") + ret + } + + @Override + def inferServiceName() { + // do not set DD_SERVICE + false + } + + @Override + protected boolean isAcceptable(int processIndex, Map traceCounts) { + def hasServletRequestTraces = traceCounts.find { it.getKey() == "[war:servlet.request[war:spring.handler]]" }?.getValue()?.get() == 201 + def hasScheduledEjbTrace = traceCounts.find { it.getKey() == "[war:trace.annotation]" }?.getValue()?.get() == 1 + assert hasScheduledEjbTrace && hasServletRequestTraces: "Encountered traces: " + traceCounts + return true + } + + + def setupSpec() { + //wait for the deployment + new PollingConditions(timeout: 300, delay: 2).eventually { + assert OkHttpUtils.client().newCall(new Request.Builder().url("http://localhost:$httpPort/war/hello").build()).execute().code() == 200 + } + } + def cleanupSpec() { ProcessBuilder processBuilder = new ProcessBuilder( "${wildflyDirectory}/bin/jboss-cli.sh", @@ -41,9 +73,9 @@ class WildflySmokeTest extends AbstractServerSmokeTest { process.waitFor() } - def "default home page #n th time"() { + def "spring controller #n th time"() { setup: - String url = "http://localhost:$httpPort/" + String url = "http://localhost:$httpPort/war/hello" def request = new Request.Builder().url(url).get().build() when: @@ -52,26 +84,21 @@ class WildflySmokeTest extends AbstractServerSmokeTest { then: def responseBodyStr = response.body().string() responseBodyStr != null - responseBodyStr.contains("Your WildFly instance is running.") - response.body().contentType().toString().contains("text/html") + responseBodyStr.contentEquals("hello world") response.code() == 200 - where: n << (1..200) } - def "spring context loaded successfully"() { + def "scheduled ejb has right service name"() { setup: - String url = "http://localhost:$httpPort/war/hello" + String url = "http://localhost:$httpPort/war/enableScheduling" def request = new Request.Builder().url(url).get().build() when: def response = client.newCall(request).execute() then: - def responseBodyStr = response.body().string() - responseBodyStr != null - responseBodyStr.contentEquals("hello world") response.code() == 200 } }