From 65d52416997bec1939262f4bf1197f8b6b9fb65c Mon Sep 17 00:00:00 2001 From: Derek Henscheid Date: Tue, 20 Jan 2026 13:56:01 -0600 Subject: [PATCH] moved "property" calls on Jersey APIs - Mutating the client (which property calls do) after creation, changes the ClientConfig mode to RequestScoped. This forces Jersey to reinitialize the injection scope with each request, which degrades performance when many API calls are made --- pom.xml | 2 +- .../org/gitlab4j/api/GitLabApiClient.java | 75 +++++++------------ 2 files changed, 27 insertions(+), 50 deletions(-) diff --git a/pom.xml b/pom.xml index 9af847a97..2ba3a0feb 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ org.gitlab4j gitlab4j-api jar - 5.0.1 + 5.0.2 GitLab4J-API - GitLab API Java Client GitLab4J-API (gitlab4j-api) provides a full featured Java client library for working with GitLab repositories and servers via the GitLab REST API. https://github.com/gitlab4j/gitlab4j-api diff --git a/src/main/java/org/gitlab4j/api/GitLabApiClient.java b/src/main/java/org/gitlab4j/api/GitLabApiClient.java index 3322e8ba1..8c0ed92af 100755 --- a/src/main/java/org/gitlab4j/api/GitLabApiClient.java +++ b/src/main/java/org/gitlab4j/api/GitLabApiClient.java @@ -1,5 +1,21 @@ package org.gitlab4j.api; +import org.gitlab4j.api.Constants.TokenType; +import org.gitlab4j.api.GitLabApi.ApiVersion; +import org.gitlab4j.api.utils.JacksonJson; +import org.gitlab4j.api.utils.MaskingLoggingFilter; +import org.glassfish.jersey.apache.connector.ApacheConnectorProvider; +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.JerseyClientBuilder; +import org.glassfish.jersey.jackson.JacksonFeature; +import org.glassfish.jersey.media.multipart.*; +import org.glassfish.jersey.media.multipart.file.FileDataBodyPart; +import org.glassfish.jersey.media.multipart.file.StreamDataBodyPart; + +import javax.net.ssl.*; +import javax.ws.rs.client.*; +import javax.ws.rs.core.*; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -14,38 +30,6 @@ import java.util.function.Supplier; import java.util.logging.Level; import java.util.logging.Logger; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLSession; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509ExtendedTrustManager; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.Entity; -import javax.ws.rs.client.Invocation; -import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.Form; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.StreamingOutput; -import org.gitlab4j.api.Constants.TokenType; -import org.gitlab4j.api.GitLabApi.ApiVersion; -import org.gitlab4j.api.utils.JacksonJson; -import org.gitlab4j.api.utils.MaskingLoggingFilter; -import org.glassfish.jersey.apache.connector.ApacheConnectorProvider; -import org.glassfish.jersey.client.ClientConfig; -import org.glassfish.jersey.client.ClientProperties; -import org.glassfish.jersey.client.JerseyClientBuilder; -import org.glassfish.jersey.jackson.JacksonFeature; -import org.glassfish.jersey.media.multipart.BodyPart; -import org.glassfish.jersey.media.multipart.Boundary; -import org.glassfish.jersey.media.multipart.FormDataMultiPart; -import org.glassfish.jersey.media.multipart.MultiPart; -import org.glassfish.jersey.media.multipart.MultiPartFeature; -import org.glassfish.jersey.media.multipart.file.FileDataBodyPart; -import org.glassfish.jersey.media.multipart.file.StreamDataBodyPart; /** @@ -69,9 +53,6 @@ public class GitLabApiClient implements AutoCloseable { private SSLContext openSslContext; private HostnameVerifier openHostnameVerifier; private Long sudoAsId; - private Integer connectTimeout; - private Integer readTimeout; - /** * Construct an instance to communicate with a GitLab API server using the specified GitLab API version, * server URL, private token, and secret token. @@ -243,6 +224,7 @@ public GitLabApiClient(ApiVersion apiVersion, String hostUrl, TokenType tokenTyp // to use the features and services explicitly configured by gitlab4j clientConfig.property(ClientProperties.FEATURE_AUTO_DISCOVERY_DISABLE, true); clientConfig.property(ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE, true); + clientConfig.property(ClientProperties.FOLLOW_REDIRECTS, true); clientConfig.register(JacksonJson.class); clientConfig.register(JacksonFeature.class); @@ -264,7 +246,7 @@ public void close() { * * @param logger the Logger instance to log to * @param level the logging level (SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST) - * @param maxEntitySize maximum number of entity bytes to be logged. When logging if the maxEntitySize + * @param maxEntityLength maximum number of entity bytes to be logged. When logging if the maxEntitySize * is reached, the entity logging will be truncated at maxEntitySize and "...more..." will be added at * the end of the log entry. If maxEntitySize is <= 0, entity logging will be disabled * @param maskedHeaderNames a list of header names that should have the values masked @@ -287,8 +269,13 @@ void enableRequestResponseLogging(Logger logger, Level level, int maxEntityLengt * @param readTimeout the per request read timeout in milliseconds, can be null to use default */ void setRequestTimeout(Integer connectTimeout, Integer readTimeout) { - this.connectTimeout = connectTimeout; - this.readTimeout = readTimeout; + clientConfig.property(ClientProperties.CONNECT_TIMEOUT, connectTimeout); + clientConfig.property(ClientProperties.READ_TIMEOUT, readTimeout); + + // Recreate the Client instance if already created. + if (apiClient != null) { + createApiClient(); + } } /** @@ -796,7 +783,7 @@ protected Invocation.Builder invocation(URL url, MultivaluedMap createApiClient(); } - WebTarget target = apiClient.target(url.toExternalForm()).property(ClientProperties.FOLLOW_REDIRECTS, true); + WebTarget target = apiClient.target(url.toExternalForm()); if (queryParams != null) { for (Map.Entry> param : queryParams.entrySet()) { target = target.queryParam(param.getKey(), param.getValue().toArray()); @@ -816,16 +803,6 @@ protected Invocation.Builder invocation(URL url, MultivaluedMap if (sudoAsId != null && sudoAsId.intValue() > 0) builder = builder.header(SUDO_HEADER, sudoAsId); - // Set the per request connect timeout - if (connectTimeout != null) { - builder.property(ClientProperties.CONNECT_TIMEOUT, connectTimeout); - } - - // Set the per request read timeout - if (readTimeout != null) { - builder.property(ClientProperties.READ_TIMEOUT, readTimeout); - } - return (builder); }