Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
15ab020
Avoid dependency on return type incompatible with spring-web 6.x
eyalkoren Dec 25, 2022
6e14086
Adding separate module for each spring-web version
eyalkoren Dec 26, 2022
2c06834
Loading spring-web 5 class also only by name when necessary
eyalkoren Dec 26, 2022
a1bb0e1
Removing specific java version directives
eyalkoren Dec 27, 2022
c418c13
Compile Spring 6.x module with Java 17
eyalkoren Dec 27, 2022
8cdf630
Restoring defaults
eyalkoren Dec 27, 2022
5eb4cbc
Upgrade animal-sniffer plugin
eyalkoren Dec 27, 2022
16621b4
Switching to Java 17 on CI
eyalkoren Dec 27, 2022
705aee2
Restore older animal-sniffer version
eyalkoren Dec 27, 2022
5eccbe8
Disabled animal-sniffer for module
eyalkoren Dec 27, 2022
e575012
Compatibility tests with JDKs 11 and 19
eyalkoren Dec 28, 2022
8b4898d
Merge remote-tracking branch 'upstream/main' into WebFlux-with-spring…
eyalkoren Dec 28, 2022
4e6fa89
Using a separate module and profiles for Java 17
eyalkoren Dec 29, 2022
c18becd
Removing a test which is dependent on build order
eyalkoren Dec 30, 2022
1cecd1d
Move Version.class to the proper package
eyalkoren Jan 3, 2023
38e1602
Fix Compatibility JDKs stage
eyalkoren Jan 3, 2023
c8c83ab
Restore single line in Jenkinsfile
eyalkoren Jan 3, 2023
5c475f9
Use Oracle instead of OpenJDK for Java 11 test
eyalkoren Jan 3, 2023
5a434e7
Enable build on JDK 19
eyalkoren Jan 4, 2023
0761d32
Merge remote-tracking branch 'upstream/main' into WebFlux-with-spring…
eyalkoren Jan 4, 2023
8017cef
Merge remote-tracking branch 'upstream/main' into WebFlux-with-spring…
eyalkoren Jan 23, 2023
31ab688
Logging response code fetch error
eyalkoren Jan 23, 2023
a68fe5a
Add to CHANGELOG
eyalkoren Jan 23, 2023
8ef82a6
fix wrong import from merging
eyalkoren Jan 23, 2023
54a7eed
Merge remote-tracking branch 'upstream/main' into WebFlux-with-spring…
eyalkoren Jan 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .ci/load/Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ pipeline {
echo "Switch to requested agent version = ${params.apm_version}"
sh(script: "git checkout ${params.apm_version}")

echo 'Building agent with Java 11'
sh(script: "JAVA_HOME=${env.HUDSON_HOME}/.java/java11 ./mvnw --batch-mode clean package -DskipTests=true -Dmaven.javadoc.skip=true -Dmaven.sources.skip=true")
echo 'Building agent with Java 17'
sh(script: "JAVA_HOME=${env.HUDSON_HOME}/.java/jdk17 ./mvnw --batch-mode clean package -DskipTests=true -Dmaven.javadoc.skip=true -Dmaven.sources.skip=true")

// copy agent jar to a known filename that don't change with version
sh(script: "cp -v \$(find ./elastic-apm-agent/target -name '*.jar' | grep -v sources | grep -v original | grep -v javadoc) ${WORKSPACE}/elastic-apm-agent.jar")
Expand Down
2 changes: 1 addition & 1 deletion .ci/packer_cache.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ set +e

source /usr/local/bin/bash_standard_lib.sh

retry 3 JAVA_HOME=$HOME/.java/java11 \
retry 3 JAVA_HOME=$HOME/.java/jdk17 \
./mvnw clean package \
-q -B \
-DskipTests=true \
Expand Down
2 changes: 1 addition & 1 deletion .ci/release/Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pipeline {
NEXUS_SECRET = 'secret/apm-team/ci/nexus'
MAVEN_CONFIG = '-B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -Dmaven.repo.local=.m2'
HOME = "${env.WORKSPACE}"
JAVA_HOME = "${env.HUDSON_HOME}/.java/java10"
JAVA_HOME = "${env.HUDSON_HOME}/.java/jdk17"
PATH = "${env.JAVA_HOME}/bin:${env.PATH}"
SLACK_CHANNEL = '#apm-agent-java'
NOTIFY_TO = 'build-apm+apm-agent-java@elastic.co'
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ endif::[]
* Add warning when agent is accidentally started on a JVM/JDK command-line tool - {pull}2924[#2924]
* Fix `NullPointerException` caused by the Elasticsearch REST client instrumentation when collecting dropped span metrics - {pull}2959[#2959]
* Fix SQS Instrumentation for Non-MessageReceive actions to avoid NoSuchElementException - {pull}2979[#2979]
* Fix `java.lang.NoSuchMethodError` when using the agent with WebFlux and Spring 6.x/Spring Boot 3.x - {pull}2935[#2935]

===== Potentially breaking changes

Expand Down
14 changes: 7 additions & 7 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pipeline {
issueCommentTrigger("(${obltGitHubComments()}|^run (jdk compatibility|benchmark|integration|windows) tests)")
}
parameters {
string(name: 'JAVA_VERSION', defaultValue: 'java11', description: 'Java version to build & test')
string(name: 'JAVA_VERSION', defaultValue: 'jdk17', description: 'Java version to build & test')
string(name: 'MAVEN_CONFIG', defaultValue: '-V -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -Dhttps.protocols=TLSv1.2 -Dmaven.wagon.http.retryHandler.count=3 -Dmaven.wagon.httpconnectionManager.ttlSeconds=25', description: 'Additional maven options.')

// Note about GH checks and optional steps
Expand Down Expand Up @@ -362,21 +362,21 @@ pipeline {
}
}
}
environment {
PATH = "${env.JAVA_HOME}/bin:${env.PATH}"
}
matrix {
agent { label 'linux && immutable' }
axes {
axis {
// the list of support java versions can be found in the infra repo (ansible/roles/java/defaults/main.yml)
// the list of supported java versions can be found in the infra repo (ansible/roles/java/defaults/main.yml)
name 'JDK_VERSION'
// 'openjdk18' disabled for now see https://github.com/elastic/apm-agent-java/issues/2328
values 'openjdk17'
values 'java11', 'jdk19'
}
}
stages {
stage('JDK Unit Tests') {
environment {
JAVA_HOME = "${env.HUDSON_HOME}/.java/${env.JDK_VERSION}"
PATH = "${env.JAVA_HOME}/bin:${env.PATH}"
}
steps {
withGithubNotify(context: "${STAGE_NAME} ${JDK_VERSION}", tab: 'tests') {
deleteDir()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/
package co.elastic.apm.attach;

import co.elastic.apm.agent.util.Version;
import co.elastic.apm.agent.common.util.Version;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/
package co.elastic.apm.attach;

import co.elastic.apm.agent.util.Version;
import co.elastic.apm.agent.common.util.Version;
import co.elastic.apm.attach.bouncycastle.BouncyCastleVerifier;
import org.junit.jupiter.api.Test;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package co.elastic.apm.agent.util;
package co.elastic.apm.agent.common.util;

import java.util.Arrays;
import java.util.Objects;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package co.elastic.apm.agent.util;

import co.elastic.apm.agent.common.util.Version;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import co.elastic.apm.agent.sdk.weakconcurrent.WeakConcurrent;
import co.elastic.apm.agent.sdk.weakconcurrent.WeakMap;
import co.elastic.apm.agent.util.ClassLoaderUtils;
import co.elastic.apm.agent.util.Version;
import co.elastic.apm.agent.common.util.Version;
import net.bytebuddy.description.NamedElement;
import net.bytebuddy.description.annotation.AnnotationSource;
import net.bytebuddy.description.method.MethodDescription;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import co.elastic.apm.agent.configuration.CoreConfiguration;
import co.elastic.apm.agent.report.ssl.SslUtils;
import co.elastic.apm.agent.util.UrlConnectionUtils;
import co.elastic.apm.agent.util.Version;
import co.elastic.apm.agent.common.util.Version;
import co.elastic.apm.agent.util.VersionUtils;
import co.elastic.apm.agent.sdk.logging.Logger;
import co.elastic.apm.agent.sdk.logging.LoggerFactory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
package co.elastic.apm.agent.report;

import co.elastic.apm.agent.util.ExecutorUtils;
import co.elastic.apm.agent.util.Version;
import co.elastic.apm.agent.common.util.Version;
import com.dslplatform.json.DslJson;
import com.dslplatform.json.JsonReader;
import com.dslplatform.json.Nullable;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* 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.agent.springwebflux;

import javax.annotation.Nullable;

/**
* This class must be located within the same package as used by the WebFlux instrumentation, otherwise it will be loaded by the
* agent class loader, rather than the WebFlux plugin class loader. If the {@link ISpringWebVersionUtils} implementations are loaded
* anywhere other than the WebFlux plugin class loader, their loading will cause a {@link LinkageError}.
*/
public class SpringWebVersionUtils {

private static final String SPRING_WEB_5_UTILS_CLASS_NAME = "co.elastic.apm.agent.springwebflux.SpringWeb5Utils";
private static final String SPRING_WEB_6_UTILS_CLASS_NAME = "co.elastic.apm.agent.springwebflux.SpringWeb6Utils";

@Nullable
private static ISpringWebVersionUtils instance = null;

private static volatile boolean initialized = false;

private static synchronized void initialize() throws Exception {
if (initialized) {
return;
}
try {
// check if using spring 6.0.0 or higher
Class.forName("org.springframework.http.HttpStatusCode");
try {
// loading class by name so to avoid linkage attempt when spring-web 6 is unavailable
instance = (ISpringWebVersionUtils) Class.forName(SPRING_WEB_6_UTILS_CLASS_NAME).getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new IllegalStateException("Spring-web 6.x+ identified, but failed to load related utility class", e);
}
} catch (ClassNotFoundException ignored) {
// assuming spring-web < 6.x
try {
// loading class by name so to avoid linkage attempt on spring-web 6, where the getStatusCode API has changed
instance = (ISpringWebVersionUtils) Class.forName(SPRING_WEB_5_UTILS_CLASS_NAME).getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new IllegalStateException("Spring-web < 6.x identified, but failed to load related utility class", e);
}
} finally {
initialized = true;
}
}

@Nullable
private static ISpringWebVersionUtils getImplementation() throws Exception {
if (!initialized) {
initialize();
}
return instance;
}

/**
* A utility method to get the status code of a {@code org.springframework.http.server.reactive.ServerHttpResponse} from any version
* of Spring framework.
*
* @param response must be of type {@code org.springframework.http.server.reactive.ServerHttpResponse}, otherwise an Exception is
* expected
* @return the status code of the provided response
*/
public static int getStatusCode(Object response) throws Exception {
ISpringWebVersionUtils implementation = getImplementation();
if (implementation != null) {
return implementation.getStatusCode(response);
}
return 200;
}

public interface ISpringWebVersionUtils {
/**
* A utility method to get the status code of a {@code org.springframework.http.server.reactive.ServerHttpResponse} from any version
* of Spring framework.
*
* @param response must be of type {@code org.springframework.http.server.reactive.ServerHttpResponse}
* @return the corresponding status code
*/
int getStatusCode(Object response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* 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.
*/

/**
* This package is common as it needs to be used by Spring WebFlux instrumentations from different modules (compiled by different Java
* versions). It must have the same package name as used by the WebFlux instrumentation, as it is expected to be loaded by the same
* plugin class loader that loads the WebFlux advice and helper classes.
*/
package co.elastic.apm.agent.springwebflux;

Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import co.elastic.apm.agent.objectpool.TestObjectPoolFactory;
import co.elastic.apm.agent.report.ApmServerClient;
import co.elastic.apm.agent.report.Reporter;
import co.elastic.apm.agent.util.Version;
import co.elastic.apm.agent.common.util.Version;
import org.stagemonitor.configuration.ConfigurationRegistry;

import static org.mockito.ArgumentMatchers.any;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import co.elastic.apm.agent.impl.transaction.Transaction;
import co.elastic.apm.agent.objectpool.TestObjectPoolFactory;
import co.elastic.apm.agent.objectpool.impl.BookkeeperObjectPool;
import co.elastic.apm.agent.util.Version;
import co.elastic.apm.agent.common.util.Version;
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
import org.assertj.core.util.Lists;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*/
package co.elastic.apm.agent.report;

import co.elastic.apm.agent.util.Version;
import co.elastic.apm.agent.common.util.Version;
import org.junit.jupiter.api.Test;

import java.io.IOException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
import co.elastic.apm.agent.impl.transaction.Transaction;
import co.elastic.apm.agent.report.processor.ProcessorEventHandler;
import co.elastic.apm.agent.report.serialize.DslJsonSerializer;
import co.elastic.apm.agent.util.Version;
import co.elastic.apm.agent.common.util.Version;
import com.dslplatform.json.DslJson;
import com.dslplatform.json.JsonWriter;
import com.fasterxml.jackson.databind.JsonNode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@
package co.elastic.apm.agent.util;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.junit.jupiter.api.io.TempDir;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.AccessController;
Expand All @@ -37,6 +38,7 @@
import static co.elastic.apm.agent.testutils.assertions.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

@EnabledForJreRange(max = JRE.JAVA_17, disabledReason = "SecurityManager is not supported anymore")
class PrivilegedActionUtilsTest {

private static final AtomicBoolean enabled = new AtomicBoolean(false);
Expand Down
38 changes: 38 additions & 0 deletions apm-agent-java-17/apm-agent-spring-6/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>co.elastic.apm</groupId>
<artifactId>apm-agent-java-17</artifactId>
<version>1.35.1-SNAPSHOT</version>
</parent>

<artifactId>apm-agent-spring-6</artifactId>
<name>${project.groupId}:${project.artifactId}</name>
<properties>
<!-- for licence header plugin -->
<apm-agent-parent.base.dir>${project.basedir}/../..</apm-agent-parent.base.dir>
</properties>

<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>apm-agent-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>6.0.1</version>
<scope>provided</scope>
</dependency>
<!-- required for the creation of a mock response -->
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.2.0.RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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.agent.springwebflux;

import org.springframework.http.HttpStatusCode;
import org.springframework.http.server.reactive.ServerHttpResponse;

/**
* This class is compiled with spring-web 6.x, as it relies on {@link HttpStatusCode} and an API that was introduced in 6.0.0.
* Therefore, it MUST only be loaded through its class name through {@link SpringWebVersionUtils}.
*/
public class SpringWeb6Utils implements SpringWebVersionUtils.ISpringWebVersionUtils {
@Override
public int getStatusCode(Object response) {
HttpStatusCode statusCode = ((ServerHttpResponse) response).getStatusCode();
return statusCode != null ? statusCode.value() : 200;
}
}
Loading