actions = new ArrayList<>();
+ private int writeLen = 0;
+ private AtomicBoolean streamFlushed = new AtomicBoolean(false);
@Override
public void write(int b) throws IOException {
@@ -241,15 +240,39 @@ public void write(byte[] b) throws IOException {
@Override
public void write(byte[] b, int off, int len) throws IOException {
- if (!flushed && this.b == null) {
- this.b = b;
- this.off = off;
- this.len = len;
+ if (!flushed) {
+ actions.add(new WriteAction(b, off, len));
+ writeLen += len;
} else {
- DelayedEntityWriter.this._flush();
+ _flush();
writer.getOutputStream().write(b, off, len);
+ writer.getOutputStream().flush();
+ }
+ }
+
+ public void _flush() throws IOException {
+ if (streamFlushed.compareAndSet(false, true)) {
+ DelayedEntityWriter.this._flush();
+ for (WriteAction action : actions) {
+ action.run();
+ }
+ actions.clear();
}
}
}
+
+ private class WriteAction {
+ private final byte[] b;
+
+ private WriteAction(byte[] b, int off, int len) {
+ this.b = new byte[len]; // b passed in can be reused
+ System.arraycopy(b, off, this.b, 0, len);
+ }
+
+ public void run() throws IOException {
+ writer.getOutputStream().write(b, 0, b.length);
+ writer.getOutputStream().flush();
+ }
+ }
}
}
diff --git a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletContainer.java b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletContainer.java
index 147ce8c39e..abde2ac29f 100644
--- a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletContainer.java
+++ b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletContainer.java
@@ -318,13 +318,33 @@ private void setResponseForInvalidUri(final HttpServletResponse response, final
final Response.Status badRequest = Response.Status.BAD_REQUEST;
if (webComponent.configSetStatusOverSendError) {
response.reset();
- //noinspection deprecation
- response.setStatus(badRequest.getStatusCode(), badRequest.getReasonPhrase());
+ setStatus(response, badRequest.getStatusCode(), badRequest.getReasonPhrase());
} else {
response.sendError(badRequest.getStatusCode(), badRequest.getReasonPhrase());
}
}
+ /**
+ *
+ * Set status and reason-phrase if the API still contains the method. Otherwise, only a status is sent.
+ *
+ *
+ * It can happen the Servlet 6 API is used and the method is not there any longer. A proprietary API can be used,
+ * or the class is transformed to Jakarta using some transformer means.
+ *
+ * @param response the servlet {@link HttpServletResponse}
+ * @param statusCode the status code
+ * @param reasonPhrase the reason phrase
+ */
+ public static void setStatus(HttpServletResponse response, int statusCode, String reasonPhrase) {
+ try {
+ // noinspection deprecation
+ response.setStatus(statusCode, reasonPhrase);
+ } catch (NoSuchMethodError noSuchMethodError) {
+ response.setStatus(statusCode);
+ }
+ }
+
@Override
public void destroy() {
super.destroy();
diff --git a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/WebComponent.java b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/WebComponent.java
index 59b1da9a23..6e795f1e8a 100644
--- a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/WebComponent.java
+++ b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/WebComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -17,6 +17,8 @@
package org.glassfish.jersey.servlet;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
import java.lang.reflect.Type;
import java.net.URI;
import java.security.AccessController;
@@ -54,6 +56,7 @@
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
+import org.glassfish.jersey.innate.io.InputStreamWrapper;
import org.glassfish.jersey.internal.ServiceFinderBinder;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.internal.inject.InjectionManager;
@@ -401,8 +404,7 @@ public Integer get() {
if (configSetStatusOverSendError) {
servletResponse.reset();
- //noinspection deprecation
- servletResponse.setStatus(status.getStatusCode(), status.getReasonPhrase());
+ ServletContainer.setStatus(servletResponse, status.getStatusCode(), status.getReasonPhrase());
} else {
servletResponse.sendError(status.getStatusCode(), status.getReasonPhrase());
}
@@ -413,7 +415,7 @@ public Integer get() {
}
/**
- * Initialize {@code ContainerRequest} instance to used used to handle {@code servletRequest}.
+ * Initialize {@code ContainerRequest} instance to used to handle {@code servletRequest}.
*/
private void initContainerRequest(
final ContainerRequest requestContext,
@@ -421,7 +423,21 @@ private void initContainerRequest(
final HttpServletResponse servletResponse,
final ResponseWriter responseWriter) throws IOException {
- requestContext.setEntityStream(servletRequest.getInputStream());
+ try {
+ requestContext.setEntityStream(new InputStreamWrapper() {
+ @Override
+ protected InputStream getWrapped() {
+ try {
+ return servletRequest.getInputStream();
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+ });
+ } catch (UncheckedIOException e) {
+ throw e.getCause();
+ }
+
requestContext.setRequestScopedInitializer(requestScopedInitializer.get(new RequestContextProvider() {
@Override
public HttpServletRequest getHttpServletRequest() {
diff --git a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/internal/ResponseWriter.java b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/internal/ResponseWriter.java
index 31b8f93156..5188a1a975 100644
--- a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/internal/ResponseWriter.java
+++ b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/internal/ResponseWriter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -37,6 +37,7 @@
import org.glassfish.jersey.server.ContainerResponse;
import org.glassfish.jersey.server.internal.JerseyRequestTimeoutHandler;
import org.glassfish.jersey.server.spi.ContainerResponseWriter;
+import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.servlet.spi.AsyncContextDelegate;
/**
@@ -144,7 +145,7 @@ public OutputStream writeResponseStatusAndHeaders(final long contentLength, fina
final String reasonPhrase = responseContext.getStatusInfo().getReasonPhrase();
if (reasonPhrase != null) {
- response.setStatus(responseContext.getStatus(), reasonPhrase);
+ ServletContainer.setStatus(response, responseContext.getStatus(), reasonPhrase);
} else {
response.setStatus(responseContext.getStatus());
}
@@ -214,12 +215,12 @@ public void failure(final Throwable error) {
try {
if (!response.isCommitted()) {
try {
+ final int statusCode = Response.Status.INTERNAL_SERVER_ERROR.getStatusCode();
if (configSetStatusOverSendError) {
response.reset();
- //noinspection deprecation
- response.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), "Request failed.");
+ ServletContainer.setStatus(response, statusCode, "Request failed.");
} else {
- response.sendError(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), "Request failed.");
+ response.sendError(statusCode, "Request failed.");
}
} catch (final IllegalStateException ex) {
// a race condition externally committing the response can still occur...
diff --git a/containers/jersey-servlet-core/src/test/java/org/glassfish/jersey/servlet/internal/RequestInputStreamTest.java b/containers/jersey-servlet-core/src/test/java/org/glassfish/jersey/servlet/internal/RequestInputStreamTest.java
new file mode 100644
index 0000000000..feb899c498
--- /dev/null
+++ b/containers/jersey-servlet-core/src/test/java/org/glassfish/jersey/servlet/internal/RequestInputStreamTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.servlet.internal;
+
+import org.glassfish.jersey.CommonProperties;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerProperties;
+import org.glassfish.jersey.servlet.ServletProperties;
+import org.glassfish.jersey.servlet.WebComponent;
+import org.glassfish.jersey.servlet.WebConfig;
+import org.glassfish.jersey.servlet.WebFilterConfig;
+import org.junit.jupiter.api.Test;
+
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.net.URI;
+import java.util.Collections;
+import java.util.Enumeration;
+
+public class RequestInputStreamTest {
+ @Test
+ public void test404RequestInputStream() throws ServletException, IOException {
+ InvocationHandler handler = new InvocationHandler() {
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ switch (method.getName()) {
+ case "getHeaderNames":
+ return Collections.emptyEnumeration();
+ case "getInputStream":
+ throw new IllegalStateException("ServletRequest#getInputStream clashes with ServletRequest#getReader");
+ }
+ return null;
+ }
+ };
+
+ FilterConfig filterConfig = new FilterConfig() {
+ @Override
+ public String getFilterName() {
+ return null;
+ }
+
+ @Override
+ public ServletContext getServletContext() {
+ return (ServletContext) Proxy.newProxyInstance(getClass().getClassLoader(),
+ new Class[]{ServletContext.class},
+ handler);
+ }
+
+ @Override
+ public String getInitParameter(String name) {
+ return null;
+ }
+
+ @Override
+ public Enumeration getInitParameterNames() {
+ return null;
+ }
+ };
+ WebConfig dummyWebConfig = new WebFilterConfig(filterConfig);
+ ResourceConfig resourceConfig = new ResourceConfig()
+ .property(CommonProperties.PROVIDER_DEFAULT_DISABLE, "ALL")
+ .property(ServerProperties.WADL_FEATURE_DISABLE, true)
+ .property(ServletProperties.FILTER_FORWARD_ON_404, true)
+ .property(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, true);
+ WebComponent component = new WebComponent(dummyWebConfig, resourceConfig);
+ component.service(URI.create("http://localhost"), URI.create("http://localhost"),
+ (HttpServletRequest) Proxy.newProxyInstance(getClass().getClassLoader(),
+ new Class[] {HttpServletRequest.class},
+ handler
+ ),
+ (HttpServletResponse) Proxy.newProxyInstance(getClass().getClassLoader(),
+ new Class[]{HttpServletResponse.class},
+ handler)
+ );
+ }
+}
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java
index b5b28f389c..ca73f4c25c 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/internal/HttpUrlConnector.java
@@ -66,6 +66,7 @@
import org.glassfish.jersey.client.spi.AsyncConnectorCallback;
import org.glassfish.jersey.client.spi.Connector;
import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.internal.util.collection.LRU;
import org.glassfish.jersey.internal.util.collection.LazyValue;
import org.glassfish.jersey.internal.util.collection.UnsafeValue;
import org.glassfish.jersey.internal.util.collection.Value;
@@ -83,7 +84,7 @@ public class HttpUrlConnector implements Connector {
private static final String ALLOW_RESTRICTED_HEADERS_SYSTEM_PROPERTY = "sun.net.http.allowRestrictedHeaders";
// Avoid multi-thread uses of HttpsURLConnection.getDefaultSSLSocketFactory() because it does not implement a
// proper lazy-initialization. See https://github.com/jersey/jersey/issues/3293
- private static final LazyValue DEFAULT_SSL_SOCKET_FACTORY =
+ private static final Value DEFAULT_SSL_SOCKET_FACTORY =
Values.lazy((Value) () -> HttpsURLConnection.getDefaultSSLSocketFactory());
// The list of restricted headers is extracted from sun.net.www.protocol.http.HttpURLConnection
private static final String[] restrictedHeaders = {
@@ -114,7 +115,12 @@ public class HttpUrlConnector implements Connector {
private final boolean fixLengthStreaming;
private final boolean setMethodWorkaround;
private final boolean isRestrictedHeaderPropertySet;
- private LazyValue sslSocketFactory;
+ private Value sslSocketFactory;
+
+ // SSLContext#getSocketFactory not idempotent
+ // JDK KeepAliveCache keeps connections per Factory
+ // SSLContext set per request blows that -> keep factory in LRU
+ private final LRU sslSocketFactoryCache = LRU.create();
private final ConnectorExtension connectorExtension
= new HttpUrlExpect100ContinueConnectorExtension();
@@ -143,6 +149,13 @@ public HttpUrlConnector(
this.fixLengthStreaming = fixLengthStreaming;
this.setMethodWorkaround = setMethodWorkaround;
+ this.sslSocketFactory = Values.lazy(new Value() {
+ @Override
+ public SSLSocketFactory get() {
+ return client.getSslContext().getSocketFactory();
+ }
+ });
+
// check if sun.net.http.allowRestrictedHeaders system property has been set and log the result
// the property is being cached in the HttpURLConnection, so this is only informative - there might
// already be some connection(s), that existed before the property was set/changed.
@@ -342,16 +355,23 @@ private void secureConnection(
}
}
- private void setSslContextFactory(Client client, ClientRequest request) {
+ protected void setSslContextFactory(Client client, ClientRequest request) {
final Supplier supplier = request.resolveProperty(ClientProperties.SSL_CONTEXT_SUPPLIER, Supplier.class);
- sslSocketFactory = Values.lazy(new Value() {
- @Override
- public SSLSocketFactory get() {
- final SSLContext ctx = supplier == null ? client.getSslContext() : supplier.get();
- return ctx.getSocketFactory();
- }
- });
+ if (supplier != null) {
+ sslSocketFactory = Values.lazy(new Value() { // lazy for double-check locking if multiple requests
+ @Override
+ public SSLSocketFactory get() {
+ SSLContext sslContext = supplier.get();
+ SSLSocketFactory factory = sslSocketFactoryCache.getIfPresent(sslContext);
+ if (factory == null) {
+ factory = sslContext.getSocketFactory();
+ sslSocketFactoryCache.put(sslContext, factory);
+ }
+ return factory;
+ }
+ });
+ }
}
private ClientResponse _apply(final ClientRequest request) throws IOException {
diff --git a/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties b/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties
index 291ac98580..8940d72197 100644
--- a/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties
+++ b/core-client/src/main/resources/org/glassfish/jersey/client/internal/localization.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0, which is available at
@@ -50,7 +50,7 @@ negative.chunk.size=Negative chunked HTTP transfer coding chunk size value speci
Reverting to programmatically set default: [{1}]
negative.input.parameter="Input parameter {0} must not be negative1."
noninject.ambiguous.services=Ambiguous providing services ${0}.
-noninject.fallback=Falling back to injection-less client.
+noninject.fallback=Jersey-HK2 module is missing. Falling back to injection-less client. Injection may not be supported on the client.
noninject.no.constructor=No applicable constructor for ${0} found.
noninject.no.binding=No binding found for ${0}.
noninject.requestscope.created=RequestScope already created.
diff --git a/core-client/src/test/java/org/glassfish/jersey/client/SSLSocketFactoryTest.java b/core-client/src/test/java/org/glassfish/jersey/client/SSLSocketFactoryTest.java
new file mode 100644
index 0000000000..362bbe67ed
--- /dev/null
+++ b/core-client/src/test/java/org/glassfish/jersey/client/SSLSocketFactoryTest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.client;
+
+import org.glassfish.jersey.client.internal.HttpUrlConnector;
+import org.glassfish.jersey.client.spi.Connector;
+import org.glassfish.jersey.internal.MapPropertiesDelegate;
+import org.glassfish.jersey.internal.PropertiesDelegate;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.core.Response;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+
+public class SSLSocketFactoryTest {
+ static final AtomicReference factoryHolder = new AtomicReference<>();
+ static SSLSocketFactory defaultSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
+
+ // @Test
+ // Alternative test
+ // Check KeepAliveCache#get(URL url, Object obj)
+ public void testSingleConnection() throws InterruptedException, IOException {
+ Client client = ClientBuilder.newClient();
+
+ for (int i = 0; i < 3; i++) {
+ try (Response response = client.target("https://www.spiegel.de")
+ .request()
+ .get()) {
+
+ response.readEntity(String.class);
+ System.out.println(String.format("response = %s", response));
+ Thread.sleep(1000);
+ }
+ }
+
+ System.in.read();
+ }
+
+ @Test
+ public void testSslContextFactoryOnClientIsSameForConsecutiveRequests() throws IOException, URISyntaxException {
+ int firstRequestFactory, secondRequestFactory = 0;
+ Client client = ClientBuilder.newClient();
+ HttpUrlConnectorProvider.ConnectionFactory connectionFactory = (url) -> (HttpURLConnection) url.openConnection();
+ SSLSocketFactoryConnector connector = (SSLSocketFactoryConnector) new SSlSocketFactoryUrlConnectorProvider()
+ .createHttpUrlConnector(client, connectionFactory, 4096, true, false);
+ URL url = new URL("https://somewhere.whereever:8080");
+ URLConnection urlConnection = url.openConnection();
+
+ // First Request
+ connector.setSslContextFactory(client, new ClientRequest(url.toURI(),
+ (ClientConfig) client.getConfiguration(), new MapPropertiesDelegate()));
+ connector.secureConnection((JerseyClient) client, (HttpURLConnection) urlConnection);
+ firstRequestFactory = factoryHolder.get().hashCode();
+
+ // reset to the default socketFactory
+ ((HttpsURLConnection) urlConnection).setSSLSocketFactory(defaultSocketFactory);
+
+ // Second Request
+ connector.setSslContextFactory(client, new ClientRequest(url.toURI(),
+ (ClientConfig) client.getConfiguration(), new MapPropertiesDelegate()));
+ connector.secureConnection((JerseyClient) client, (HttpURLConnection) urlConnection);
+ secondRequestFactory = factoryHolder.get().hashCode();
+
+ MatcherAssert.assertThat(firstRequestFactory, Matchers.equalTo(secondRequestFactory));
+ }
+
+ @Test
+ public void testSslContextFactoryOnRequestIsSameForConsecutiveRequests() throws IOException, URISyntaxException {
+ SSLSocketFactory firstRequestFactory, secondRequestFactory = null;
+ Client client = ClientBuilder.newClient();
+ SSLContext sslContext = new SslContextClientBuilder().build();
+ HttpUrlConnectorProvider.ConnectionFactory connectionFactory = (url) -> (HttpURLConnection) url.openConnection();
+ SSLSocketFactoryConnector connector = (SSLSocketFactoryConnector) new SSlSocketFactoryUrlConnectorProvider()
+ .createHttpUrlConnector(client, connectionFactory, 4096, true, false);
+ URL url = new URL("https://somewhere.whereever:8080");
+ URLConnection urlConnection = url.openConnection();
+ PropertiesDelegate propertiesDelegate = new MapPropertiesDelegate();
+ propertiesDelegate.setProperty(ClientProperties.SSL_CONTEXT_SUPPLIER, (Supplier) () -> sslContext);
+
+ // First Request
+ connector.setSslContextFactory(client, new ClientRequest(url.toURI(),
+ (ClientConfig) client.getConfiguration(), propertiesDelegate));
+ connector.secureConnection((JerseyClient) client, (HttpURLConnection) urlConnection);
+ firstRequestFactory = factoryHolder.get();
+
+ // reset to the default socketFactory
+ ((HttpsURLConnection) urlConnection).setSSLSocketFactory(defaultSocketFactory);
+
+ // Second Request
+ connector.setSslContextFactory(client, new ClientRequest(url.toURI(),
+ (ClientConfig) client.getConfiguration(), propertiesDelegate));
+ connector.secureConnection((JerseyClient) client, (HttpURLConnection) urlConnection);
+ secondRequestFactory = factoryHolder.get();
+
+ MatcherAssert.assertThat(firstRequestFactory, Matchers.equalTo(secondRequestFactory));
+ }
+
+ private static class SSLSocketFactoryConnector extends HttpUrlConnector {
+ public SSLSocketFactoryConnector(Client client, HttpUrlConnectorProvider.ConnectionFactory connectionFactory,
+ int chunkSize, boolean fixLengthStreaming, boolean setMethodWorkaround) {
+ super(client, connectionFactory, chunkSize, fixLengthStreaming, setMethodWorkaround);
+ }
+
+ @Override
+ protected void secureConnection(JerseyClient client, HttpURLConnection uc) {
+ super.secureConnection(client, uc);
+ if (HttpsURLConnection.class.isInstance(uc)) {
+ SSLSocketFactory factory = ((HttpsURLConnection) uc).getSSLSocketFactory();
+ factoryHolder.set(factory);
+ }
+ }
+
+ @Override
+ protected void setSslContextFactory(Client client, ClientRequest request) {
+ super.setSslContextFactory(client, request);
+ }
+ }
+
+ private static class SSlSocketFactoryUrlConnectorProvider extends HttpUrlConnectorProvider {
+ @Override
+ protected Connector createHttpUrlConnector(Client client, ConnectionFactory connectionFactory, int chunkSize,
+ boolean fixLengthStreaming, boolean setMethodWorkaround) {
+ return new SSLSocketFactoryConnector(
+ client,
+ connectionFactory,
+ chunkSize,
+ fixLengthStreaming,
+ setMethodWorkaround);
+ }
+ }
+}
diff --git a/core-common/pom.xml b/core-common/pom.xml
index 56f0d056e9..46315aa9c8 100644
--- a/core-common/pom.xml
+++ b/core-common/pom.xml
@@ -674,7 +674,6 @@
org.apache.maven.plugins
maven-source-plugin
- 3.0.1
attach-sources
diff --git a/core-common/src/main/java/org/glassfish/jersey/innate/io/InputStreamWrapper.java b/core-common/src/main/java/org/glassfish/jersey/innate/io/InputStreamWrapper.java
new file mode 100644
index 0000000000..c2109fe99f
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/io/InputStreamWrapper.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.innate.io;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Generic wrapper template for InputStream.
+ */
+public abstract class InputStreamWrapper extends InputStream {
+
+ /**
+ * Return the wrapped stream
+ * @return
+ */
+ protected abstract InputStream getWrapped();
+
+ /**
+ * Get wrapped stream that can throw {@link IOException}
+ * @return the wrapped InputStream.
+ * @throws IOException
+ */
+ protected InputStream getWrappedIOE() throws IOException {
+ return getWrapped();
+ }
+
+ @Override
+ public int read() throws IOException {
+ return getWrappedIOE().read();
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ return getWrappedIOE().read(b);
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ return getWrappedIOE().read(b, off, len);
+ }
+
+ @Override
+ public long skip(long n) throws IOException {
+ return getWrappedIOE().skip(n);
+ }
+
+ @Override
+ public int available() throws IOException {
+ return getWrappedIOE().available();
+ }
+
+ @Override
+ public void close() throws IOException {
+ getWrappedIOE().close();
+ }
+
+ @Override
+ public void mark(int readlimit) {
+ getWrapped().mark(readlimit);
+ }
+
+ @Override
+ public void reset() throws IOException {
+ getWrappedIOE().reset();
+ }
+
+ @Override
+ public boolean markSupported() {
+ return getWrapped().markSupported();
+ }
+}
diff --git a/core-common/src/main/java/org/glassfish/jersey/innate/io/package-info.java b/core-common/src/main/java/org/glassfish/jersey/innate/io/package-info.java
new file mode 100644
index 0000000000..e569f79f58
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/io/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+/**
+ * Jersey innate io related packages. The innate packages will not be opened by JPMS outside of Jersey.
+ * Not for public use.
+ */
+package org.glassfish.jersey.innate.io;
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderInterceptorExecutor.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderInterceptorExecutor.java
index 91738c15fb..a0e5dfc364 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderInterceptorExecutor.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderInterceptorExecutor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -38,6 +38,7 @@
import jakarta.ws.rs.ext.ReaderInterceptor;
import jakarta.ws.rs.ext.ReaderInterceptorContext;
+import org.glassfish.jersey.innate.io.InputStreamWrapper;
import org.glassfish.jersey.internal.LocalizationMessages;
import org.glassfish.jersey.internal.PropertiesDelegate;
import org.glassfish.jersey.internal.inject.InjectionManager;
@@ -248,7 +249,7 @@ private Object invokeReadFrom(final ReaderInterceptorContext context, final Mess
* {@link jakarta.ws.rs.ext.MessageBodyReader}s should not close the given {@link java.io.InputStream stream}. This input
* stream makes sure that the stream is not closed even if MBR tries to do it.
*/
- private static class UnCloseableInputStream extends InputStream {
+ private static class UnCloseableInputStream extends InputStreamWrapper {
private final InputStream original;
private final MessageBodyReader reader;
@@ -259,43 +260,8 @@ private UnCloseableInputStream(final InputStream original, final MessageBodyRead
}
@Override
- public int read() throws IOException {
- return original.read();
- }
-
- @Override
- public int read(final byte[] b) throws IOException {
- return original.read(b);
- }
-
- @Override
- public int read(final byte[] b, final int off, final int len) throws IOException {
- return original.read(b, off, len);
- }
-
- @Override
- public long skip(final long l) throws IOException {
- return original.skip(l);
- }
-
- @Override
- public int available() throws IOException {
- return original.available();
- }
-
- @Override
- public synchronized void mark(final int i) {
- original.mark(i);
- }
-
- @Override
- public synchronized void reset() throws IOException {
- original.reset();
- }
-
- @Override
- public boolean markSupported() {
- return original.markSupported();
+ protected InputStream getWrapped() {
+ return original;
}
@Override
@@ -304,10 +270,6 @@ public void close() throws IOException {
LOGGER.log(Level.FINE, LocalizationMessages.MBR_TRYING_TO_CLOSE_STREAM(reader.getClass()));
}
}
-
- private InputStream unwrap() {
- return original;
- }
}
/**
@@ -320,7 +282,7 @@ private InputStream unwrap() {
*/
public static InputStream closeableInputStream(InputStream inputStream) {
if (inputStream instanceof UnCloseableInputStream) {
- return ((UnCloseableInputStream) inputStream).unwrap();
+ return ((UnCloseableInputStream) inputStream).getWrapped();
} else {
return inputStream;
}
diff --git a/core-server/pom.xml b/core-server/pom.xml
index f0af2e88f4..263ab483d8 100644
--- a/core-server/pom.xml
+++ b/core-server/pom.xml
@@ -233,7 +233,13 @@
org.jboss
jboss-vfs
- 3.2.6.Final
+ ${jboss.vfs.version}
+ test
+
+
+ org.jboss.logging
+ jboss-logging
+ ${jboss.logging.version}
test
@@ -246,6 +252,16 @@
+
+ jdk8
+
+ 1.8
+
+
+ ${jboss.vfs.jdk8.version}
+ ${jboss.logging.8.version}
+
+
securityOff
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarFileScanner.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarFileScanner.java
index 14e86e3eb5..8c116ca685 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarFileScanner.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/scanning/JarFileScanner.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -24,6 +24,7 @@
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.glassfish.jersey.innate.io.InputStreamWrapper;
import org.glassfish.jersey.server.internal.AbstractResourceFinderAdapter;
import org.glassfish.jersey.server.internal.LocalizationMessages;
@@ -109,52 +110,17 @@ public void reset() {
@Override
public InputStream open() {
//noinspection NullableProblems
- return new InputStream() {
+ return new InputStreamWrapper() {
@Override
- public int read() throws IOException {
- return jarInputStream.read();
- }
-
- @Override
- public int read(final byte[] bytes) throws IOException {
- return jarInputStream.read(bytes);
- }
-
- @Override
- public int read(final byte[] bytes, final int i, final int i2) throws IOException {
- return jarInputStream.read(bytes, i, i2);
- }
-
- @Override
- public long skip(final long l) throws IOException {
- return jarInputStream.skip(l);
- }
-
- @Override
- public int available() throws IOException {
- return jarInputStream.available();
+ protected InputStream getWrapped() {
+ return jarInputStream;
}
@Override
public void close() throws IOException {
jarInputStream.closeEntry();
}
-
- @Override
- public synchronized void mark(final int i) {
- jarInputStream.mark(i);
- }
-
- @Override
- public synchronized void reset() throws IOException {
- jarInputStream.reset();
- }
-
- @Override
- public boolean markSupported() {
- return jarInputStream.markSupported();
- }
};
}
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/wadl/internal/WadlResource.java b/core-server/src/main/java/org/glassfish/jersey/server/wadl/internal/WadlResource.java
index 5a7188a2e0..98676812cc 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/wadl/internal/WadlResource.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/wadl/internal/WadlResource.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -21,6 +21,7 @@
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.Locale;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
@@ -62,7 +63,7 @@ public final class WadlResource {
public WadlResource() {
- this.lastModified = new SimpleDateFormat(HTTPDATEFORMAT).format(new Date());
+ this.lastModified = new SimpleDateFormat(HTTPDATEFORMAT, Locale.US).format(new Date());
}
private boolean isCached(UriInfo uriInfo, boolean detailedWadl) {
@@ -81,7 +82,7 @@ public synchronized Response getWadl(@Context UriInfo uriInfo) {
if ((wadlXmlRepresentation == null) || (!isCached(uriInfo, detailedWadl))) {
this.lastBaseUri = uriInfo.getBaseUri();
lastDetailedWadl = detailedWadl;
- this.lastModified = new SimpleDateFormat(HTTPDATEFORMAT).format(new Date());
+ this.lastModified = new SimpleDateFormat(HTTPDATEFORMAT, Locale.US).format(new Date());
ApplicationDescription applicationDescription = wadlContext.getApplication(uriInfo,
detailedWadl);
diff --git a/examples/NOTICE.md b/examples/NOTICE.md
index e982511591..034205c6f3 100644
--- a/examples/NOTICE.md
+++ b/examples/NOTICE.md
@@ -71,7 +71,7 @@ Javassist Version 3.30.2-GA
* Project: http://www.javassist.org/
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
-Jackson JAX-RS Providers Version 2.17.0
+Jackson JAX-RS Providers Version 2.17.1
* License: Apache License, 2.0
* Project: https://github.com/FasterXML/jackson-jaxrs-providers
* Copyright: (c) 2009-2023 FasterXML, LLC. All rights reserved unless otherwise indicated.
diff --git a/examples/extended-wadl-webapp/pom.xml b/examples/extended-wadl-webapp/pom.xml
index 3feed37108..0b5f9f2db1 100644
--- a/examples/extended-wadl-webapp/pom.xml
+++ b/examples/extended-wadl-webapp/pom.xml
@@ -109,7 +109,7 @@
org.slf4j
slf4j-log4j12
- 1.6.4
+ 2.0.13
test
diff --git a/examples/groovy/pom.xml b/examples/groovy/pom.xml
index 8d7a370d85..0252257db2 100644
--- a/examples/groovy/pom.xml
+++ b/examples/groovy/pom.xml
@@ -140,7 +140,7 @@
org.codehaus.mojo
build-helper-maven-plugin
- 3.0.0
+ ${buildhelper.mvn.plugin.version}
3
diff --git a/examples/jaxb/pom.xml b/examples/jaxb/pom.xml
index f8e72a720c..44303095c9 100644
--- a/examples/jaxb/pom.xml
+++ b/examples/jaxb/pom.xml
@@ -41,7 +41,7 @@
org.codehaus.woodstox
woodstox-core-asl
- 4.1.2
+ 4.4.1
org.glassfish.jersey.media
diff --git a/examples/osgi-http-service/functional-test/pom.xml b/examples/osgi-http-service/functional-test/pom.xml
index 5ec3b1c296..05b2447c27 100644
--- a/examples/osgi-http-service/functional-test/pom.xml
+++ b/examples/osgi-http-service/functional-test/pom.xml
@@ -145,7 +145,7 @@
org.slf4j
slf4j-log4j12
- 1.6.4
+ 2.0.13
test
diff --git a/examples/pom.xml b/examples/pom.xml
index 1798d4f1b2..8d25b08f5b 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -182,7 +182,7 @@
org.commonjava.maven.plugins
directory-maven-plugin
- 0.3.1
+ 1.0
directories
@@ -199,7 +199,7 @@
org.apache.maven.plugins
maven-resources-plugin
- 2.6
+ ${resources.mvn.plugin.version}
diff --git a/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/JerseyKeyValues.java b/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/JerseyKeyValues.java
index 66cdaf7b1e..8b6d9b3dfe 100644
--- a/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/JerseyKeyValues.java
+++ b/ext/micrometer/src/main/java/org/glassfish/jersey/micrometer/server/JerseyKeyValues.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -23,6 +23,9 @@
import org.glassfish.jersey.server.ExtendedUriInfo;
import org.glassfish.jersey.server.monitoring.RequestEvent;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Response;
+
/**
* Factory methods for {@link KeyValue KeyValues} associated with a request-response
* exchange that is handled by Jersey server.
@@ -38,6 +41,9 @@ class JerseyKeyValues {
private static final KeyValue URI_ROOT = JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.URI
.withValue("root");
+ private static final KeyValue URI_UNKNOWN = JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.URI
+ .withValue("UNKNOWN");
+
private static final KeyValue EXCEPTION_NONE = JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.EXCEPTION
.withValue("None");
@@ -82,17 +88,30 @@ static KeyValue status(ContainerResponse response) {
* @return the uri KeyValue derived from the request event
*/
static KeyValue uri(RequestEvent event) {
- ContainerResponse response = event.getContainerResponse();
- if (response != null) {
- int status = response.getStatus();
+ int status = 0;
+ if (event.getContainerResponse() != null) {
+ status = event.getContainerResponse().getStatus();
+ } else if (WebApplicationException.class.isInstance(event.getException())) {
+ Response webAppResponse = ((WebApplicationException) event.getException()).getResponse();
+ if (webAppResponse != null) {
+ status = webAppResponse.getStatus();
+ }
+ }
+ if (status != 0) {
if (JerseyTags.isRedirection(status) && event.getUriInfo().getMatchedResourceMethod() == null) {
return URI_REDIRECTION;
}
if (status == 404 && event.getUriInfo().getMatchedResourceMethod() == null) {
return URI_NOT_FOUND;
}
+ if (status >= 500 && status <= 599) {
+ return STATUS_SERVER_ERROR;
+ }
}
String matchingPattern = JerseyTags.getMatchingPattern(event);
+ if (matchingPattern == null) {
+ return URI_UNKNOWN;
+ }
if (matchingPattern.equals("/")) {
return URI_ROOT;
}
diff --git a/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/exception/JerseyKeyValuesTest.java b/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/exception/JerseyKeyValuesTest.java
new file mode 100644
index 0000000000..99bad31000
--- /dev/null
+++ b/ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/exception/JerseyKeyValuesTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.micrometer.server.exception;
+
+import io.micrometer.common.KeyValue;
+import io.micrometer.common.KeyValues;
+import org.glassfish.jersey.micrometer.server.DefaultJerseyObservationConvention;
+import org.glassfish.jersey.micrometer.server.JerseyContext;
+import org.glassfish.jersey.server.ExtendedUriInfo;
+import org.glassfish.jersey.server.internal.monitoring.RequestEventImpl;
+import org.glassfish.jersey.server.monitoring.RequestEvent;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.NotFoundException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Collections;
+import java.util.Optional;
+
+public class JerseyKeyValuesTest {
+ @Test
+ public void testOnException() {
+ ExtendedUriInfo uriInfo = (ExtendedUriInfo) Proxy.newProxyInstance(getClass().getClassLoader(),
+ new Class[]{ExtendedUriInfo.class},
+ new InvocationHandler() {
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ switch (method.getName()) {
+ case "getMatchedTemplates":
+ return Collections.emptyList();
+ }
+ return null;
+ }
+ });
+ RequestEventImpl event = new RequestEventImpl.Builder()
+ .setExtendedUriInfo(uriInfo)
+ .setException(new NotFoundException(), RequestEvent.ExceptionCause.ORIGINAL)
+ .build(RequestEvent.Type.ON_EXCEPTION);
+ JerseyContext context = new JerseyContext(event);
+ DefaultJerseyObservationConvention convention = new DefaultJerseyObservationConvention("Test-Metric");
+ KeyValues values = convention.getLowCardinalityKeyValues(context);
+ Optional kv = values.stream().filter(p -> p.getValue().equals("NOT_FOUND")).findFirst();
+ MatcherAssert.assertThat(kv.isPresent(), Matchers.equalTo(true));
+ }
+}
diff --git a/incubator/declarative-linking/pom.xml b/incubator/declarative-linking/pom.xml
index 181bb67105..cdb5680870 100644
--- a/incubator/declarative-linking/pom.xml
+++ b/incubator/declarative-linking/pom.xml
@@ -88,7 +88,7 @@
org.skyscreamer
jsonassert
- 1.4.0
+ 1.5.1
test
diff --git a/media/jaxb/pom.xml b/media/jaxb/pom.xml
index 75a49a0399..6586b38ea5 100644
--- a/media/jaxb/pom.xml
+++ b/media/jaxb/pom.xml
@@ -82,21 +82,6 @@
build-helper-maven-plugin
true
-
- de.jflex
- maven-jflex-plugin
- 1.4.3
-
-
-
- generate
-
-
- ${project.build.directory}/generated-sources/rsrc-gen
-
-
-
-
org.apache.felix
maven-bundle-plugin
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/cfg/MapperConfiguratorBase.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/cfg/MapperConfiguratorBase.java
index 75bc66eec7..bc280ccbfb 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/cfg/MapperConfiguratorBase.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/cfg/MapperConfiguratorBase.java
@@ -13,8 +13,8 @@
* well as accessing it.
*/
public abstract class MapperConfiguratorBase,
- MAPPER extends ObjectMapper
->
+ MAPPER extends ObjectMapper
+ >
{
/**
* Mapper provider was constructed with if any, or that was constructed
@@ -22,7 +22,7 @@ public abstract class MapperConfiguratorBase
+ extends MapperConfiguratorBase
{
+ // @since 2.17.1
+ private final ReentrantLock _lock = new ReentrantLock();
+
/*
/**********************************************************
/* Construction
/**********************************************************
*/
-
+
public JsonMapperConfigurator(ObjectMapper mapper, Annotations[] defAnnotations)
{
super(mapper, defAnnotations);
@@ -33,18 +37,24 @@ public JsonMapperConfigurator(ObjectMapper mapper, Annotations[] defAnnotations)
* Method that locates, configures and returns {@link ObjectMapper} to use
*/
@Override
- public synchronized ObjectMapper getConfiguredMapper() {
- /* important: should NOT call mapper(); needs to return null
- * if no instance has been passed or constructed
- */
+ public ObjectMapper getConfiguredMapper() {
+ // important: should NOT call mapper(); needs to return null
+ // if no instance has been passed or constructed
return _mapper;
}
@Override
- public synchronized ObjectMapper getDefaultMapper() {
+ public ObjectMapper getDefaultMapper() {
if (_defaultMapper == null) {
- _defaultMapper = new ObjectMapper();
- _setAnnotations(_defaultMapper, _defaultAnnotationsToUse);
+ _lock.lock();
+ try {
+ if (_defaultMapper == null) {
+ _defaultMapper = new ObjectMapper();
+ _setAnnotations(_defaultMapper, _defaultAnnotationsToUse);
+ }
+ } finally {
+ _lock.unlock();
+ }
}
return _defaultMapper;
}
@@ -64,8 +74,15 @@ public synchronized ObjectMapper getDefaultMapper() {
protected ObjectMapper mapper()
{
if (_mapper == null) {
- _mapper = new ObjectMapper();
- _setAnnotations(_mapper, _defaultAnnotationsToUse);
+ _lock.lock();
+ try {
+ if (_mapper == null) {
+ _mapper = new ObjectMapper();
+ _setAnnotations(_mapper, _defaultAnnotationsToUse);
+ }
+ } finally {
+ _lock.unlock();
+ }
}
return _mapper;
}
@@ -100,22 +117,22 @@ protected AnnotationIntrospector _resolveIntrospectors(Annotations[] annotations
protected AnnotationIntrospector _resolveIntrospector(Annotations ann)
{
switch (ann) {
- case JACKSON:
- return new JacksonAnnotationIntrospector();
- case JAXB:
- /* For this, need to use indirection just so that error occurs
- * when we get here, and not when this class is being loaded
- */
- try {
- if (_jaxbIntrospectorClass == null) {
- _jaxbIntrospectorClass = JaxbAnnotationIntrospector.class;
+ case JACKSON:
+ return new JacksonAnnotationIntrospector();
+ case JAXB:
+ /* For this, need to use indirection just so that error occurs
+ * when we get here, and not when this class is being loaded
+ */
+ try {
+ if (_jaxbIntrospectorClass == null) {
+ _jaxbIntrospectorClass = JaxbAnnotationIntrospector.class;
+ }
+ return _jaxbIntrospectorClass.newInstance();
+ } catch (Exception e) {
+ throw new IllegalStateException("Failed to instantiate JaxbAnnotationIntrospector: "+e.getMessage(), e);
}
- return _jaxbIntrospectorClass.newInstance();
- } catch (Exception e) {
- throw new IllegalStateException("Failed to instantiate JaxbAnnotationIntrospector: "+e.getMessage(), e);
- }
- default:
- throw new IllegalStateException();
+ default:
+ throw new IllegalStateException();
}
}
}
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/PackageVersion.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/PackageVersion.java
index 88e31680b8..5d328da992 100644
--- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/PackageVersion.java
+++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/PackageVersion.java
@@ -11,7 +11,7 @@
*/
public final class PackageVersion implements Versioned {
public final static Version VERSION = VersionUtil.parseVersion(
- "2.17.0", "com.fasterxml.jackson.jaxrs", "jackson-jaxrs-json-provider");
+ "2.17.1", "com.fasterxml.jackson.jaxrs", "jackson-jaxrs-json-provider");
@Override
public Version version() {
diff --git a/media/json-jackson/src/main/resources/META-INF/NOTICE.markdown b/media/json-jackson/src/main/resources/META-INF/NOTICE.markdown
index 6034c04d7c..4edecfc595 100644
--- a/media/json-jackson/src/main/resources/META-INF/NOTICE.markdown
+++ b/media/json-jackson/src/main/resources/META-INF/NOTICE.markdown
@@ -31,7 +31,7 @@ The project maintains the following source code repositories:
## Third-party Content
-Jackson JAX-RS Providers version 2.17.0
+Jackson JAX-RS Providers version 2.17.1
* License: Apache License, 2.0
* Project: https://github.com/FasterXML/jackson-jaxrs-providers
* Copyright: (c) 2009-2023 FasterXML, LLC. All rights reserved unless otherwise indicated.
diff --git a/media/moxy/pom.xml b/media/moxy/pom.xml
index 335f80e509..5ae722eced 100644
--- a/media/moxy/pom.xml
+++ b/media/moxy/pom.xml
@@ -62,21 +62,6 @@