From 2ee39d5d7f832f2b00cde4e8bb867684d39e3d86 Mon Sep 17 00:00:00 2001 From: Maxim Nesen Date: Tue, 28 May 2024 10:21:04 +0200 Subject: [PATCH 01/13] update Jackson to 2.17.1 Signed-off-by: Maxim Nesen --- NOTICE.md | 2 +- examples/NOTICE.md | 2 +- .../jaxrs/cfg/MapperConfiguratorBase.java | 30 ++++---- .../jaxrs/json/JsonMapperConfigurator.java | 69 ++++++++++++------- .../jackson/jaxrs/json/PackageVersion.java | 2 +- .../main/resources/META-INF/NOTICE.markdown | 2 +- pom.xml | 2 +- 7 files changed, 63 insertions(+), 46 deletions(-) diff --git a/NOTICE.md b/NOTICE.md index 6a4c169dd4..56231f8752 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -70,7 +70,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-2024 FasterXML, LLC. All rights reserved unless otherwise indicated. diff --git a/examples/NOTICE.md b/examples/NOTICE.md index 3e1e8f8f92..5724485fbf 100644 --- a/examples/NOTICE.md +++ b/examples/NOTICE.md @@ -66,7 +66,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/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/pom.xml b/pom.xml index c2a22c2a70..df7d3c39c0 100644 --- a/pom.xml +++ b/pom.xml @@ -2217,7 +2217,7 @@ 2.10.0 4.5.14 5.3.1 - 2.17.0 + 2.17.1 1.9.13 3.30.2-GA 1.19.3 From d8f3e0fba99262feffed245f5b22d1836da7ea10 Mon Sep 17 00:00:00 2001 From: jansupol Date: Mon, 3 Jun 2024 17:25:35 +0200 Subject: [PATCH 02/13] prevent calling ServletRequest#getInputStream if FILTER_FORWARD_ON_404 Introduce InputStreamWrapper Signed-off-by: jansupol --- .../apache/connector/ApacheConnector.java | 52 ++-------- .../apache5/connector/Apache5Connector.java | 52 ++-------- .../jersey/servlet/WebComponent.java | 23 ++++- .../internal/RequestInputStreamTest.java | 97 +++++++++++++++++++ .../jersey/innate/io/InputStreamWrapper.java | 86 ++++++++++++++++ .../jersey/innate/io/package-info.java | 21 ++++ .../internal/ReaderInterceptorExecutor.java | 50 ++-------- .../internal/scanning/JarFileScanner.java | 44 +-------- .../ResponseReadAndBufferEntityTest.java | 50 ++-------- 9 files changed, 254 insertions(+), 221 deletions(-) create mode 100644 containers/jersey-servlet-core/src/test/java/org/glassfish/jersey/servlet/internal/RequestInputStreamTest.java create mode 100644 core-common/src/main/java/org/glassfish/jersey/innate/io/InputStreamWrapper.java create mode 100644 core-common/src/main/java/org/glassfish/jersey/innate/io/package-info.java diff --git a/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java b/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java index 289150a086..6f1138e362 100644 --- a/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java +++ b/connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java @@ -60,6 +60,7 @@ import org.glassfish.jersey.client.innate.http.SSLParamConfigurator; import org.glassfish.jersey.client.spi.AsyncConnectorCallback; import org.glassfish.jersey.client.spi.Connector; +import org.glassfish.jersey.innate.io.InputStreamWrapper; import org.glassfish.jersey.internal.util.PropertiesHelper; import org.glassfish.jersey.message.internal.HeaderUtils; import org.glassfish.jersey.message.internal.OutboundMessageContext; @@ -890,7 +891,7 @@ protected void prepareSocket(SSLSocket socket) throws IOException { } } - private static class CancellableInputStream extends InputStream { + private static class CancellableInputStream extends InputStreamWrapper { private final InputStream in; private final Supplier isCancelled; @@ -899,58 +900,17 @@ private CancellableInputStream(InputStream in, Supplier isCancelled) { this.isCancelled = isCancelled; } - public int read(byte b[]) throws IOException { - checkAborted(); - return in.read(); - } - - public int read(byte b[], int off, int len) throws IOException { - checkAborted(); - return in.read(b, off, len); - } - - @Override - public int read() throws IOException { - checkAborted(); - return in.read(); - } - - public boolean markSupported() { - return in.markSupported(); - } - - @Override - public long skip(long n) throws IOException { - checkAborted(); - return in.skip(n); - } - - @Override - public int available() throws IOException { - checkAborted(); - return in.available(); - } - @Override - public void close() throws IOException { - in.close(); + protected InputStream getWrapped() { + return in; } @Override - public void mark(int readlimit) { - in.mark(readlimit); - } - - @Override - public void reset() throws IOException { - checkAborted(); - in.reset(); - } - - private void checkAborted() throws IOException { + protected InputStream getWrappedIOE() throws IOException { if (isCancelled.get()) { throw new IOException(new CancellationException()); } + return in; } } } diff --git a/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java b/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java index 23dd648836..a4743f98c9 100644 --- a/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java +++ b/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java @@ -105,6 +105,7 @@ import org.glassfish.jersey.client.innate.http.SSLParamConfigurator; import org.glassfish.jersey.client.spi.AsyncConnectorCallback; import org.glassfish.jersey.client.spi.Connector; +import org.glassfish.jersey.innate.io.InputStreamWrapper; import org.glassfish.jersey.internal.util.PropertiesHelper; import org.glassfish.jersey.message.internal.HeaderUtils; import org.glassfish.jersey.message.internal.OutboundMessageContext; @@ -894,7 +895,7 @@ protected void prepareSocket(SSLSocket socket) throws IOException { } } - private static class CancellableInputStream extends InputStream { + private static class CancellableInputStream extends InputStreamWrapper { private final InputStream in; private final Supplier isCancelled; @@ -903,58 +904,17 @@ private CancellableInputStream(InputStream in, Supplier isCancelled) { this.isCancelled = isCancelled; } - public int read(byte b[]) throws IOException { - checkAborted(); - return in.read(); - } - - public int read(byte b[], int off, int len) throws IOException { - checkAborted(); - return in.read(b, off, len); - } - - @Override - public int read() throws IOException { - checkAborted(); - return in.read(); - } - - public boolean markSupported() { - return in.markSupported(); - } - - @Override - public long skip(long n) throws IOException { - checkAborted(); - return in.skip(n); - } - - @Override - public int available() throws IOException { - checkAborted(); - return in.available(); - } - @Override - public void close() throws IOException { - in.close(); + protected InputStream getWrapped() { + return in; } @Override - public void mark(int readlimit) { - in.mark(readlimit); - } - - @Override - public void reset() throws IOException { - checkAborted(); - in.reset(); - } - - private void checkAborted() throws IOException { + protected InputStream getWrappedIOE() throws IOException { if (isCancelled.get()) { throw new IOException(new CancellationException()); } + return in; } } 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 0017bdd1e8..ab4e927649 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 javax.servlet.http.HttpServletRequest; import javax.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; @@ -413,7 +416,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 +424,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/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..a443165c15 --- /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 javax.servlet.FilterConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.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-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 5263fff80f..19d34bf835 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, 2019 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 javax.ws.rs.ext.ReaderInterceptor; import javax.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 javax.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/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/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ResponseReadAndBufferEntityTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ResponseReadAndBufferEntityTest.java index e9aa6d0c14..9b479c84f3 100644 --- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ResponseReadAndBufferEntityTest.java +++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ResponseReadAndBufferEntityTest.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 @@ -35,6 +35,7 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import org.glassfish.jersey.innate.io.InputStreamWrapper; import org.glassfish.jersey.logging.LoggingFeature; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.test.JerseyTest; @@ -57,7 +58,7 @@ public class ResponseReadAndBufferEntityTest extends JerseyTest { private static final Logger LOGGER = Logger.getLogger(ResponseReadAndBufferEntityTest.class.getName()); - public static class CorruptableInputStream extends InputStream { + public static class CorruptableInputStream extends InputStreamWrapper { private final AtomicInteger closeCounter = new AtomicInteger(0); @@ -71,53 +72,16 @@ public CorruptableInputStream() { } @Override - public synchronized int read() throws IOException { - if (corruptRead) { - corrupt(); - } - return delegate.read(); - } - - @Override - public int read(final byte[] b) throws IOException { - if (corruptRead) { - corrupt(); - } - return delegate.read(b); + protected InputStream getWrapped() { + return delegate; } @Override - public int read(final byte[] b, final int off, final int len) throws IOException { + protected InputStream getWrappedIOE() throws IOException { if (corruptRead) { corrupt(); } - return delegate.read(b, off, len); - } - - @Override - public long skip(final long n) throws IOException { - if (corruptRead) { - corrupt(); - } - return delegate.skip(n); - } - - @Override - public int available() throws IOException { - if (corruptRead) { - corrupt(); - } - return delegate.available(); - } - - @Override - public boolean markSupported() { - return delegate.markSupported(); - } - - @Override - public void mark(final int readAheadLimit) { - delegate.mark(readAheadLimit); + return delegate; } @Override From 7d69a424da408c7322dc8e90b1facf46fad27043 Mon Sep 17 00:00:00 2001 From: jansupol Date: Thu, 6 Jun 2024 18:11:12 +0200 Subject: [PATCH 03/13] Support missing Content-Length header Signed-off-by: jansupol --- .../apache5/connector/Apache5Connector.java | 2 +- .../jdk/connector/internal/HttpParser.java | 7 + .../internal/TransferEncodingParser.java | 2 +- .../netty/connector/JerseyClientHandler.java | 21 +-- .../client/connector/NoContentLengthTest.java | 136 ++++++++++++++++++ 5 files changed, 151 insertions(+), 17 deletions(-) create mode 100644 tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/NoContentLengthTest.java diff --git a/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java b/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java index a4743f98c9..3142331190 100644 --- a/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java +++ b/connectors/apache5-connector/src/main/java/org/glassfish/jersey/apache5/connector/Apache5Connector.java @@ -522,7 +522,7 @@ public ClientResponse apply(final ClientRequest clientRequest) throws Processing final HttpEntity entity = response.getEntity(); if (entity != null) { - if (headers.get(HttpHeaders.CONTENT_LENGTH) == null) { + if (headers.get(HttpHeaders.CONTENT_LENGTH) == null && entity.getContentLength() >= 0) { headers.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(entity.getContentLength())); } diff --git a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpParser.java b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpParser.java index 14322df02a..8f1bb1d72e 100644 --- a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpParser.java +++ b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/HttpParser.java @@ -514,8 +514,15 @@ private void decideTransferEncoding() throws ParseException { } return; + } else if (httpResponse.getHasContent()) { + // missing Content-Length + transferEncodingParser = TransferEncodingParser + .createFixedLengthParser(httpResponse.getBodyStream(), Long.MAX_VALUE); + return; } + + // TODO what now? Expect no content or fail loudly? } diff --git a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/TransferEncodingParser.java b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/TransferEncodingParser.java index 7dccd87375..1a94ff7d32 100644 --- a/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/TransferEncodingParser.java +++ b/connectors/jdk-connector/src/main/java/org/glassfish/jersey/jdk/connector/internal/TransferEncodingParser.java @@ -63,7 +63,7 @@ boolean parse(ByteBuffer input) throws ParseException { responseBody.notifyDataAvailable(parsed); consumedLength += data.length; - return consumedLength == expectedLength; + return consumedLength == expectedLength || expectedLength == Long.MAX_VALUE /* unknown at the beginning */; } } diff --git a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/JerseyClientHandler.java b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/JerseyClientHandler.java index 717290514f..c2e47c6e22 100644 --- a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/JerseyClientHandler.java +++ b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/JerseyClientHandler.java @@ -98,6 +98,8 @@ public void channelInactive(ChannelHandlerContext ctx) { if (readTimedOut) { responseDone.completeExceptionally(new TimeoutException("Stream closed: read timeout")); + } else if (jerseyRequest.isCancelled()) { + responseDone.completeExceptionally(new CancellationException()); } else { responseDone.completeExceptionally(new IOException("Stream closed")); } @@ -186,21 +188,10 @@ public String getReasonPhrase() { } // request entity handling. - if ((response.headers().contains(HttpHeaders.CONTENT_LENGTH) && HttpUtil.getContentLength(response) > 0) - || HttpUtil.isTransferEncodingChunked(response)) { - - nis = new NettyInputStream(); - responseDone.whenComplete((_r, th) -> nis.complete(th)); - - jerseyResponse.setEntityStream(nis); - } else { - jerseyResponse.setEntityStream(new InputStream() { - @Override - public int read() throws IOException { - return -1; - } - }); - } + nis = new NettyInputStream(); + responseDone.whenComplete((_r, th) -> nis.complete(th)); + + jerseyResponse.setEntityStream(nis); } if (msg instanceof HttpContent) { diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/NoContentLengthTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/NoContentLengthTest.java new file mode 100644 index 0000000000..8699142f6c --- /dev/null +++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/NoContentLengthTest.java @@ -0,0 +1,136 @@ +/* + * 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.tests.e2e.client.connector; + +import org.glassfish.jersey.apache.connector.ApacheConnectorProvider; +import org.glassfish.jersey.apache5.connector.Apache5ConnectorProvider; +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.HttpUrlConnectorProvider; +import org.glassfish.jersey.client.spi.ConnectorProvider; +import org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider; +import org.glassfish.jersey.jdk.connector.JdkConnectorProvider; +import org.glassfish.jersey.jetty.connector.JettyConnectorProvider; +import org.glassfish.jersey.netty.connector.NettyConnectorProvider; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.UncheckedIOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +public class NoContentLengthTest { + + private static final String MSG = "12345678901234567890123456789012345678901234567890"; + + private static int port; + private static AtomicBoolean running = new AtomicBoolean(false); + + @BeforeEach + void beforeEach() { + while (!running.compareAndSet(false, true)) { + try { + Thread.sleep(1000L); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + Runnable runnable = new Runnable() { + @Override + public void run() { + try { + String _port = System.getProperty("jersey.config.test.container.port"); + port = Integer.parseInt(_port == null || _port.isEmpty() ? "8080" : _port); + ServerSocket serverSocket = new ServerSocket(port); + System.err.println("Starting server on port : " + port); + + Socket clientSocket = serverSocket.accept(); + + BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + BufferedWriter out = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())); + + String s; + while ((s = in.readLine()) != null) { + // System.out.println(s); + if (s.isEmpty()) { + break; + } + } + + out.write("HTTP/1.0 200 OK\r\n"); + out.write("Content-Type: text/plain\r\n"); + out.write("\r\n"); + out.write(MSG); + + out.close(); + in.close(); + clientSocket.close(); + serverSocket.close(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } finally { + running.set(false); + } + } + }; + Thread newThread = new Thread(runnable); + newThread.start(); + } + + public static List providers() { + return Arrays.asList( + new ApacheConnectorProvider(), + new Apache5ConnectorProvider(), + new HttpUrlConnectorProvider(), + new NettyConnectorProvider(), + new JettyConnectorProvider(), + new GrizzlyConnectorProvider(), + new JdkConnectorProvider() + ); + } + + @ParameterizedTest + @MethodSource("providers") + public void testNoContentLength(ConnectorProvider connectorProvider) { + try (Response r = target(connectorProvider).request().get()) { + MatcherAssert.assertThat(r.getStatus(), Matchers.is(200)); + MatcherAssert.assertThat(r.getHeaderString(HttpHeaders.CONTENT_LENGTH), Matchers.nullValue()); + MatcherAssert.assertThat(r.hasEntity(), Matchers.is(true)); + MatcherAssert.assertThat(r.readEntity(String.class), Matchers.is(MSG)); + } + } + + private WebTarget target(ConnectorProvider connectorProvider) { + ClientConfig config = new ClientConfig(); + config.connectorProvider(connectorProvider); + return ClientBuilder.newClient(config).target("http://localhost:" + port); + } +} From e24eb6dea31dfaab4bdfa41a2c1e8a14bd025c2c Mon Sep 17 00:00:00 2001 From: jansupol Date: Mon, 27 May 2024 22:04:09 +0200 Subject: [PATCH 04/13] More release checks Signed-off-by: jansupol --- .../test/artifacts/ClassVersionChecker.java | 11 +++- .../test/artifacts/DependencyResolver.java | 26 ++++++++- .../jersey/test/artifacts/MavenUtil.java | 29 ++++++++-- .../artifacts/DownloadBomPomDependencies.java | 26 ++++++++- .../test/artifacts/LegalDocsIncludedTest.java | 10 +++- .../jersey/test/artifacts/ManifestTest.java | 22 +++++++- .../test/artifacts/MultiReleaseTest.java | 54 ++++++++++++++++++- 7 files changed, 167 insertions(+), 11 deletions(-) diff --git a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/ClassVersionChecker.java b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/ClassVersionChecker.java index 743d609627..8a97941ab0 100644 --- a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/ClassVersionChecker.java +++ b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/ClassVersionChecker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -27,7 +27,14 @@ class ClassVersionChecker { static TestResult checkClassVersion(JarFile jar, JarEntry entry, Properties properties) throws IOException { final String jerseyVersion = MavenUtil.getJerseyVersion(properties); - final int minVersion = jerseyVersion.startsWith("3.1") ? 11 : 8; + final int minVersion; + if (jerseyVersion.startsWith("4")) { + minVersion = 17; + } else if (jerseyVersion.startsWith("3.1")) { + minVersion = 11; + } else { + minVersion = 8; + } return checkClassVersion(jar.getInputStream(entry), jar.getName() + File.separator + entry.getName(), minVersion); } diff --git a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/DependencyResolver.java b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/DependencyResolver.java index b1a7ee3bba..eeea9822e6 100644 --- a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/DependencyResolver.java +++ b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/DependencyResolver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -42,4 +42,28 @@ static Artifact resolveArtifact(org.apache.maven.model.Dependency d, List remoteRepos, + RepositorySystem repoSystem, RepositorySystemSession repoSession) + throws ArtifactResolutionException { + DefaultArtifact artifact = new DefaultArtifact( + d.getGroupId(), d.getArtifactId(), "sources", d.getType(), d.getVersion() + ); + ArtifactRequest request = new ArtifactRequest(); + request.setArtifact(artifact); + request.setRepositories(remoteRepos); + return repoSystem.resolveArtifact(repoSession, request).getArtifact(); + } + + static Artifact resolveJavadoc(org.apache.maven.model.Dependency d, List remoteRepos, + RepositorySystem repoSystem, RepositorySystemSession repoSession) + throws ArtifactResolutionException { + DefaultArtifact artifact = new DefaultArtifact( + d.getGroupId(), d.getArtifactId(), "javadoc", d.getType(), d.getVersion() + ); + ArtifactRequest request = new ArtifactRequest(); + request.setArtifact(artifact); + request.setRepositories(remoteRepos); + return repoSystem.resolveArtifact(repoSession, request).getArtifact(); + } } \ No newline at end of file diff --git a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/MavenUtil.java b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/MavenUtil.java index 20e77377b7..98d4616fcf 100644 --- a/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/MavenUtil.java +++ b/tests/release-test/src/main/java/org/glassfish/jersey/test/artifacts/MavenUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -29,6 +29,7 @@ import java.util.Collections; import java.util.List; import java.util.Properties; +import java.util.stream.Collectors; import java.util.stream.Stream; public final class MavenUtil { @@ -37,7 +38,7 @@ public final class MavenUtil { private static final String PROJECT_VERSION = "project.version"; static File getArtifactJar(File repositoryRoot, Dependency dependency, Properties properties) { - return getArtifactFile(repositoryRoot, dependency, properties, "jar"); + return getArtifactFile(repositoryRoot, dependency, properties, dependency.getType()); } private static File getArtifactFile(File repositoryRoot, Dependency dependency, Properties properties, String extension) { @@ -52,7 +53,11 @@ private static File getArtifactFile(File repositoryRoot, Dependency dependency, } String version = MavenUtil.getDependencyVersion(dependency, properties); fileSuffix.append(version).append(File.separator); - fileSuffix.append(dependency.getArtifactId()).append('-').append(version).append(".").append(extension); + fileSuffix.append(dependency.getArtifactId()).append('-').append(version); + if (dependency.getClassifier() != null) { + fileSuffix.append('-').append(dependency.getClassifier()); + } + fileSuffix.append(".").append(extension); return new File(repositoryRoot, fileSuffix.toString()); } @@ -103,7 +108,16 @@ static Stream keepJerseyJars(Stream stream, DependencyPa static Stream streamJerseyJars() throws IOException, XmlPullParserException { Model model = getModelFromFile("pom.xml"); List deps = getBomPomDependencies(model); + return streamJerseyJars(deps); + } + static Stream streamJerseySources() throws IOException, XmlPullParserException { + Model model = getModelFromFile("pom.xml"); + List deps = getBomPomSources(model); + return streamJerseyJars(deps); + } + + private static Stream streamJerseyJars(List deps) throws IOException, XmlPullParserException { return deps.stream() .filter(dep -> dep.getGroupId().startsWith("org.glassfish.jersey")) .filter(dep -> dep.getType().equals("jar")); @@ -139,6 +153,15 @@ private static List getBomPomDependencies(Model model) throws IOExce return bomPomModel.getDependencyManagement().getDependencies(); } + private static List getBomPomSources(Model model) throws XmlPullParserException, IOException { + return getBomPomDependencies(model).stream() + .map(dependency -> { + dependency.setClassifier("sources"); + return dependency; + }) + .collect(Collectors.toList()); + } + static String getJerseyVersion(Properties properties) { String property = properties.getProperty(JERSEY_VERSION); // when it is in the pom.file if (property == null || property.startsWith("${")) { diff --git a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/DownloadBomPomDependencies.java b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/DownloadBomPomDependencies.java index 99c94eee3b..6a74f0787c 100644 --- a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/DownloadBomPomDependencies.java +++ b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/DownloadBomPomDependencies.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -58,6 +58,12 @@ public void testDownloadBomPomDependencies() throws Exception { Artifact m = mavenEnvironment.resolveArtifact(member); System.out.append("Resolved ").append(member.getGroupId()).append(":").append(member.getArtifactId()).append(":") .append(member.getVersion()).append(" to ").println(m.getFile().getName()); + m = mavenEnvironment.resolveSource(member); + System.out.append("Resolved sources ").append(member.getGroupId()).append(":").append(member.getArtifactId()) + .append(":").append(member.getVersion()).append(" to ").println(m.getFile().getName()); + m = mavenEnvironment.resolveJavadoc(member); + System.out.append("Resolved javadoc ").append(member.getGroupId()).append(":").append(member.getArtifactId()) + .append(":").append(member.getVersion()).append(" to ").println(m.getFile().getName()); } } @@ -74,6 +80,14 @@ public void testDownloadNonBomPomDependencies() throws Exception { System.out.append("Resolved ").append(dependency.getGroupId()).append(":") .append(dependency.getArtifactId()).append(":") .append(dependency.getVersion()).append(" to ").println(m.getFile().getName()); + m = mavenEnvironment.resolveSource(dependency); + System.out.append("Resolved source ").append(dependency.getGroupId()).append(":") + .append(dependency.getArtifactId()).append(":") + .append(dependency.getVersion()).append(" to ").println(m.getFile().getName()); + m = mavenEnvironment.resolveJavadoc(dependency); + System.out.append("Resolved javadoc ").append(dependency.getGroupId()).append(":") + .append(dependency.getArtifactId()).append(":") + .append(dependency.getVersion()).append(" to ").println(m.getFile().getName()); } } @@ -102,6 +116,16 @@ Artifact resolveArtifact(Dependency dependency) throws ArtifactResolutionExcepti return DependencyResolver.resolveArtifact(dependency, remoteRepos, repositorySystem, repoSession); } + Artifact resolveSource(Dependency dependency) throws ArtifactResolutionException { + dependency.setVersion(jerseyVersion); + return DependencyResolver.resolveSource(dependency, remoteRepos, repositorySystem, repoSession); + } + + Artifact resolveJavadoc(Dependency dependency) throws ArtifactResolutionException { + dependency.setVersion(jerseyVersion); + return DependencyResolver.resolveJavadoc(dependency, remoteRepos, repositorySystem, repoSession); + } + private List getRemoteRepositories() throws Exception { MavenProject project = getMavenProjectForResourceFile("/release-test-pom.xml"); List remoteArtifactRepositories = project.getRemoteProjectRepositories(); diff --git a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/LegalDocsIncludedTest.java b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/LegalDocsIncludedTest.java index 74e0281a84..8c784af933 100644 --- a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/LegalDocsIncludedTest.java +++ b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/LegalDocsIncludedTest.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 @@ -41,7 +41,15 @@ public void testLegalFiles() throws IOException, XmlPullParserException { List jars = MavenUtil.streamJerseyJars() .map(dependency -> MavenUtil.getArtifactJar(localRepository, dependency, properties)) .collect(Collectors.toList()); + testLegalFiles(jars, testResult); + jars = MavenUtil.streamJerseySources() + .map(dependency -> MavenUtil.getArtifactJar(localRepository, dependency, properties)) + .collect(Collectors.toList()); + testLegalFiles(jars, testResult); + } + + private void testLegalFiles(List jars, TestResult testResult) throws IOException { for (File jar : jars) { for (String filename : new String[]{LICENSE_FILE, NOTICE_FILE}) { JarFile jarFile = new JarFile(jar); diff --git a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ManifestTest.java b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ManifestTest.java index 0c77d69c3c..a5208681dc 100644 --- a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ManifestTest.java +++ b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ManifestTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -25,6 +25,7 @@ import java.util.Properties; import java.util.jar.JarFile; import java.util.stream.Collectors; +import java.util.zip.ZipEntry; public class ManifestTest { private static final File localRepository = MavenUtil.getLocalMavenRepository(); @@ -63,6 +64,25 @@ public void testHasOsgiManifest() throws IOException, XmlPullParserException { } } + for (File jar : jars) { + JarFile jarFile = new JarFile(jar); + String value = jarFile.getManifest().getMainAttributes().getValue("Multi-Release"); +// System.out.append("Accessing META-INF/versions").append(" of ").println(jar.getName()); + ZipEntry versions = jarFile.getEntry("META-INF/versions/"); + if (versions != null) { + if (!"true".equals(value)) { + testResult.exception().append("'Multi-Release: true' not set for ").println(jar.getName()); + } else { + testResult.ok().append("'Multi-Release: true' set for ").println(jar.getName()); + } + } else { + if ("true".equals(value)) { + testResult.exception().append("'Multi-Release: true' SET for ").println(jar.getName()); + } + } + + } + //Assertions.assertTrue(testResult.result(), "Some error occurred, see previous messages"); Assert.assertTrue("Some error occurred, see previous messages", testResult.result()); } diff --git a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/MultiReleaseTest.java b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/MultiReleaseTest.java index 288932a58c..317118d207 100644 --- a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/MultiReleaseTest.java +++ b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/MultiReleaseTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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 @@ -40,12 +40,14 @@ public class MultiReleaseTest { private static final DependencyPair[] jdk11multiRelease = jdk11multiRelease(properties); private static final DependencyPair[] jdk12multiRelease = jdk12multiRelease(properties); private static final DependencyPair[] jdk17multiRelease = jdk17multiRelease(properties); + private static final DependencyPair[] jdk21multiRelease = jdk21multiRelease(properties); @Test public void testIsJdkMultiRelease() throws IOException, XmlPullParserException { TestResult result = testJdkVersions("11", jdk11multiRelease); result.append(testJdkVersions("12", jdk12multiRelease)); result.append(testJdkVersions("17", jdk17multiRelease)); + result.append(testJdkVersions("21", jdk21multiRelease)); //Assertions.assertTrue(result.result(), "Some error occurred, see previous messages"); Assert.assertTrue("Some error occurred, see previous messages", result.result()); } @@ -54,6 +56,7 @@ private static TestResult testJdkVersions(String version, DependencyPair... depe throws XmlPullParserException, IOException { final TestResult result = new TestResult(); if (dependencies == null || dependencies.length == 0) { + System.out.append("No dependencies found for jdk ").println(version); return result; } @@ -81,6 +84,7 @@ private static TestResult testJdkVersions(String version, DependencyPair... depe result.exception().append("Not a multirelease jar ").append(jar.getName()).println("!"); } ZipEntry versions = jarFile.getEntry("META-INF/versions/" + version); + System.out.append("Accessing META-INF/versions/").append(version).append(" of ").println(jar.getName()); if (versions == null) { result.exception().append("No classes for JDK ").append(version).append(" for ").println(jar.getName()); } @@ -95,6 +99,26 @@ private static TestResult testJdkVersions(String version, DependencyPair... depe result.append(ClassVersionChecker.checkClassVersion(jarFile, jarEntry, properties)); } + // Verify that number of multirelease jars matches the expected dependencies + StringBuilder multi = new StringBuilder(); + int multiCnt = 0; + List allFiles = MavenUtil.streamJerseyJars() + .map(dependency -> MavenUtil.getArtifactJar(localRepository, dependency, properties)) + .collect(Collectors.toList()); + for (File jar : files) { + JarFile jarFile = new JarFile(jar); + if (jarFile.isMultiRelease()) { + multiCnt++; + multi.append("Multirelease jar ").append(jar.getName()).append('\n'); + } + } + if (files.size() == multiCnt) { + result.ok().println("There is expected number of multirelease jars"); + } else { + result.exception().println("There is unexpected number of multirelease jars:"); + result.exception().append(multi).println(""); + } + return result; } @@ -136,12 +160,38 @@ private static DependencyPair[] jdk12multiRelease(Properties properties) { private static DependencyPair[] jdk17multiRelease(Properties properties) { String jerseyVersion = MavenUtil.getJerseyVersion(properties); - if (jerseyVersion.startsWith("3")) { + if (jerseyVersion.startsWith("3.0")) { + return new DependencyPair[] { + new DependencyPair("org.glassfish.jersey.connectors", "jersey-helidon-connector"), + new DependencyPair("org.glassfish.jersey.ext", "jersey-spring6") + }; + } else if (jerseyVersion.startsWith("3")) { return new DependencyPair[] { new DependencyPair("org.glassfish.jersey.connectors", "jersey-helidon-connector"), + new DependencyPair("org.glassfish.jersey.connectors", "jersey-jetty-connector"), + new DependencyPair("org.glassfish.jersey.connectors", "jersey-jetty-http2-connector"), + new DependencyPair("org.glassfish.jersey.containers", "jersey-container-jetty-http"), + new DependencyPair("org.glassfish.jersey.containers", "jersey-container-jetty-http2"), + new DependencyPair("org.glassfish.jersey.test-framework.providers", "jersey-test-framework-provider-jetty"), + new DependencyPair("org.glassfish.jersey.test-framework.providers", + "jersey-test-framework-provider-jetty-http2"), new DependencyPair("org.glassfish.jersey.ext", "jersey-spring6") }; } return new DependencyPair[]{}; } + + private static DependencyPair[] jdk21multiRelease(Properties properties) { + String jerseyVersion = MavenUtil.getJerseyVersion(properties); + if (jerseyVersion.startsWith("4")) { + return new DependencyPair[]{ + new DependencyPair("org.glassfish.jersey.core", "jersey-common") + }; + } else { + return new DependencyPair[]{ + new DependencyPair("org.glassfish.jersey.bundles", "jaxrs-ri"), + new DependencyPair("org.glassfish.jersey.core", "jersey-common") + }; + } + } } From 04857d723829d9832201980ff3005aad064d0410 Mon Sep 17 00:00:00 2001 From: Maxim Nesen Date: Tue, 18 Jun 2024 12:42:41 +0200 Subject: [PATCH 05/13] mvn build improvements (#5666) Signed-off-by: Maxim Nesen --- .../resources/archetype-resources/pom.xml | 3 +- archetypes/jersey-heroku-webapp/pom.xml | 2 +- .../resources/archetype-resources/pom.xml | 5 +-- archetypes/jersey-quickstart-grizzly2/pom.xml | 2 +- .../src/main/resources/META-INF/archetype.xml | 29 ------------- .../META-INF/maven/archetype-metadata.xml | 42 +++++++++++++++++++ .../resources/archetype-resources/pom.xml | 9 ++-- archetypes/jersey-quickstart-webapp/pom.xml | 2 +- .../src/main/resources/META-INF/archetype.xml | 29 ------------- .../META-INF/maven/archetype-metadata.xml | 42 +++++++++++++++++++ .../resources/archetype-resources/pom.xml | 3 +- bundles/apidocs/pom.xml | 2 +- bundles/jaxrs-ri/pom.xml | 2 +- connectors/helidon-connector/pom.xml | 2 +- core-common/pom.xml | 1 - core-server/pom.xml | 17 +++++++- examples/extended-wadl-webapp/pom.xml | 2 +- examples/groovy/pom.xml | 6 +-- .../helloworld-spring-annotations/pom.xml | 4 +- examples/java8-webapp/pom.xml | 2 +- examples/jaxb/pom.xml | 2 +- .../osgi-http-service/functional-test/pom.xml | 2 +- examples/pom.xml | 4 +- ext/microprofile/mp-rest-client/pom.xml | 2 +- ext/spring4/pom.xml | 4 +- ext/spring5/pom.xml | 4 +- incubator/declarative-linking/pom.xml | 2 +- media/jaxb/pom.xml | 15 ------- media/moxy/pom.xml | 15 ------- pom.xml | 6 ++- tests/e2e-tls/pom.xml | 2 +- tests/integration/JERSEY-2988/pom.xml | 2 +- .../cdi-resource-with-at-context/pom.xml | 2 +- tests/integration/jersey-2776/pom.xml | 2 +- .../runners/jersey-grizzly-runner/pom.xml | 2 +- .../performance/test-cases/monitoring/pom.xml | 14 +++---- .../jersey/test/artifacts/ArchetypesTest.java | 34 ++++----------- 37 files changed, 156 insertions(+), 164 deletions(-) delete mode 100644 archetypes/jersey-quickstart-grizzly2/src/main/resources/META-INF/archetype.xml create mode 100644 archetypes/jersey-quickstart-grizzly2/src/main/resources/META-INF/maven/archetype-metadata.xml delete mode 100644 archetypes/jersey-quickstart-webapp/src/main/resources/META-INF/archetype.xml create mode 100644 archetypes/jersey-quickstart-webapp/src/main/resources/META-INF/maven/archetype-metadata.xml diff --git a/archetypes/jersey-example-java8-webapp/src/main/resources/archetype-resources/pom.xml b/archetypes/jersey-example-java8-webapp/src/main/resources/archetype-resources/pom.xml index dc88fe13f3..af777dd4a0 100644 --- a/archetypes/jersey-example-java8-webapp/src/main/resources/archetype-resources/pom.xml +++ b/archetypes/jersey-example-java8-webapp/src/main/resources/archetype-resources/pom.xml @@ -1,7 +1,7 @@ - - - jersey-quickstart-grizzly2 - - src/main/java/Main.java - src/main/java/MyResource.java - - - src/test/java/MyResourceTest.java - - diff --git a/archetypes/jersey-quickstart-grizzly2/src/main/resources/META-INF/maven/archetype-metadata.xml b/archetypes/jersey-quickstart-grizzly2/src/main/resources/META-INF/maven/archetype-metadata.xml new file mode 100644 index 0000000000..54380e52c4 --- /dev/null +++ b/archetypes/jersey-quickstart-grizzly2/src/main/resources/META-INF/maven/archetype-metadata.xml @@ -0,0 +1,42 @@ + + + + + + + src/main/java + + **/* + + + + + src/test/java + + **/* + + + + \ No newline at end of file diff --git a/archetypes/jersey-quickstart-grizzly2/src/main/resources/archetype-resources/pom.xml b/archetypes/jersey-quickstart-grizzly2/src/main/resources/archetype-resources/pom.xml index 779f0802af..087417f001 100644 --- a/archetypes/jersey-quickstart-grizzly2/src/main/resources/archetype-resources/pom.xml +++ b/archetypes/jersey-quickstart-grizzly2/src/main/resources/archetype-resources/pom.xml @@ -40,7 +40,7 @@ org.junit.jupiter junit-jupiter - \${junit-jupiter.version} + \${junit5.version} test @@ -50,7 +50,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + ${compiler.mvn.plugin.version} true 1.8 @@ -60,7 +60,7 @@ org.codehaus.mojo exec-maven-plugin - 1.2.1 + ${exec.mvn.plugin.version} @@ -83,8 +83,7 @@ ${project.version} - 5.10.2 + ${junit5.version} UTF-8 - 3.2.5 diff --git a/archetypes/jersey-quickstart-webapp/pom.xml b/archetypes/jersey-quickstart-webapp/pom.xml index 4fab928319..21aa6b3d72 100644 --- a/archetypes/jersey-quickstart-webapp/pom.xml +++ b/archetypes/jersey-quickstart-webapp/pom.xml @@ -36,7 +36,7 @@ org.apache.maven.plugins maven-resources-plugin - 2.5 + ${resources.mvn.plugin.version} \ diff --git a/archetypes/jersey-quickstart-webapp/src/main/resources/META-INF/archetype.xml b/archetypes/jersey-quickstart-webapp/src/main/resources/META-INF/archetype.xml deleted file mode 100644 index cea1eea5e9..0000000000 --- a/archetypes/jersey-quickstart-webapp/src/main/resources/META-INF/archetype.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - jersey-quickstart-webapp - - src/main/java/MyResource.java - - - src/main/webapp/index.jsp - src/main/webapp/WEB-INF/web.xml - - diff --git a/archetypes/jersey-quickstart-webapp/src/main/resources/META-INF/maven/archetype-metadata.xml b/archetypes/jersey-quickstart-webapp/src/main/resources/META-INF/maven/archetype-metadata.xml new file mode 100644 index 0000000000..bea65b3530 --- /dev/null +++ b/archetypes/jersey-quickstart-webapp/src/main/resources/META-INF/maven/archetype-metadata.xml @@ -0,0 +1,42 @@ + + + + + + + src/main/java + + + src/main/webapp + + **/* + + + + src/test/java + + **/* + + + + \ No newline at end of file diff --git a/archetypes/jersey-quickstart-webapp/src/main/resources/archetype-resources/pom.xml b/archetypes/jersey-quickstart-webapp/src/main/resources/archetype-resources/pom.xml index fc70d51357..341fb67664 100644 --- a/archetypes/jersey-quickstart-webapp/src/main/resources/archetype-resources/pom.xml +++ b/archetypes/jersey-quickstart-webapp/src/main/resources/archetype-resources/pom.xml @@ -15,7 +15,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + ${compiler.mvn.plugin.version} true 1.8 @@ -63,6 +63,5 @@ ${project.version} UTF-8 - 3.4.0 diff --git a/bundles/apidocs/pom.xml b/bundles/apidocs/pom.xml index 3f7f7c0f9a..a0ea49a315 100644 --- a/bundles/apidocs/pom.xml +++ b/bundles/apidocs/pom.xml @@ -127,7 +127,7 @@ org.glassfish javax.servlet - 3.1 + 3.1.1 org.glassfish.jersey.containers diff --git a/bundles/jaxrs-ri/pom.xml b/bundles/jaxrs-ri/pom.xml index aae987cf25..442cc53318 100644 --- a/bundles/jaxrs-ri/pom.xml +++ b/bundles/jaxrs-ri/pom.xml @@ -424,7 +424,7 @@ org.codehaus.mojo wagon-maven-plugin - 1.0-beta-4 + 2.0.2 false diff --git a/connectors/helidon-connector/pom.xml b/connectors/helidon-connector/pom.xml index 63bd4bbadc..a34b2583f4 100644 --- a/connectors/helidon-connector/pom.xml +++ b/connectors/helidon-connector/pom.xml @@ -34,7 +34,7 @@ io.helidon.jersey helidon-jersey-connector - 2.2.1 + ${helidon.connector.version} provided diff --git a/core-common/pom.xml b/core-common/pom.xml index 11d3977f5a..e93ca182d9 100644 --- a/core-common/pom.xml +++ b/core-common/pom.xml @@ -676,7 +676,6 @@ org.apache.maven.plugins maven-source-plugin - 3.0.1 attach-sources diff --git a/core-server/pom.xml b/core-server/pom.xml index 1fc66f1bde..5b32a1e99a 100644 --- a/core-server/pom.xml +++ b/core-server/pom.xml @@ -227,7 +227,13 @@ org.jboss jboss-vfs - 3.2.6.Final + ${jboss.vfs.version} + test + + + org.jboss.logging + jboss-logging + ${jboss.logging.version} test @@ -240,6 +246,15 @@ + + jdk8 + + 1.8 + + + ${jboss.vfs.jdk8.version} + + jdk11+ diff --git a/examples/extended-wadl-webapp/pom.xml b/examples/extended-wadl-webapp/pom.xml index 051ade4546..0d1a933fd3 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 201f35ac27..b527e8749c 100644 --- a/examples/groovy/pom.xml +++ b/examples/groovy/pom.xml @@ -48,7 +48,7 @@ org.junit.jupiter junit-jupiter-engine - 5.8.2 + ${junit5.version} test @@ -83,7 +83,7 @@ org.codehaus.gmavenplus gmavenplus-plugin - 1.12.1 + 3.0.0 1 @@ -126,7 +126,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.0.0 + ${buildhelper.mvn.plugin.version} 3 diff --git a/examples/helloworld-spring-annotations/pom.xml b/examples/helloworld-spring-annotations/pom.xml index ea11e81741..1723ca6665 100644 --- a/examples/helloworld-spring-annotations/pom.xml +++ b/examples/helloworld-spring-annotations/pom.xml @@ -44,7 +44,7 @@ commons-logging commons-logging - 1.2 + ${commons.logging.version} org.glassfish.jersey.test-framework.providers @@ -54,7 +54,7 @@ javax.servlet javax.servlet-api - 3.0.1 + ${servlet3.version} diff --git a/examples/java8-webapp/pom.xml b/examples/java8-webapp/pom.xml index da28b44284..87098e8755 100644 --- a/examples/java8-webapp/pom.xml +++ b/examples/java8-webapp/pom.xml @@ -56,7 +56,7 @@ org.eclipse.jetty jetty-maven-plugin - 9.2.6.v20141205 + ${jetty.version} 5 9999 diff --git a/examples/jaxb/pom.xml b/examples/jaxb/pom.xml index 275855d4bd..5a2b873d4b 100644 --- a/examples/jaxb/pom.xml +++ b/examples/jaxb/pom.xml @@ -37,7 +37,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 a1425e5db6..4bb826e3e2 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 fd0009e590..596fde5347 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -185,7 +185,7 @@ org.commonjava.maven.plugins directory-maven-plugin - 0.3.1 + 1.0 directories @@ -202,7 +202,7 @@ org.apache.maven.plugins maven-resources-plugin - 2.6 + ${resources.mvn.plugin.version} diff --git a/ext/microprofile/mp-rest-client/pom.xml b/ext/microprofile/mp-rest-client/pom.xml index 34a1405245..560e58f3b0 100644 --- a/ext/microprofile/mp-rest-client/pom.xml +++ b/ext/microprofile/mp-rest-client/pom.xml @@ -77,7 +77,7 @@ javax.enterprise cdi-api - 2.0 + ${cdi.api.version} provided diff --git a/ext/spring4/pom.xml b/ext/spring4/pom.xml index 611b90547d..d003c719f2 100644 --- a/ext/spring4/pom.xml +++ b/ext/spring4/pom.xml @@ -65,7 +65,7 @@ commons-logging commons-logging - 1.2 + ${commons.logging.version} test @@ -150,7 +150,7 @@ org.aspectj aspectjrt - 1.6.11 + 1.9.22.1 test diff --git a/ext/spring5/pom.xml b/ext/spring5/pom.xml index 64946def34..709d11f4fb 100644 --- a/ext/spring5/pom.xml +++ b/ext/spring5/pom.xml @@ -65,7 +65,7 @@ commons-logging commons-logging - 1.2 + ${commons.logging.version} test @@ -154,7 +154,7 @@ org.aspectj aspectjrt - 1.6.11 + 1.9.22.1 test diff --git a/incubator/declarative-linking/pom.xml b/incubator/declarative-linking/pom.xml index 024e71d00f..1b6d5b029f 100644 --- a/incubator/declarative-linking/pom.xml +++ b/incubator/declarative-linking/pom.xml @@ -83,7 +83,7 @@ org.skyscreamer jsonassert - 1.4.0 + 1.5.1 test diff --git a/media/jaxb/pom.xml b/media/jaxb/pom.xml index cb41dbcf15..38d987301a 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/moxy/pom.xml b/media/moxy/pom.xml index 96042128d5..8744ebc0eb 100644 --- a/media/moxy/pom.xml +++ b/media/moxy/pom.xml @@ -62,21 +62,6 @@ - - de.jflex - maven-jflex-plugin - 1.4.3 - - - - generate - - - ${project.build.directory}/generated-sources/rsrc-gen - - - - diff --git a/pom.xml b/pom.xml index df7d3c39c0..03d836ae56 100644 --- a/pom.xml +++ b/pom.xml @@ -2214,6 +2214,7 @@ 33.1.0-jre 2.2 1.4.14 + 2.2.1 2.10.0 4.5.14 5.3.1 @@ -2223,6 +2224,9 @@ 1.19.3 ${jersey1.version} 1.3.7 + 3.3.2.Final + 3.2.17.Final + 3.6.0.Final 1.37 1.49 4.13.2 @@ -2258,7 +2262,7 @@ 20.3.14 - 1.2 + 2.0.SP1 2.0.2 javax.enterprise.*;version="[1,3)" 3.2.6 diff --git a/tests/e2e-tls/pom.xml b/tests/e2e-tls/pom.xml index dfecf09378..b7657c5f59 100644 --- a/tests/e2e-tls/pom.xml +++ b/tests/e2e-tls/pom.xml @@ -96,7 +96,7 @@ io.specto hoverfly-java-junit5 - 0.14.0 + 0.18.1 test diff --git a/tests/integration/JERSEY-2988/pom.xml b/tests/integration/JERSEY-2988/pom.xml index e47be8324e..dc74f72b1d 100644 --- a/tests/integration/JERSEY-2988/pom.xml +++ b/tests/integration/JERSEY-2988/pom.xml @@ -61,7 +61,7 @@ javax.enterprise cdi-api - 2.0 + ${cdi.api.version} org.jboss.weld.servlet diff --git a/tests/integration/cdi-integration/cdi-resource-with-at-context/pom.xml b/tests/integration/cdi-integration/cdi-resource-with-at-context/pom.xml index 6f0ef1bee0..21cce901ec 100644 --- a/tests/integration/cdi-integration/cdi-resource-with-at-context/pom.xml +++ b/tests/integration/cdi-integration/cdi-resource-with-at-context/pom.xml @@ -46,7 +46,7 @@ javax.enterprise cdi-api - 2.0 + ${cdi.api.version} provided diff --git a/tests/integration/jersey-2776/pom.xml b/tests/integration/jersey-2776/pom.xml index 51234decb8..be57cca805 100644 --- a/tests/integration/jersey-2776/pom.xml +++ b/tests/integration/jersey-2776/pom.xml @@ -42,7 +42,7 @@ org.apache.cxf cxf-rt-rs-client - 3.0.3 + 3.5.8 test diff --git a/tests/performance/runners/jersey-grizzly-runner/pom.xml b/tests/performance/runners/jersey-grizzly-runner/pom.xml index 10ce415226..c5c265a36a 100644 --- a/tests/performance/runners/jersey-grizzly-runner/pom.xml +++ b/tests/performance/runners/jersey-grizzly-runner/pom.xml @@ -49,7 +49,7 @@ org.apache.maven.plugins maven-jar-plugin - 2.4 + ${jar.mvn.plugin.version} true diff --git a/tests/performance/test-cases/monitoring/pom.xml b/tests/performance/test-cases/monitoring/pom.xml index c4076c2a7d..d5b84bd93c 100644 --- a/tests/performance/test-cases/monitoring/pom.xml +++ b/tests/performance/test-cases/monitoring/pom.xml @@ -37,13 +37,13 @@ com.yammer.metrics metrics-core - 2.1.2 + 2.2.0 org.junit.jupiter junit-jupiter - 5.9.1 + 5.10.2 test @@ -56,13 +56,13 @@ commons-codec commons-codec - 1.5 + 1.17.0 org.slf4j slf4j-jdk14 - 1.6.1 + 2.0.13 @@ -97,11 +97,11 @@ org.apache.maven.plugins maven-compiler-plugin - 3.1 + 3.13.0 true - 1.7 - 1.7 + 1.8 + 1.8 false false diff --git a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ArchetypesTest.java b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ArchetypesTest.java index b42830ba54..5be312c314 100644 --- a/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ArchetypesTest.java +++ b/tests/release-test/src/test/java/org/glassfish/jersey/test/artifacts/ArchetypesTest.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 @@ -52,16 +52,21 @@ public void testPropertiesVersion() throws XmlPullParserException, IOException { continue; } // Update the names with the ones in Jersey - Map.Entry updatedEntry = updateEntry(pomEntry); // Check the properties are there - if (properties.getProperty(updatedEntry.getKey().toString()) == null) { + final String key = pomEntry.getKey().toString(); + + if (properties.getProperty(key) == null) { testResult.ok().append("Property ") .append(pomEntry.getKey().toString()) .append(" from ").append(pom).println(" not in Jersey"); failed = true; } // check the values - else if (!properties.getProperty(updatedEntry.getKey().toString()).equals(updatedEntry.getValue())) { + else if ( + //archetype property value can be a variable from the main pom.xml - check and exclude if so + !(properties.containsKey(key) && pomEntry.getValue().toString().contains(key)) + && !properties.getProperty(key).equals(pomEntry.getValue()) + ) { testResult.exception().append("The property ") .append(pomEntry.getKey().toString()) .append(" in archetype pom ") @@ -81,25 +86,4 @@ else if (!properties.getProperty(updatedEntry.getKey().toString()).equals(update } } - private Map.Entry updateEntry(Map.Entry pomEntry) { - if (pomEntry.getKey().equals("junit-jupiter.version")) { - return new Map.Entry() { - @Override - public Object getKey() { - return "junit5.version"; - } - - @Override - public Object getValue() { - return pomEntry.getValue(); - } - - @Override - public Object setValue(Object value) { - return value; - } - }; - } - return pomEntry; - } } From ed233c5af83901758d1ddc4e9555575c4c66986b Mon Sep 17 00:00:00 2001 From: jansupol <15908245+jansupol@users.noreply.github.com> Date: Tue, 18 Jun 2024 12:43:24 +0200 Subject: [PATCH 06/13] Prevent blowing connections number for reoccurring SSLContextFatories (#5677) Signed-off-by: jansupol --- .../client/internal/HttpUrlConnector.java | 40 +++-- .../jersey/client/SSLSocketFactoryTest.java | 157 ++++++++++++++++++ 2 files changed, 187 insertions(+), 10 deletions(-) create mode 100644 core-client/src/test/java/org/glassfish/jersey/client/SSLSocketFactoryTest.java 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 443349631d..350ad2b2a7 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/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..49110fd8af --- /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 javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.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); + } + } +} From c97f94456979e13d91db8bf4f0e3eed156f03a5b Mon Sep 17 00:00:00 2001 From: Vaibhav Vishal <36727272+vavishal@users.noreply.github.com> Date: Tue, 16 Jul 2024 13:03:50 +0530 Subject: [PATCH 07/13] Last-Modified header is garbled when accessing wadl document on Japanese locale (#5698) * Last-Modified header is garbled when accessing wadl document on Japanese locale Signed-off-by: Vaibhav Vishal --- .../server/wadl/internal/WadlResource.java | 7 ++++--- .../e2e/server/wadl/WadlResourceTest.java | 18 +++++++++++++++++- 2 files changed, 21 insertions(+), 4 deletions(-) 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 8f32cf3e1b..20fd4b5428 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, 2018 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 javax.ws.rs.GET; import javax.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/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlResourceTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlResourceTest.java index 0eddec69c3..7baf8c040e 100644 --- a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlResourceTest.java +++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/wadl/WadlResourceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2022 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 @@ -30,6 +30,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.concurrent.ExecutionException; @@ -108,6 +109,7 @@ import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -399,6 +401,20 @@ public void testLastModifiedGET() { assertTrue(r.getHeaders().containsKey("Last-modified")); } + @Test + public void testLastModifiedGETOnJPLocale() { + Locale defaultLocale = Locale.getDefault(); + try { + Locale.setDefault(new Locale("ja", "JP")); + final WebTarget target = target("/application.wadl"); + + final Response r = target.queryParam(WadlUtils.DETAILED_WADL_QUERY_PARAM, "true").request().get(Response.class); + assertDoesNotThrow(() -> r.getLastModified()); + } finally { + Locale.setDefault(defaultLocale); + } + } + @Test public void testLastModifiedOPTIONS() { final WebTarget target = target("/widgets/3/verbose"); From 6380dc536c2d5b7bb92938aac13ca061b49a04b0 Mon Sep 17 00:00:00 2001 From: jansupol Date: Wed, 3 Jul 2024 16:07:29 +0200 Subject: [PATCH 08/13] Prevent NPE in micrometer when there is no response & 404 Signed-off-by: jansupol --- .../micrometer/server/JerseyKeyValues.java | 21 +++++-- .../server/exception/JerseyKeyValuesTest.java | 62 +++++++++++++++++++ 2 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 ext/micrometer/src/test/java/org/glassfish/jersey/micrometer/server/exception/JerseyKeyValuesTest.java 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..8e73635132 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 javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response; + /** * Factory methods for {@link KeyValue KeyValues} associated with a request-response * exchange that is handled by Jersey server. @@ -82,15 +85,25 @@ 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.equals("/")) { 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..7f0358203c --- /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 javax.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)); + } +} From 80951a42235dddefad901c664b67ca4edfcb05d7 Mon Sep 17 00:00:00 2001 From: jansupol Date: Thu, 4 Jul 2024 11:13:46 +0200 Subject: [PATCH 09/13] Backport a fix from micrometer repo for this https://github.com/micrometer-metrics/micrometer/commit/66c1d4772019146b47ac27e4bcdd324000cedc7f Signed-off-by: jansupol --- .../glassfish/jersey/micrometer/server/JerseyKeyValues.java | 6 ++++++ 1 file changed, 6 insertions(+) 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 8e73635132..d8b6c3de96 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 @@ -41,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"); @@ -106,6 +109,9 @@ static KeyValue uri(RequestEvent event) { } } String matchingPattern = JerseyTags.getMatchingPattern(event); + if (matchingPattern == null) { + return URI_UNKNOWN; + } if (matchingPattern.equals("/")) { return URI_ROOT; } From 8174fede93025f7f7deac7b25f63f5893624a534 Mon Sep 17 00:00:00 2001 From: jansupol Date: Wed, 3 Jul 2024 10:40:10 +0200 Subject: [PATCH 10/13] Support Multipart with Buffered Entity and Netty Connector Signed-off-by: jansupol --- .../netty/connector/NettyConnector.java | 16 +++- .../connector/internal/NettyEntityWriter.java | 51 ++++++++--- .../e2e/client/connector/MultiPartTest.java | 86 ++++++++++++++++++- 3 files changed, 137 insertions(+), 16 deletions(-) diff --git a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java index afb18ea365..d1de3ac1c0 100644 --- a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java +++ b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java @@ -88,6 +88,9 @@ import org.glassfish.jersey.client.spi.AsyncConnectorCallback; import org.glassfish.jersey.client.spi.Connector; import org.glassfish.jersey.innate.VirtualThreadUtil; +import org.glassfish.jersey.internal.util.collection.LazyValue; +import org.glassfish.jersey.internal.util.collection.Value; +import org.glassfish.jersey.internal.util.collection.Values; import org.glassfish.jersey.message.internal.OutboundMessageContext; import org.glassfish.jersey.netty.connector.internal.NettyEntityWriter; @@ -103,6 +106,17 @@ class NettyConnector implements Connector { final Client client; final HashMap> connections = new HashMap<>(); + private static final LazyValue NETTY_VERSION = Values.lazy( + (Value) () -> { + String nettyVersion = null; + try { + nettyVersion = io.netty.util.Version.identify().values().iterator().next().artifactVersion(); + } catch (Throwable t) { + nettyVersion = "4.1.x"; + } + return "Netty " + nettyVersion; + }); + // If HTTP keepalive is enabled the value of "http.maxConnections" determines the maximum number // of idle connections that will be simultaneously kept alive, per destination. private static final String HTTP_KEEPALIVE_STRING = System.getProperty("http.keepAlive"); @@ -524,7 +538,7 @@ private String buildPathWithQueryParameters(URI requestUri) { @Override public String getName() { - return "Netty 4.1.x"; + return NETTY_VERSION.get(); } @Override diff --git a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/internal/NettyEntityWriter.java b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/internal/NettyEntityWriter.java index a9e70409f8..bcd3fd868c 100644 --- a/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/internal/NettyEntityWriter.java +++ b/connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/internal/NettyEntityWriter.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 @@ -24,8 +24,10 @@ import java.io.IOException; import java.io.OutputStream; +import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; /** * The Entity Writer is used to write entity in Netty. One implementation is delayed, @@ -196,10 +198,7 @@ private void _flush() throws IOException { for (Runnable runnable : delayedOps) { runnable.run(); } - - if (outputStream.b != null) { - writer.getOutputStream().write(outputStream.b, outputStream.off, outputStream.len); - } + outputStream._flush(); } } @@ -216,7 +215,7 @@ public OutputStream getOutputStream() { @Override public long getLength() { - return outputStream.len - outputStream.off; + return outputStream.writeLen; } @Override @@ -225,9 +224,9 @@ public Type getType() { } private class DelayedOutputStream extends OutputStream { - private byte[] b; - private int off; - private int len; + private final List 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/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/MultiPartTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/MultiPartTest.java index 613925cd31..54e70c0a47 100644 --- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/MultiPartTest.java +++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/MultiPartTest.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 @@ -16,11 +16,17 @@ package org.glassfish.jersey.tests.e2e.client.connector; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.HttpUrlConnectorProvider; +import org.glassfish.jersey.client.RequestEntityProcessing; import org.glassfish.jersey.client.spi.ConnectorProvider; import org.glassfish.jersey.jdk.connector.JdkConnectorProvider; import org.glassfish.jersey.jetty.connector.JettyConnectorProvider; +import org.glassfish.jersey.media.multipart.FormDataBodyPart; +import org.glassfish.jersey.media.multipart.FormDataMultiPart; import org.glassfish.jersey.netty.connector.NettyConnectorProvider; import org.glassfish.jersey.logging.LoggingFeature; import org.glassfish.jersey.media.multipart.BodyPart; @@ -32,6 +38,8 @@ import org.glassfish.jersey.test.JerseyTest; import org.glassfish.jersey.test.TestProperties; import org.glassfish.jersey.test.spi.TestHelper; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DynamicContainer; import org.junit.jupiter.api.Test; @@ -40,18 +48,27 @@ import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; import javax.ws.rs.core.Application; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.Response; +import javax.ws.rs.ext.Provider; +import javax.ws.rs.ext.WriterInterceptor; +import javax.ws.rs.ext.WriterInterceptorContext; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.logging.Handler; import java.util.logging.Level; +import java.util.logging.LogManager; import java.util.logging.Logger; public class MultiPartTest { @@ -129,5 +146,72 @@ public void testMultipart() { } } } + + @Test + public void testNettyBufferedMultipart() { +// setDebugLevel(Level.FINEST); + ClientConfig config = new ClientConfig(); + + config.connectorProvider(new NettyConnectorProvider()); + config.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.BUFFERED); + config.register(org.glassfish.jersey.media.multipart.MultiPartFeature.class); + config.register(new LoggingHandler(LogLevel.DEBUG)); + config.register(new LoggingInterceptor()); + config.property(ClientProperties.ASYNC_THREADPOOL_SIZE, 10); + config.property("jersey.config.client.logging.verbosity", LoggingFeature.Verbosity.PAYLOAD_TEXT); + config.property("jersey.config.client.logging.logger.level", Level.FINEST.toString()); + + Client client = ClientBuilder.newClient(config); + + FormDataMultiPart formData = new FormDataMultiPart(); + FormDataBodyPart bodyPart1 = new FormDataBodyPart("hello1", "{\"first\":\"firstLine\",\"second\":\"secondLine\"}", + MediaType.APPLICATION_JSON_TYPE); + formData.bodyPart(bodyPart1); + formData.bodyPart(new FormDataBodyPart("hello2", + "{\"first\":\"firstLine\",\"second\":\"secondLine\",\"third\":\"thirdLine\"}", + MediaType.APPLICATION_JSON_TYPE)); + formData.bodyPart(new FormDataBodyPart("hello3", + "{\"first\":\"firstLine\",\"second\":\"secondLine\",\"" + + "second\":\"secondLine\",\"second\":\"secondLine\",\"second\":\"secondLine\"}", + MediaType.APPLICATION_JSON_TYPE)); + formData.bodyPart(new FormDataBodyPart("plaintext", "hello")); + + Response response1 = client.target(target().getUri()).path("upload") + .request() + .post(Entity.entity(formData, formData.getMediaType())); + + MatcherAssert.assertThat(response1.getStatus(), Matchers.is(200)); + MatcherAssert.assertThat(response1.readEntity(String.class), + Matchers.stringContainsInOrder("first", "firstLine", "second", "secondLine")); + response1.close(); + client.close(); + } + + public static void setDebugLevel(Level newLvl) { + Logger rootLogger = LogManager.getLogManager().getLogger(""); + Handler[] handlers = rootLogger.getHandlers(); + rootLogger.setLevel(newLvl); + for (Handler h : handlers) { + h.setLevel(Level.ALL); + } + Logger nettyLogger = Logger.getLogger("io.netty"); + nettyLogger.setLevel(Level.FINEST); + } + + @Provider + public class LoggingInterceptor implements WriterInterceptor { + + @Override + public void aroundWriteTo(WriterInterceptorContext context) + throws IOException, WebApplicationException { + try { + MultivaluedMap headers = context.getHeaders(); + headers.forEach((key, val) -> System.out.println(key + ":" + val)); + context.proceed(); + } catch (Exception e) { + throw e; + } + } + } } } From 6fcec23407fe2ca2a665c82bf617b1ac821d72f6 Mon Sep 17 00:00:00 2001 From: jansupol Date: Tue, 2 Jul 2024 12:59:30 +0200 Subject: [PATCH 11/13] Wrap call of deprecated HttpServletResponse#setStatus into try catch Signed-off-by: jansupol --- .../jersey/servlet/ServletContainer.java | 24 +++++++++++++++++-- .../jersey/servlet/WebComponent.java | 3 +-- .../servlet/internal/ResponseWriter.java | 11 +++++---- 3 files changed, 29 insertions(+), 9 deletions(-) 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 038217db70..d4d5fbc184 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 ab4e927649..5cd2f21db1 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 @@ -404,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()); } 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 38301f898a..e166fe1fb2 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... From c4adbb3d605c1b8cc0521142b58e3ec0ad496fcf Mon Sep 17 00:00:00 2001 From: jansupol Date: Fri, 28 Jun 2024 15:59:12 +0200 Subject: [PATCH 12/13] Better explanation of missing jersey-hk2 module consequences. Signed-off-by: jansupol --- .../glassfish/jersey/client/internal/localization.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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. From bbeaa55aaab6736a268357a226ac6dc2fd136008 Mon Sep 17 00:00:00 2001 From: Maxim Nesen Date: Wed, 17 Jul 2024 10:22:19 +0200 Subject: [PATCH 13/13] After-merge Signed-off-by: Maxim Nesen --- core-server/pom.xml | 1 + pom.xml | 4 +--- tests/e2e-client/pom.xml | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core-server/pom.xml b/core-server/pom.xml index 5bb8b5c4f4..263ab483d8 100644 --- a/core-server/pom.xml +++ b/core-server/pom.xml @@ -259,6 +259,7 @@
${jboss.vfs.jdk8.version} + ${jboss.logging.8.version}
diff --git a/pom.xml b/pom.xml index 6b560ea773..b37f5c03e9 100644 --- a/pom.xml +++ b/pom.xml @@ -2240,7 +2240,6 @@ 33.1.0-jre 2.2 - 1.4.14 2.10.0 org.glassfish.hk2.*;version="[2.5,4)" org.jvnet.hk2.*;version="[2.5,4)" @@ -2248,7 +2247,6 @@ 5.3.1 2.17.1 3.30.2-GA - 3.5.3.Final 3.4.3.Final 1.19.3 ${jersey1.version} @@ -2325,7 +2323,7 @@ 3.0 3.0.0 org.eclipse.jetty.*;version="[11,15)" - 11.0.20 + 11.0.22 11.0.15 9.4.54.v20240208 11.0.20 diff --git a/tests/e2e-client/pom.xml b/tests/e2e-client/pom.xml index e0a036b36e..a8e9f41157 100644 --- a/tests/e2e-client/pom.xml +++ b/tests/e2e-client/pom.xml @@ -237,6 +237,7 @@ org/glassfish/jersey/tests/e2e/client/connector/proxy/Proxy*Test.java + org/glassfish/jersey/tests/e2e/client/connector/NoContentLengthTest.java org/glassfish/jersey/tests/e2e/client/nettyconnector/Expect100ContinueTest.java