diff --git a/instrumentation/spring/spring-ws-2.0/javaagent/src/test/groovy/test/boot/HelloEndpoint.groovy b/instrumentation/spring/spring-ws-2.0/javaagent/src/test/groovy/test/boot/HelloEndpoint.groovy deleted file mode 100644 index 0c040cc85c..0000000000 --- a/instrumentation/spring/spring-ws-2.0/javaagent/src/test/groovy/test/boot/HelloEndpoint.groovy +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test.boot - -import io.opentelemetry.test.hello_web_service.HelloRequest -import io.opentelemetry.test.hello_web_service.HelloRequestSoapAction -import io.opentelemetry.test.hello_web_service.HelloRequestWsAction -import io.opentelemetry.test.hello_web_service.HelloResponse -import org.springframework.ws.server.endpoint.annotation.Endpoint -import org.springframework.ws.server.endpoint.annotation.PayloadRoot -import org.springframework.ws.server.endpoint.annotation.RequestPayload -import org.springframework.ws.server.endpoint.annotation.ResponsePayload -import org.springframework.ws.soap.addressing.server.annotation.Action -import org.springframework.ws.soap.server.endpoint.annotation.SoapAction - -@Endpoint -class HelloEndpoint { - private static final String NAMESPACE_URI = "http://opentelemetry.io/test/hello-web-service" - - @PayloadRoot(namespace = NAMESPACE_URI, localPart = "helloRequest") - @ResponsePayload - HelloResponse hello(@RequestPayload HelloRequest request) { - return handleHello(request.getName()) - } - - @SoapAction(value = "http://opentelemetry.io/test/hello-soap-action") - @ResponsePayload - HelloResponse helloSoapAction(@RequestPayload HelloRequestSoapAction request) { - return handleHello(request.getName()) - } - - @Action(value = "http://opentelemetry.io/test/hello-ws-action") - @ResponsePayload - HelloResponse helloWsAction(@RequestPayload HelloRequestWsAction request) { - return handleHello(request.getName()) - } - - private HelloResponse handleHello(String name) { - if ("exception" == name) { - throw new Exception("hello exception") - } - HelloResponse response = new HelloResponse() - response.setMessage("Hello " + name) - - return response - } -} diff --git a/instrumentation/spring/spring-ws-2.0/javaagent/src/test/groovy/test/boot/SpringWsTest.groovy b/instrumentation/spring/spring-ws-2.0/javaagent/src/test/groovy/test/boot/SpringWsTest.groovy deleted file mode 100644 index c14e073cf0..0000000000 --- a/instrumentation/spring/spring-ws-2.0/javaagent/src/test/groovy/test/boot/SpringWsTest.groovy +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test.boot - -import io.opentelemetry.api.trace.SpanKind -import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification -import io.opentelemetry.instrumentation.test.asserts.TraceAssert -import io.opentelemetry.instrumentation.test.base.HttpServerTestTrait -import io.opentelemetry.sdk.trace.data.SpanData -import io.opentelemetry.semconv.incubating.CodeIncubatingAttributes -import io.opentelemetry.test.hello_web_service.HelloRequest -import io.opentelemetry.test.hello_web_service.HelloRequestSoapAction -import io.opentelemetry.test.hello_web_service.HelloRequestWsAction -import io.opentelemetry.test.hello_web_service.HelloResponse -import org.springframework.boot.SpringApplication -import org.springframework.context.ConfigurableApplicationContext -import org.springframework.oxm.jaxb.Jaxb2Marshaller -import org.springframework.util.ClassUtils -import org.springframework.ws.client.core.WebServiceMessageCallback -import org.springframework.ws.client.core.WebServiceTemplate -import org.springframework.ws.soap.addressing.client.ActionCallback -import org.springframework.ws.soap.client.SoapFaultClientException -import org.springframework.ws.soap.client.core.SoapActionCallback -import spock.lang.Shared - -import static io.opentelemetry.api.trace.SpanKind.INTERNAL -import static io.opentelemetry.api.trace.StatusCode.ERROR - -class SpringWsTest extends AgentInstrumentationSpecification implements HttpServerTestTrait { - - @Shared - private Jaxb2Marshaller marshaller = new Jaxb2Marshaller() - - def setupSpec() { - setupServer() - - marshaller.setPackagesToScan(ClassUtils.getPackageName(HelloRequest)) - marshaller.afterPropertiesSet() - } - - def cleanupSpec() { - cleanupServer() - } - - @Override - ConfigurableApplicationContext startServer(int port) { - def app = new SpringApplication(AppConfig, WebServiceConfig) - app.setDefaultProperties([ - "server.port" : port, - "server.context-path" : getContextPath(), - "server.servlet.contextPath" : getContextPath(), - "server.error.include-message": "always"]) - def context = app.run() - return context - } - - @Override - void stopServer(ConfigurableApplicationContext ctx) { - ctx.close() - } - - @Override - String getContextPath() { - return "/xyz" - } - - HelloResponse makeRequest(methodName, name) { - WebServiceTemplate webServiceTemplate = new WebServiceTemplate(marshaller) - - Object request = null - WebServiceMessageCallback callback = null - if ("hello" == methodName) { - request = new HelloRequest(name: name) - } else if ("helloSoapAction" == methodName) { - request = new HelloRequestSoapAction(name: name) - callback = new SoapActionCallback("http://opentelemetry.io/test/hello-soap-action") - } else if ("helloWsAction" == methodName) { - request = new HelloRequestWsAction(name: name) - callback = new ActionCallback("http://opentelemetry.io/test/hello-ws-action") - } else { - throw new IllegalArgumentException(methodName) - } - - return (HelloResponse) webServiceTemplate.marshalSendAndReceive(address.resolve("ws").toString(), request, callback) - } - - def "test #methodName"(methodName) { - setup: - HelloResponse response = makeRequest(methodName, "Test") - - expect: - response.getMessage() == "Hello Test" - - and: - assertTraces(1) { - trace(0, 2) { - serverSpan(it, 0, getContextPath() + "/ws/*") - handlerSpan(it, 1, methodName, span(0)) - } - } - - where: - methodName << ["hello", "helloSoapAction", "helloWsAction"] - } - - def "test #methodName exception"(methodName) { - when: - makeRequest(methodName, "exception") - - then: - def error = thrown(SoapFaultClientException) - error.getMessage() == "hello exception" - - and: - def expectedException = new Exception("hello exception") - assertTraces(1) { - trace(0, 2) { - serverSpan(it, 0, getContextPath() + "/ws/*", expectedException) - handlerSpan(it, 1, methodName, span(0), expectedException) - } - } - - where: - methodName << ["hello", "helloSoapAction", "helloWsAction"] - } - - static serverSpan(TraceAssert trace, int index, String route, Throwable exception = null) { - trace.span(index) { - hasNoParent() - name "POST " + route - kind SpanKind.SERVER - if (exception != null) { - status ERROR - } - } - } - - static handlerSpan(TraceAssert trace, int index, String methodName, Object parentSpan = null, Throwable exception = null) { - trace.span(index) { - if (parentSpan == null) { - hasNoParent() - } else { - childOf((SpanData) parentSpan) - } - name "HelloEndpoint." + methodName - kind INTERNAL - if (exception) { - status ERROR - errorEvent(exception.class, exception.message) - } - attributes { - "$CodeIncubatingAttributes.CODE_NAMESPACE" "test.boot.HelloEndpoint" - "$CodeIncubatingAttributes.CODE_FUNCTION" methodName - } - } - } -} diff --git a/instrumentation/spring/spring-ws-2.0/javaagent/src/test/groovy/test/boot/WebServiceConfig.groovy b/instrumentation/spring/spring-ws-2.0/javaagent/src/test/groovy/test/boot/WebServiceConfig.groovy deleted file mode 100644 index 13e9b18333..0000000000 --- a/instrumentation/spring/spring-ws-2.0/javaagent/src/test/groovy/test/boot/WebServiceConfig.groovy +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package test.boot - -import org.springframework.boot.web.servlet.ServletRegistrationBean -import org.springframework.context.ApplicationContext -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.core.io.ClassPathResource -import org.springframework.ws.config.annotation.EnableWs -import org.springframework.ws.config.annotation.WsConfigurerAdapter -import org.springframework.ws.transport.http.MessageDispatcherServlet -import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition -import org.springframework.xml.xsd.SimpleXsdSchema -import org.springframework.xml.xsd.XsdSchema - -@EnableWs -@Configuration -class WebServiceConfig extends WsConfigurerAdapter { - @Bean - ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) { - MessageDispatcherServlet servlet = new MessageDispatcherServlet() - servlet.setApplicationContext(applicationContext) - servlet.setTransformWsdlLocations(true) - return new ServletRegistrationBean<>(servlet, "/ws/*") - } - - @Bean(name = "hello") - DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) { - DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition() - wsdl11Definition.setPortTypeName("HelloPort") - wsdl11Definition.setLocationUri("/ws") - wsdl11Definition.setTargetNamespace("http://opentelemetry.io/test/hello-web-service") - wsdl11Definition.setSchema(countriesSchema) - return wsdl11Definition - } - - @Bean - XsdSchema helloSchema() { - return new SimpleXsdSchema(new ClassPathResource("hello.xsd")) - } - -} diff --git a/instrumentation/spring/spring-ws-2.0/javaagent/src/test/groovy/test/boot/AppConfig.groovy b/instrumentation/spring/spring-ws-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/ws/v2_0/AppConfig.java similarity index 63% rename from instrumentation/spring/spring-ws-2.0/javaagent/src/test/groovy/test/boot/AppConfig.groovy rename to instrumentation/spring/spring-ws-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/ws/v2_0/AppConfig.java index e9ddd37cdb..2ffa4dd640 100644 --- a/instrumentation/spring/spring-ws-2.0/javaagent/src/test/groovy/test/boot/AppConfig.groovy +++ b/instrumentation/spring/spring-ws-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/ws/v2_0/AppConfig.java @@ -3,12 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -package test.boot +package io.opentelemetry.javaagent.instrumentation.spring.ws.v2_0; -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @SpringBootApplication -class AppConfig implements WebMvcConfigurer { - -} +public class AppConfig implements WebMvcConfigurer {} diff --git a/instrumentation/spring/spring-ws-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/ws/v2_0/HelloEndpoint.java b/instrumentation/spring/spring-ws-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/ws/v2_0/HelloEndpoint.java new file mode 100644 index 0000000000..0fdf3be509 --- /dev/null +++ b/instrumentation/spring/spring-ws-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/ws/v2_0/HelloEndpoint.java @@ -0,0 +1,52 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.spring.ws.v2_0; + +import io.opentelemetry.test.hello_web_service.HelloRequest; +import io.opentelemetry.test.hello_web_service.HelloRequestSoapAction; +import io.opentelemetry.test.hello_web_service.HelloRequestWsAction; +import io.opentelemetry.test.hello_web_service.HelloResponse; +import org.springframework.ws.server.endpoint.annotation.Endpoint; +import org.springframework.ws.server.endpoint.annotation.PayloadRoot; +import org.springframework.ws.server.endpoint.annotation.RequestPayload; +import org.springframework.ws.server.endpoint.annotation.ResponsePayload; +import org.springframework.ws.soap.addressing.server.annotation.Action; +import org.springframework.ws.soap.server.endpoint.annotation.SoapAction; + +@Endpoint +public class HelloEndpoint { + + private static final String NAMESPACE_URI = "http://opentelemetry.io/test/hello-web-service"; + + @PayloadRoot(namespace = NAMESPACE_URI, localPart = "helloRequest") + @ResponsePayload + public HelloResponse hello(@RequestPayload HelloRequest request) throws Exception { + return handleHello(request.getName()); + } + + @SoapAction(value = "http://opentelemetry.io/test/hello-soap-action") + @ResponsePayload + public HelloResponse helloSoapAction(@RequestPayload HelloRequestSoapAction request) + throws Exception { + return handleHello(request.getName()); + } + + @Action(value = "http://opentelemetry.io/test/hello-ws-action") + @ResponsePayload + public HelloResponse helloWsAction(@RequestPayload HelloRequestWsAction request) + throws Exception { + return handleHello(request.getName()); + } + + private static HelloResponse handleHello(String name) throws Exception { + if ("exception".equals(name)) { + throw new Exception("hello exception"); + } + HelloResponse response = new HelloResponse(); + response.setMessage("Hello " + name); + return response; + } +} diff --git a/instrumentation/spring/spring-ws-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/ws/v2_0/SpringWsTest.java b/instrumentation/spring/spring-ws-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/ws/v2_0/SpringWsTest.java new file mode 100644 index 0000000000..381549a020 --- /dev/null +++ b/instrumentation/spring/spring-ws-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/ws/v2_0/SpringWsTest.java @@ -0,0 +1,179 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.spring.ws.v2_0; + +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE; +import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_STACKTRACE; +import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_TYPE; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import com.google.common.collect.ImmutableMap; +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpServerUsingTest; +import io.opentelemetry.instrumentation.testing.junit.http.HttpServerInstrumentationExtension; +import io.opentelemetry.sdk.trace.data.StatusData; +import io.opentelemetry.semconv.incubating.CodeIncubatingAttributes; +import io.opentelemetry.test.hello_web_service.HelloRequest; +import io.opentelemetry.test.hello_web_service.HelloRequestSoapAction; +import io.opentelemetry.test.hello_web_service.HelloRequestWsAction; +import io.opentelemetry.test.hello_web_service.HelloResponse; +import java.net.URISyntaxException; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.boot.SpringApplication; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.oxm.jaxb.Jaxb2Marshaller; +import org.springframework.util.ClassUtils; +import org.springframework.ws.client.core.WebServiceMessageCallback; +import org.springframework.ws.client.core.WebServiceTemplate; +import org.springframework.ws.soap.addressing.client.ActionCallback; +import org.springframework.ws.soap.client.SoapFaultClientException; +import org.springframework.ws.soap.client.core.SoapActionCallback; + +class SpringWsTest extends AbstractHttpServerUsingTest { + + @RegisterExtension + private static final InstrumentationExtension testing = + HttpServerInstrumentationExtension.forAgent(); + + private static final Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); + + @BeforeAll + void setup() { + startServer(); + } + + @AfterAll + void cleanup() { + cleanupServer(); + } + + @Override + protected ConfigurableApplicationContext setupServer() throws Exception { + SpringApplication app = new SpringApplication(AppConfig.class, WebServiceConfig.class); + app.setDefaultProperties( + ImmutableMap.of( + "server.port", + port, + "server.context-path", + getContextPath(), + "server.servlet.contextPath", + getContextPath(), + "server.error.include-message", + "always")); + marshaller.setPackagesToScan(ClassUtils.getPackageName(HelloRequest.class)); + marshaller.afterPropertiesSet(); + return app.run(); + } + + @Override + protected void stopServer(ConfigurableApplicationContext configurableApplicationContext) + throws Exception { + configurableApplicationContext.close(); + } + + @Override + protected String getContextPath() { + return "/xyz"; + } + + HelloResponse makeRequest(String methodName, String name) throws URISyntaxException { + WebServiceTemplate webServiceTemplate = new WebServiceTemplate(marshaller); + + Object request; + WebServiceMessageCallback callback = null; + if ("hello".equals(methodName)) { + HelloRequest req = new HelloRequest(); + req.setName(name); + request = req; + } else if ("helloSoapAction".equals(methodName)) { + HelloRequestSoapAction req = new HelloRequestSoapAction(); + req.setName(name); + request = req; + callback = new SoapActionCallback("http://opentelemetry.io/test/hello-soap-action"); + } else if ("helloWsAction".equals(methodName)) { + HelloRequestWsAction req = new HelloRequestWsAction(); + req.setName(name); + request = req; + callback = new ActionCallback("http://opentelemetry.io/test/hello-ws-action"); + } else { + throw new IllegalArgumentException(methodName); + } + + return (HelloResponse) + webServiceTemplate.marshalSendAndReceive( + address.resolve("ws").toString(), request, callback); + } + + @ParameterizedTest + @ValueSource(strings = {"hello", "helloSoapAction", "helloWsAction"}) + void testMethodName(String methodName) throws URISyntaxException { + HelloResponse response = makeRequest(methodName, "Test"); + + assertThat(response.getMessage()).isEqualTo("Hello Test"); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasNoParent().hasName("POST /xyz/ws/*").hasKind(SpanKind.SERVER), + span -> + span.hasParent(trace.getSpan(0)) + .hasName("HelloEndpoint." + methodName) + .hasKind(SpanKind.INTERNAL) + .hasAttributesSatisfyingExactly( + equalTo( + CodeIncubatingAttributes.CODE_NAMESPACE, + "io.opentelemetry.javaagent.instrumentation.spring.ws.v2_0.HelloEndpoint"), + equalTo(CodeIncubatingAttributes.CODE_FUNCTION, methodName)))); + } + + @ParameterizedTest + @ValueSource(strings = {"hello", "helloSoapAction", "helloWsAction"}) + void testMethodNameException(String methodName) { + assertThatThrownBy(() -> makeRequest(methodName, "exception")) + .isInstanceOf(SoapFaultClientException.class) + .hasMessage("hello exception"); + + Exception expectedException = new Exception("hello exception"); + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> + span.hasNoParent() + .hasName("POST /xyz/ws/*") + .hasKind(SpanKind.SERVER) + .hasStatus(StatusData.error()), + span -> + span.hasParent(trace.getSpan(0)) + .hasName("HelloEndpoint." + methodName) + .hasKind(SpanKind.INTERNAL) + .hasStatus(StatusData.error()) + .hasEventsSatisfyingExactly( + event -> + event + .hasName("exception") + .hasAttributesSatisfyingExactly( + equalTo( + EXCEPTION_TYPE, + expectedException.getClass().getCanonicalName()), + equalTo(EXCEPTION_MESSAGE, expectedException.getMessage()), + satisfies( + EXCEPTION_STACKTRACE, + val -> val.isInstanceOf(String.class)))) + .hasAttributesSatisfyingExactly( + equalTo( + CodeIncubatingAttributes.CODE_NAMESPACE, + "io.opentelemetry.javaagent.instrumentation.spring.ws.v2_0.HelloEndpoint"), + equalTo(CodeIncubatingAttributes.CODE_FUNCTION, methodName)))); + } +} diff --git a/instrumentation/spring/spring-ws-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/ws/v2_0/WebServiceConfig.java b/instrumentation/spring/spring-ws-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/ws/v2_0/WebServiceConfig.java new file mode 100644 index 0000000000..61dca42176 --- /dev/null +++ b/instrumentation/spring/spring-ws-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/ws/v2_0/WebServiceConfig.java @@ -0,0 +1,47 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.spring.ws.v2_0; + +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; +import org.springframework.ws.config.annotation.EnableWs; +import org.springframework.ws.config.annotation.WsConfigurerAdapter; +import org.springframework.ws.transport.http.MessageDispatcherServlet; +import org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition; +import org.springframework.xml.xsd.SimpleXsdSchema; +import org.springframework.xml.xsd.XsdSchema; + +@EnableWs +@Configuration +public class WebServiceConfig extends WsConfigurerAdapter { + + @Bean + ServletRegistrationBean messageDispatcherServlet( + ApplicationContext applicationContext) { + MessageDispatcherServlet servlet = new MessageDispatcherServlet(); + servlet.setApplicationContext(applicationContext); + servlet.setTransformWsdlLocations(true); + return new ServletRegistrationBean<>(servlet, "/ws/*"); + } + + @Bean(name = "hello") + DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema helloSchema) { + DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition(); + wsdl11Definition.setPortTypeName("HelloPort"); + wsdl11Definition.setLocationUri("/ws"); + wsdl11Definition.setTargetNamespace("http://opentelemetry.io/test/hello-web-service"); + wsdl11Definition.setSchema(helloSchema); + return wsdl11Definition; + } + + @Bean + XsdSchema helloSchema() { + return new SimpleXsdSchema(new ClassPathResource("hello.xsd")); + } +}