diff --git a/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-plugin/pom.xml b/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-plugin/pom.xml index d50747f701..14fc5539a6 100644 --- a/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-plugin/pom.xml +++ b/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-plugin/pom.xml @@ -13,13 +13,26 @@ ${project.basedir}/../../.. + true + + + + + org.springframework.boot + spring-boot-dependencies + 3.0.5 + pom + import + + + + org.springframework spring-webmvc - ${version.spring} provided @@ -38,7 +51,6 @@ com.squareup.okhttp3 okhttp - ${version.okhttp} test @@ -48,9 +60,8 @@ test - org.apache.httpcomponents - httpclient - 4.3.6 + org.apache.httpcomponents.client5 + httpclient5 test diff --git a/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-plugin/src/test/java/co/elastic/apm/agent/resttemplate/SpringRestTemplateInstrumentationTest.java b/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-plugin/src/test/java/co/elastic/apm/agent/resttemplate/SpringRestTemplateInstrumentationTest.java index 9bc79292ad..29bc51f423 100644 --- a/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-plugin/src/test/java/co/elastic/apm/agent/resttemplate/SpringRestTemplateInstrumentationTest.java +++ b/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-plugin/src/test/java/co/elastic/apm/agent/resttemplate/SpringRestTemplateInstrumentationTest.java @@ -18,6 +18,7 @@ */ package co.elastic.apm.agent.resttemplate; +import co.elastic.apm.agent.common.JvmRuntimeInfo; import co.elastic.apm.agent.httpclient.AbstractHttpClientInstrumentationTest; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -27,29 +28,52 @@ import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; -import java.util.Arrays; +import java.util.List; import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; @RunWith(Parameterized.class) public class SpringRestTemplateInstrumentationTest extends AbstractHttpClientInstrumentationTest { - private final RestTemplate restTemplate; + // Cannot directly reference RestTemplate here because it is compiled with Java 17 + private final Object restTemplate; - public SpringRestTemplateInstrumentationTest(Supplier supplier) { - restTemplate = new RestTemplate(supplier.get()); + public SpringRestTemplateInstrumentationTest(Supplier supplier) { + restTemplate = supplier.get(); } @Parameterized.Parameters() - public static Iterable> data() { - return Arrays.asList( - SimpleClientHttpRequestFactory::new, - OkHttp3ClientHttpRequestFactory::new, - HttpComponentsClientHttpRequestFactory::new); + public static Iterable> data() { + if (JvmRuntimeInfo.ofCurrentVM().getMajorVersion() >= 17) { + return Java17Code.getRestTemplateFactories(); + } else { + return List.of(); + } } @Override protected void performGet(String path) { - // note: getForEntity is only available as of Spring-web 3.0.2 - restTemplate.getForEntity(path, String.class); + Java17Code.performGet(restTemplate, path); + } + + /** + * The code is compiled with java 17 but potentially run with java 11. + * JUnit will inspect the test class, therefore it must not contain any references to java 17 code. + */ + private static class Java17Code { + public static void performGet(Object restTemplate, String path) { + // note: getForEntity is only available as of Spring-web 3.0.2 + ((RestTemplate) restTemplate).getForEntity(path, String.class); + } + + public static Iterable> getRestTemplateFactories() { + return Stream.>of( + SimpleClientHttpRequestFactory::new, + OkHttp3ClientHttpRequestFactory::new, + HttpComponentsClientHttpRequestFactory::new) + .map(fac -> (Supplier) (() -> new RestTemplate(fac.get()))) + .collect(Collectors.toList()); + } } } diff --git a/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-test/src/test/java/co/elastic/apm/agent/resttemplate/SpringRestTemplateVersionsIT.java b/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-test/src/test/java/co/elastic/apm/agent/resttemplate/SpringRestTemplateVersionsIT.java index c26a569233..cbbf5dc06c 100644 --- a/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-test/src/test/java/co/elastic/apm/agent/resttemplate/SpringRestTemplateVersionsIT.java +++ b/apm-agent-plugins/apm-spring-resttemplate/apm-spring-resttemplate-test/src/test/java/co/elastic/apm/agent/resttemplate/SpringRestTemplateVersionsIT.java @@ -83,7 +83,7 @@ void testVersion5(String version) throws Exception { @ParameterizedTest @ValueSource(strings = { - "[6.0.0,7.0.0)" // using ivy range specifier to make test against later versions + "6.0.5" }) @EnabledForJreRange(min = JRE.JAVA_17, disabledReason = "Spring 6 requires JDK 17") void testVersion6(String version) throws Exception { diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index 4aba510eaa..26369d2aee 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -28,6 +28,7 @@ runtime-attach jakartaee-jsf-app main-app-test + spring-boot-3 aws-lambda-test diff --git a/integration-tests/spring-boot-2/pom.xml b/integration-tests/spring-boot-2/pom.xml index 50a480e04a..e02355e2cc 100644 --- a/integration-tests/spring-boot-2/pom.xml +++ b/integration-tests/spring-boot-2/pom.xml @@ -21,10 +21,23 @@ - 2.1.8.RELEASE ${project.basedir}/../.. + true + + + + + org.springframework.boot + spring-boot-dependencies + 2.7.10 + pom + import + + + + ${project.groupId} @@ -57,4 +70,19 @@ + + + + maven-jar-plugin + + + + test-jar + + + + + + + diff --git a/integration-tests/spring-boot-2/spring-boot-2-base/pom.xml b/integration-tests/spring-boot-2/spring-boot-2-base/pom.xml index 96205fba37..e24073ae92 100644 --- a/integration-tests/spring-boot-2/spring-boot-2-base/pom.xml +++ b/integration-tests/spring-boot-2/spring-boot-2-base/pom.xml @@ -16,26 +16,10 @@ ${project.basedir}/../../.. - - - - maven-jar-plugin - - - - test-jar - - - - - - - org.springframework.boot spring-boot-starter-web - ${version.spring-boot} @@ -47,17 +31,14 @@ org.springframework.boot spring-boot-starter-log4j2 - ${version.spring-boot} org.springframework.boot spring-boot-starter-security - ${version.spring-boot} org.springframework.boot spring-boot-starter-test - ${version.spring-boot} diff --git a/integration-tests/spring-boot-2/spring-boot-2-base/src/test/java/co/elastic/apm/spring/boot/AbstractSpringBootTest.java b/integration-tests/spring-boot-2/spring-boot-2-base/src/test/java/co/elastic/apm/spring/boot/AbstractSpringBootTest.java index a5b5a7e5cd..3551cf1957 100644 --- a/integration-tests/spring-boot-2/spring-boot-2-base/src/test/java/co/elastic/apm/spring/boot/AbstractSpringBootTest.java +++ b/integration-tests/spring-boot-2/spring-boot-2-base/src/test/java/co/elastic/apm/spring/boot/AbstractSpringBootTest.java @@ -35,21 +35,21 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.boot.web.server.LocalServerPort; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import org.springframework.security.web.SecurityFilterChain; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.stagemonitor.configuration.ConfigurationRegistry; +import java.time.Duration; import java.util.Collections; import static org.assertj.core.api.Java6Assertions.assertThat; @@ -78,9 +78,9 @@ public static void beforeClass() { public void setUp() { doReturn(true).when(config.getConfig(ReporterConfiguration.class)).isReportSynchronously(); restTemplate = new TestRestTemplate(new RestTemplateBuilder() - .setConnectTimeout(0) - .setReadTimeout(0) - .basicAuthorization("username", "password")); + .setConnectTimeout(Duration.ZERO) + .setReadTimeout(Duration.ZERO) + .basicAuthentication("username", "password")); reporter.reset(); } @@ -106,7 +106,11 @@ public void greetingShouldReturnDefaultMessage() throws Exception { // the service.name will not be overwritten for the webapp class loader based on spring.application.name assertThat(transaction.getTraceContext().getServiceName()).isNull(); assertThat(transaction.getFrameworkName()).isEqualTo("Spring Web MVC"); - assertThat(transaction.getFrameworkVersion()).isEqualTo("5.1.9.RELEASE"); + assertThat(transaction.getFrameworkVersion()).matches(getExpectedSpringVersionRegex()); + } + + protected String getExpectedSpringVersionRegex() { + return "5\\.[0-9]+\\.[0-9]+"; } @Test @@ -122,6 +126,7 @@ public void testStaticFile() { @RestController @SpringBootApplication + @EnableWebSecurity public static class TestApp { public static void main(String[] args) { @@ -134,26 +139,22 @@ public String greeting() { return "Hello World"; } - @Configuration - @EnableWebSecurity - public class WebSecurityConfig extends WebSecurityConfigurerAdapter { - @Override - protected void configure(HttpSecurity http) throws Exception { - http.authorizeRequests() - .anyRequest().authenticated() - .and() - .httpBasic(); - } - - @Bean - @Override - public UserDetailsService userDetailsService() { - return new InMemoryUserDetailsManager(User.withDefaultPasswordEncoder() - .username("username") - .password("password") - .roles("USER") - .build()); - } + @Bean + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + http.authorizeRequests() + .anyRequest().authenticated() + .and() + .httpBasic(); + return http.build(); + } + + @Bean + public UserDetailsService userDetailsService() { + return new InMemoryUserDetailsManager(User.withDefaultPasswordEncoder() + .username("username") + .password("password") + .roles("USER") + .build()); } } diff --git a/integration-tests/spring-boot-2/spring-boot-2-jetty/pom.xml b/integration-tests/spring-boot-2/spring-boot-2-jetty/pom.xml index 08b16d03ef..0dd5a5d042 100644 --- a/integration-tests/spring-boot-2/spring-boot-2-jetty/pom.xml +++ b/integration-tests/spring-boot-2/spring-boot-2-jetty/pom.xml @@ -34,7 +34,6 @@ org.springframework.boot spring-boot-starter-jetty - ${version.spring-boot} diff --git a/integration-tests/spring-boot-2/spring-boot-2-undertow/pom.xml b/integration-tests/spring-boot-2/spring-boot-2-undertow/pom.xml index d7af2b6c85..bda6b56e52 100644 --- a/integration-tests/spring-boot-2/spring-boot-2-undertow/pom.xml +++ b/integration-tests/spring-boot-2/spring-boot-2-undertow/pom.xml @@ -34,7 +34,6 @@ org.springframework.boot spring-boot-starter-undertow - ${version.spring-boot} diff --git a/integration-tests/spring-boot-3/pom.xml b/integration-tests/spring-boot-3/pom.xml new file mode 100644 index 0000000000..cb414d037e --- /dev/null +++ b/integration-tests/spring-boot-3/pom.xml @@ -0,0 +1,72 @@ + + + 4.0.0 + + + integration-tests + co.elastic.apm + 1.38.1-SNAPSHOT + + + spring-boot-3 + pom + + ${project.groupId}:${project.artifactId} + + + spring-boot-3-jetty + spring-boot-3-tomcat + spring-boot-3-undertow + + + + ${project.basedir}/../.. + true + + + + + + + org.springframework.boot + spring-boot-dependencies + 3.0.5 + pom + import + + + + + + + ${project.groupId} + apm-agent-core + test-jar + ${project.version} + test + + + + ${project.groupId} + apm-spring-webmvc-plugin + ${project.version} + + + ${project.groupId} + apm-servlet-plugin + ${project.version} + + + ${project.groupId} + apm-api-plugin + ${project.version} + + + ${project.groupId} + apm-agent-api + ${project.version} + test + + + diff --git a/integration-tests/spring-boot-3/spring-boot-3-jetty/pom.xml b/integration-tests/spring-boot-3/spring-boot-3-jetty/pom.xml new file mode 100644 index 0000000000..9a96c587f5 --- /dev/null +++ b/integration-tests/spring-boot-3/spring-boot-3-jetty/pom.xml @@ -0,0 +1,49 @@ + + + + spring-boot-3 + co.elastic.apm + 1.38.1-SNAPSHOT + + 4.0.0 + + spring-boot-3-jetty + + ${project.groupId}:${project.artifactId} + + + ${project.basedir}/../../.. + + + + + jakarta.servlet + jakarta.servlet-api + 5.0.0 + + + ${project.groupId} + spring-boot-2-base + ${project.version} + test-jar + test + + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + ${project.groupId} + spring-boot-2-jetty + ${project.version} + test-jar + test + + + + diff --git a/integration-tests/spring-boot-3/spring-boot-3-jetty/src/test/java/co/elastic/apm/spring/boot/SpringBoot3JettyIT.java b/integration-tests/spring-boot-3/spring-boot-3-jetty/src/test/java/co/elastic/apm/spring/boot/SpringBoot3JettyIT.java new file mode 100644 index 0000000000..fb5fdc0c30 --- /dev/null +++ b/integration-tests/spring-boot-3/spring-boot-3-jetty/src/test/java/co/elastic/apm/spring/boot/SpringBoot3JettyIT.java @@ -0,0 +1,27 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you 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 co.elastic.apm.spring.boot; + +public class SpringBoot3JettyIT extends SpringBootJettyIT { + + @Override + protected String getExpectedSpringVersionRegex() { + return "6\\.[0-9]+\\.[0-9]+"; + } +} diff --git a/integration-tests/spring-boot-3/spring-boot-3-tomcat/pom.xml b/integration-tests/spring-boot-3/spring-boot-3-tomcat/pom.xml new file mode 100644 index 0000000000..8db3b92a24 --- /dev/null +++ b/integration-tests/spring-boot-3/spring-boot-3-tomcat/pom.xml @@ -0,0 +1,37 @@ + + + + spring-boot-3 + co.elastic.apm + 1.38.1-SNAPSHOT + + 4.0.0 + + spring-boot-3-tomcat + + ${project.groupId}:${project.artifactId} + + + ${project.basedir}/../../.. + + + + + ${project.groupId} + spring-boot-2-base + ${project.version} + test-jar + test + + + ${project.groupId} + spring-boot-2-tomcat + ${project.version} + test-jar + test + + + + diff --git a/integration-tests/spring-boot-3/spring-boot-3-tomcat/src/test/java/co/elastic/apm/spring/boot/SpringBoot3TomcatIT.java b/integration-tests/spring-boot-3/spring-boot-3-tomcat/src/test/java/co/elastic/apm/spring/boot/SpringBoot3TomcatIT.java new file mode 100644 index 0000000000..dc0798243b --- /dev/null +++ b/integration-tests/spring-boot-3/spring-boot-3-tomcat/src/test/java/co/elastic/apm/spring/boot/SpringBoot3TomcatIT.java @@ -0,0 +1,27 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you 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 co.elastic.apm.spring.boot; + +public class SpringBoot3TomcatIT extends SpringBootTomcatIT { + + @Override + protected String getExpectedSpringVersionRegex() { + return "6\\.[0-9]+\\.[0-9]+"; + } +} diff --git a/integration-tests/spring-boot-3/spring-boot-3-undertow/pom.xml b/integration-tests/spring-boot-3/spring-boot-3-undertow/pom.xml new file mode 100644 index 0000000000..edde6f8d79 --- /dev/null +++ b/integration-tests/spring-boot-3/spring-boot-3-undertow/pom.xml @@ -0,0 +1,44 @@ + + + + spring-boot-3 + co.elastic.apm + 1.38.1-SNAPSHOT + + 4.0.0 + + spring-boot-3-undertow + + ${project.groupId}:${project.artifactId} + + + ${project.basedir}/../../.. + + + + + ${project.groupId} + spring-boot-2-base + ${project.version} + test-jar + test + + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + ${project.groupId} + spring-boot-2-undertow + ${project.version} + test-jar + test + + + + diff --git a/integration-tests/spring-boot-3/spring-boot-3-undertow/src/test/java/co/elastic/apm/spring/boot/SpringBoot3UndertowIT.java b/integration-tests/spring-boot-3/spring-boot-3-undertow/src/test/java/co/elastic/apm/spring/boot/SpringBoot3UndertowIT.java new file mode 100644 index 0000000000..41320c3a5c --- /dev/null +++ b/integration-tests/spring-boot-3/spring-boot-3-undertow/src/test/java/co/elastic/apm/spring/boot/SpringBoot3UndertowIT.java @@ -0,0 +1,27 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you 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 co.elastic.apm.spring.boot; + +public class SpringBoot3UndertowIT extends SpringBootUndertowIT { + + @Override + protected String getExpectedSpringVersionRegex() { + return "6\\.[0-9]+\\.[0-9]+"; + } +}