Skip to content

Commit 40cea5e

Browse files
authored
Test earliest spring boot version (#11474)
1 parent e07ef6f commit 40cea5e

File tree

24 files changed

+246
-58
lines changed

24 files changed

+246
-58
lines changed

.github/renovate.json5

+3-1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@
104104
},
105105
{
106106
// intentionally using Spring Boot 2 in this smoke tests
107+
// new versions of Spring Boot 3 are tested with
108+
// https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/dc4330e0a3060bd7d8c4090ad0b8fc4727e68113/settings.gradle.kts#L43-L45
107109
"matchFileNames": [
108110
"smoke-tests/images/spring-boot/build.gradle.kts",
109111
"smoke-tests-otel-starter/spring-boot-2/build.gradle.kts",
@@ -116,7 +118,7 @@
116118
"org.slf4j:slf4j-api",
117119
"org.springframework.boot",
118120
"org.springframework.boot:spring-boot-dependencies"],
119-
"matchUpdateTypes": ["major"],
121+
"matchUpdateTypes": ["major", "minor"],
120122
"enabled": false,
121123
},
122124
{

.github/workflows/native-tests-daily.yml

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ on:
99
jobs:
1010
graalvm-native-tests:
1111
uses: ./.github/workflows/reusable-native-tests.yml
12+
with:
13+
test-latest-deps: true
1214

1315
workflow-notification:
1416
needs:

.github/workflows/reusable-native-tests.yml

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ on:
66
skip-native-tests:
77
type: boolean
88
required: false
9+
test-latest-deps:
10+
type: boolean
11+
required: false
912

1013
jobs:
1114
graalvm-native-tests:
@@ -32,5 +35,5 @@ jobs:
3235
# therefore we're starting a Kafka container manually for the tests
3336
docker compose -f .github/graal-native-docker-compose.yaml up -d
3437
# don't wait for startup - gradle compile takes long enough
35-
./gradlew nativeTest
38+
./gradlew ${{ inputs.test-latest-deps && '-PtestLatestDeps=true' || '' }} nativeTest
3639
docker compose -f .github/graal-native-docker-compose.yaml down # is this needed?

dependencyManagement/build.gradle.kts

-2
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,6 @@ val DEPENDENCIES = listOf(
113113
"org.codehaus.mojo:animal-sniffer-annotations:1.23",
114114
"org.junit-pioneer:junit-pioneer:1.9.1",
115115
"org.objenesis:objenesis:3.4",
116-
// Note that this is only referenced as "org.springframework.boot" in build files, not the artifact name.
117-
"org.springframework.boot:spring-boot-dependencies:2.7.18",
118116
"javax.validation:validation-api:2.0.1.Final",
119117
"org.snakeyaml:snakeyaml-engine:2.7"
120118
)

instrumentation/spring/spring-boot-autoconfigure/build.gradle.kts

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ plugins {
66
base.archivesName.set("opentelemetry-spring-boot")
77
group = "io.opentelemetry.instrumentation"
88

9-
val versions: Map<String, String> by project
10-
val springBootVersion = versions["org.springframework.boot"]
9+
val springBootVersion = "2.7.18" // AutoConfiguration is added in 2.7.0, but can be used with older versions
1110

1211
// r2dbc-proxy is shadowed to prevent org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration
1312
// from being loaded by Spring Boot (by the presence of META-INF/services/io.r2dbc.spi.ConnectionFactoryProvider) - even if the user doesn't want to use R2DBC.
@@ -22,7 +21,7 @@ sourceSets {
2221
}
2322

2423
dependencies {
25-
implementation("org.springframework.boot:spring-boot-autoconfigure:$springBootVersion")
24+
compileOnly("org.springframework.boot:spring-boot-autoconfigure:$springBootVersion")
2625
annotationProcessor("org.springframework.boot:spring-boot-autoconfigure-processor:$springBootVersion")
2726
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor:$springBootVersion")
2827
implementation("javax.validation:validation-api")

instrumentation/spring/spring-webmvc/spring-webmvc-5.3/library/build.gradle.kts

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ plugins {
22
id("otel.library-instrumentation")
33
}
44

5-
val versions: Map<String, String> by project
6-
val springBootVersion = versions["org.springframework.boot"]
5+
val springBootVersion = "2.6.15"
76

87
dependencies {
98
compileOnly("org.springframework:spring-webmvc:5.3.0")

instrumentation/spring/starters/spring-boot-starter/build.gradle.kts

+3-4
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ plugins {
55

66
group = "io.opentelemetry.instrumentation"
77

8-
val versions: Map<String, String> by project
9-
val springBootVersion = versions["org.springframework.boot"]
8+
val springBootVersion = "2.6.15"
109

1110
dependencies {
12-
api("org.springframework.boot:spring-boot-starter:$springBootVersion")
13-
api("org.springframework.boot:spring-boot-starter-aop:$springBootVersion")
11+
compileOnly("org.springframework.boot:spring-boot-starter:$springBootVersion")
12+
compileOnly("org.springframework.boot:spring-boot-starter-aop:$springBootVersion")
1413
api(project(":instrumentation:spring:spring-boot-autoconfigure"))
1514
api(project(":instrumentation:spring:spring-boot-autoconfigure-3"))
1615
api(project(":instrumentation-annotations"))

instrumentation/spring/starters/zipkin-spring-boot-starter/build.gradle.kts

+1-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ plugins {
55

66
group = "io.opentelemetry.instrumentation"
77

8-
val versions: Map<String, String> by project
9-
val springBootVersion = versions["org.springframework.boot"]
8+
val springBootVersion = "2.6.15"
109

1110
dependencies {
1211
api("org.springframework.boot:spring-boot-starter:$springBootVersion")

settings.gradle.kts

+18
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,23 @@ dependencyResolutionManagement {
2828
mavenCentral()
2929
mavenLocal()
3030
}
31+
32+
versionCatalogs {
33+
fun addSpringBootCatalog(name: String, minVersion: String, maxVersion: String) {
34+
val latestDepTest = gradle.startParameter.projectProperties["testLatestDeps"] == "true"
35+
create(name) {
36+
val version =
37+
gradle.startParameter.projectProperties["${name}Version"]
38+
?: (if (latestDepTest) maxVersion else minVersion)
39+
plugin("versions", "org.springframework.boot").version(version)
40+
}
41+
}
42+
// r2dbc is not compatible with earlier versions
43+
addSpringBootCatalog("springBoot2", "2.6.15", "2.+")
44+
// spring boot 3.0 is not compatible with graalvm native image
45+
addSpringBootCatalog("springBoot31", "3.1.0", "3.+")
46+
addSpringBootCatalog("springBoot32", "3.2.0", "3.+")
47+
}
3148
}
3249

3350
val gradleEnterpriseServer = "https://ge.opentelemetry.io"
@@ -141,6 +158,7 @@ include(":smoke-tests:images:spring-boot")
141158
include(":smoke-tests-otel-starter:spring-smoke-testing")
142159
include(":smoke-tests-otel-starter:spring-boot-2")
143160
include(":smoke-tests-otel-starter:spring-boot-3")
161+
include(":smoke-tests-otel-starter:spring-boot-3.2")
144162
include(":smoke-tests-otel-starter:spring-boot-common")
145163
include(":smoke-tests-otel-starter:spring-boot-reactive-2")
146164
include(":smoke-tests-otel-starter:spring-boot-reactive-3")

smoke-tests-otel-starter/spring-boot-2/build.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
plugins {
22
id("otel.java-conventions")
3-
id("org.springframework.boot") version "2.7.18"
3+
alias(springBoot2.plugins.versions)
44
}
55

66
description = "smoke-tests-otel-starter-spring-boot-2"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
plugins {
2+
id("otel.java-conventions")
3+
alias(springBoot32.plugins.versions)
4+
id("org.graalvm.buildtools.native")
5+
}
6+
7+
description = "smoke-tests-otel-starter-spring-boot-3.2"
8+
9+
otelJava {
10+
minJavaVersionSupported.set(JavaVersion.VERSION_17)
11+
}
12+
13+
dependencies {
14+
implementation("org.springframework.boot:spring-boot-starter-web")
15+
implementation("org.springframework.boot:spring-boot-starter-data-jdbc")
16+
runtimeOnly("com.h2database:h2")
17+
implementation("org.apache.commons:commons-dbcp2")
18+
implementation("org.springframework.kafka:spring-kafka")
19+
implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
20+
implementation(platform(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES))
21+
22+
implementation(project(":smoke-tests-otel-starter:spring-boot-common"))
23+
testImplementation("org.springframework.boot:spring-boot-starter-test")
24+
}
25+
26+
springBoot {
27+
mainClass = "io.opentelemetry.spring.smoketest.OtelSpringStarterSmokeTestApplication"
28+
}
29+
30+
tasks {
31+
compileAotJava {
32+
with(options) {
33+
compilerArgs.add("-Xlint:-deprecation,-unchecked,none")
34+
// To disable warnings/failure coming from the Java compiler during the Spring AOT processing
35+
// -deprecation,-unchecked and none are required (none is not enough)
36+
}
37+
}
38+
compileAotTestJava {
39+
with(options) {
40+
compilerArgs.add("-Xlint:-deprecation,-unchecked,none")
41+
// To disable warnings/failure coming from the Java compiler during the Spring AOT processing
42+
// -deprecation,-unchecked and none are required (none is not enough)
43+
}
44+
}
45+
checkstyleAot {
46+
isEnabled = false
47+
}
48+
checkstyleAotTest {
49+
isEnabled = false
50+
}
51+
}
52+
53+
// To be able to execute the tests as GraalVM native executables
54+
configurations.configureEach {
55+
exclude("org.apache.groovy", "groovy")
56+
exclude("org.apache.groovy", "groovy-json")
57+
exclude("org.spockframework", "spock-core")
58+
}
59+
60+
graalvmNative {
61+
binaries.all {
62+
// Workaround for https://github.com/junit-team/junit5/issues/3405
63+
buildArgs.add("--initialize-at-build-time=org.junit.platform.launcher.core.LauncherConfig")
64+
buildArgs.add("--initialize-at-build-time=org.junit.jupiter.engine.config.InstantiatingConfigurationParameterConverter")
65+
}
66+
67+
// See https://github.com/graalvm/native-build-tools/issues/572
68+
metadataRepository {
69+
enabled.set(false)
70+
}
71+
72+
tasks.test {
73+
useJUnitPlatform()
74+
setForkEvery(1)
75+
}
76+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.spring.smoketest;
7+
8+
import org.springframework.boot.SpringApplication;
9+
import org.springframework.boot.autoconfigure.SpringBootApplication;
10+
import org.springframework.context.annotation.ImportRuntimeHints;
11+
12+
@SpringBootApplication
13+
@ImportRuntimeHints(RuntimeHints.class)
14+
public class OtelSpringStarterSmokeTestApplication {
15+
16+
public OtelSpringStarterSmokeTestApplication() {}
17+
18+
public static void main(String[] args) {
19+
SpringApplication.run(OtelSpringStarterSmokeTestApplication.class);
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.spring.smoketest;
7+
8+
import org.springframework.aot.hint.MemberCategory;
9+
import org.springframework.aot.hint.RuntimeHintsRegistrar;
10+
import org.springframework.aot.hint.TypeReference;
11+
12+
// Necessary for GraalVM native test
13+
public class RuntimeHints implements RuntimeHintsRegistrar {
14+
15+
@Override
16+
public void registerHints(
17+
org.springframework.aot.hint.RuntimeHints hints, ClassLoader classLoader) {
18+
hints.resources().registerResourceBundle("org.apache.commons.dbcp2.LocalStrings");
19+
20+
// To avoid Spring native issue with MongoDB: java.lang.ClassNotFoundException:
21+
// org.springframework.data.mongodb.core.aggregation.AggregationOperation
22+
hints
23+
.reflection()
24+
.registerType(
25+
TypeReference.of(
26+
"org.springframework.data.mongodb.core.aggregation.AggregationOperation"),
27+
hint -> {
28+
hint.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
29+
});
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.spring.smoketest;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
10+
import io.opentelemetry.api.trace.SpanKind;
11+
import io.opentelemetry.sdk.testing.assertj.TraceAssert;
12+
import io.opentelemetry.semconv.HttpAttributes;
13+
import io.opentelemetry.semconv.UrlAttributes;
14+
import org.junit.jupiter.api.Test;
15+
import org.springframework.beans.factory.annotation.Autowired;
16+
import org.springframework.boot.test.context.SpringBootTest;
17+
import org.springframework.boot.test.web.server.LocalServerPort;
18+
import org.springframework.web.client.RestClient;
19+
20+
@SpringBootTest(
21+
classes = {
22+
OtelSpringStarterSmokeTestApplication.class,
23+
AbstractOtelSpringStarterSmokeTest.TestConfiguration.class,
24+
SpringSmokeOtelConfiguration.class
25+
},
26+
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
27+
class OtelSpringStarterSmokeTest extends AbstractSpringStarterSmokeTest {
28+
29+
@Autowired RestClient.Builder restClientBuilder;
30+
@LocalServerPort private int port;
31+
32+
@Test
33+
void restClient() {
34+
testing.clearAllExportedData();
35+
36+
RestClient client = restClientBuilder.baseUrl("http://localhost:" + port).build();
37+
assertThat(
38+
client
39+
.get()
40+
.uri(OtelSpringStarterSmokeTestController.PING)
41+
.retrieve()
42+
.body(String.class))
43+
.isEqualTo("pong");
44+
45+
if (System.getProperty("org.graalvm.nativeimage.imagecode") != null) {
46+
// ignore the trace for creating the db table
47+
testing.waitAndAssertTraces(trace -> {}, OtelSpringStarterSmokeTest::assertClient);
48+
} else {
49+
testing.waitAndAssertTraces(OtelSpringStarterSmokeTest::assertClient);
50+
}
51+
}
52+
53+
private static void assertClient(TraceAssert traceAssert) {
54+
traceAssert.hasSpansSatisfyingExactly(
55+
nestedClientSpan ->
56+
nestedClientSpan
57+
.hasKind(SpanKind.CLIENT)
58+
.hasAttributesSatisfying(
59+
a -> assertThat(a.get(UrlAttributes.URL_FULL)).endsWith("/ping")),
60+
nestedServerSpan ->
61+
nestedServerSpan
62+
.hasKind(SpanKind.SERVER)
63+
.hasAttribute(HttpAttributes.HTTP_ROUTE, "/ping"));
64+
}
65+
}

smoke-tests-otel-starter/spring-boot-3/build.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
plugins {
22
id("otel.java-conventions")
3-
id("org.springframework.boot") version "3.3.0"
3+
alias(springBoot31.plugins.versions)
44
id("org.graalvm.buildtools.native")
55
}
66

smoke-tests-otel-starter/spring-boot-3/src/test/java/io/opentelemetry/spring/smoketest/OtelSpringStarterSmokeTest.java

+1-26
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,7 @@
55

66
package io.opentelemetry.spring.smoketest;
77

8-
import static org.assertj.core.api.Assertions.assertThat;
9-
10-
import org.junit.jupiter.api.Test;
11-
import org.springframework.beans.factory.annotation.Autowired;
128
import org.springframework.boot.test.context.SpringBootTest;
13-
import org.springframework.boot.test.web.server.LocalServerPort;
14-
import org.springframework.web.client.RestClient;
159

1610
@SpringBootTest(
1711
classes = {
@@ -24,23 +18,4 @@
2418
// The headers are simply set here to make sure that headers can be parsed
2519
"otel.exporter.otlp.headers.c=3"
2620
})
27-
class OtelSpringStarterSmokeTest extends AbstractOtelSpringStarterSmokeTest {
28-
29-
@Autowired RestClient.Builder restClientBuilder;
30-
@LocalServerPort private int port;
31-
32-
@Test
33-
void restClient() {
34-
testing.clearAllExportedData();
35-
36-
RestClient client = restClientBuilder.baseUrl("http://localhost:" + port).build();
37-
assertThat(
38-
client
39-
.get()
40-
.uri(OtelSpringStarterSmokeTestController.PING)
41-
.retrieve()
42-
.body(String.class))
43-
.isEqualTo("pong");
44-
assertClient();
45-
}
46-
}
21+
class OtelSpringStarterSmokeTest extends AbstractOtelSpringStarterSmokeTest {}

0 commit comments

Comments
 (0)