Merge commit 'c42a6a214b9cbee8b4bd9b27e3693215403adadb' into 3.x Signed-off-by: Maxim Nesen <maxim.nesen@oracle.com>
diff --git a/connectors/helidon-connector/src/test/java/org/glassfish/jersey/helidon/connector/MetaInfOverrideTest.java b/connectors/helidon-connector/src/test/java/org/glassfish/jersey/helidon/connector/MetaInfOverrideTest.java new file mode 100644 index 0000000..0483bdd --- /dev/null +++ b/connectors/helidon-connector/src/test/java/org/glassfish/jersey/helidon/connector/MetaInfOverrideTest.java
@@ -0,0 +1,99 @@ +/* + * Copyright (c) 2023 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.helidon.connector; + +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.HttpUrlConnectorProvider; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.ClientRequestContext; +import jakarta.ws.rs.client.ClientRequestFilter; +import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.Response; +import java.io.IOException; + +// The Helidon jar has META-INF set +// Test of override +class MetaInfOverrideTest extends JerseyTest { + + @Path("/origin") + public static class UserAgentServer { + @GET + public String get(@Context HttpHeaders headers) { + return headers.getHeaderString(HttpHeaders.USER_AGENT); + } + } + + @Override + protected Application configure() { + return new ResourceConfig(UserAgentServer.class); + } + + @Test + void defaultMetaInfTest() { + try (Response r = target("origin").request().get()) { + Assertions.assertEquals(200, r.getStatus()); + Assertions.assertTrue(r.readEntity(String.class).contains("Helidon")); + } + } + + @Test + void overrideMetaInfTest() { + ClientConfig config = new ClientConfig(); + config.connectorProvider(new HttpUrlConnectorProvider()); + try (Response r = ClientBuilder.newClient(config).target(target("origin").getUri()).request().get()) { + Assertions.assertEquals(200, r.getStatus()); + r.bufferEntity(); + System.out.println(r.readEntity(String.class)); + Assertions.assertTrue(r.readEntity(String.class).contains("HttpUrlConnection")); + } + } + + @Test + void overrideMetaInfByOtherConfigPropertyTest() { + ClientConfig config = new ClientConfig(); + config.property(ClientProperties.CONNECTOR_PROVIDER, "org.glassfish.jersey.client.HttpUrlConnectorProvider"); + try (Response r = ClientBuilder.newClient(config).target(target("origin").getUri()).request().get()) { + Assertions.assertEquals(200, r.getStatus()); + r.bufferEntity(); + System.out.println(r.readEntity(String.class)); + Assertions.assertTrue(r.readEntity(String.class).contains("HttpUrlConnection")); + } + } + + @Test + void overrideMetaInfByThePropertyTest() { + try (Response r = ClientBuilder.newBuilder() + .property(ClientProperties.CONNECTOR_PROVIDER, "org.glassfish.jersey.client.HttpUrlConnectorProvider") + .build() + .target(target("origin").getUri()).request().get()) { + Assertions.assertEquals(200, r.getStatus()); + r.bufferEntity(); + System.out.println(r.readEntity(String.class)); + Assertions.assertTrue(r.readEntity(String.class).contains("HttpUrlConnection")); + } + } +}
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 71f38ea..d460867 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
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2023 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 @@ -189,6 +189,9 @@ if (content.isReadable()) { content.retain(); + if (nis == null) { + nis = new NettyInputStream(); + } nis.publish(content); }
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java index 909af8d..cd90578 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientProperties.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023 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,8 @@ import org.glassfish.jersey.internal.util.PropertiesHelper; import org.glassfish.jersey.internal.util.PropertyAlias; +import jakarta.ws.rs.client.ClientBuilder; + /** * Jersey client implementation configuration properties. * @@ -444,7 +446,7 @@ EXPECT_100_CONTINUE_THRESHOLD_SIZE = "jersey.config.client.request.expect.100.continue.threshold.size"; /** - * Default threshold size (64kb) after which which Expect:100-Continue header would be applied before + * Default threshold size (64kb) after which Expect:100-Continue header would be applied before * the main request. * * @since 2.32 @@ -463,6 +465,22 @@ */ public static final String QUERY_PARAM_STYLE = "jersey.config.client.uri.query.param.style"; + /** + * Sets the {@link org.glassfish.jersey.client.spi.ConnectorProvider} class. Overrides the value from META-INF/services. + * + * <p> + * The value MUST be an instance of {@code String}. + * </p> + * <p> + * The property is recognized by {@link ClientBuilder}. + * </p> + * <p> + * The name of the configuration property is <tt>{@value}</tt>. + * </p> + * @since 2.40 + */ + public static final String CONNECTOR_PROVIDER = "jersey.config.client.connector.provider"; + private ClientProperties() { // prevents instantiation }
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/JerseyClientBuilder.java b/core-client/src/main/java/org/glassfish/jersey/client/JerseyClientBuilder.java index 69b6265..9277919 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/JerseyClientBuilder.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/JerseyClientBuilder.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023 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,6 +16,7 @@ package org.glassfish.jersey.client; +import java.security.AccessController; import java.security.KeyStore; import java.util.Collections; import java.util.LinkedList; @@ -32,9 +33,13 @@ import javax.net.ssl.SSLContext; import org.glassfish.jersey.SslConfigurator; +import org.glassfish.jersey.client.innate.inject.NonInjectionManager; import org.glassfish.jersey.client.internal.LocalizationMessages; import org.glassfish.jersey.client.spi.ClientBuilderListener; +import org.glassfish.jersey.client.spi.ConnectorProvider; import org.glassfish.jersey.internal.ServiceFinder; +import org.glassfish.jersey.internal.config.ExternalPropertiesConfigurationFactory; +import org.glassfish.jersey.internal.util.ReflectionHelper; import org.glassfish.jersey.internal.util.collection.UnsafeValue; import org.glassfish.jersey.internal.util.collection.Values; import org.glassfish.jersey.model.internal.RankedComparator; @@ -186,6 +191,9 @@ @Override public JerseyClient build() { + ExternalPropertiesConfigurationFactory.configure(this.config); + setConnectorFromProperties(); + if (sslContext != null) { return new JerseyClient(config, sslContext, hostnameVerifier, null); } else if (sslConfigurator != null) { @@ -204,6 +212,20 @@ } } + private void setConnectorFromProperties() { + final Object connectorClass = config.getProperty(ClientProperties.CONNECTOR_PROVIDER); + if (connectorClass != null) { + if (String.class.isInstance(connectorClass)) { + Class<? extends ConnectorProvider> clazz + = AccessController.doPrivileged(ReflectionHelper.classForNamePA((String) connectorClass)); + final ConnectorProvider connectorProvider = new NonInjectionManager().justCreate(clazz); + config.connectorProvider(connectorProvider); + } else { + throw new IllegalArgumentException(); + } + } + } + @Override public ClientConfig getConfiguration() { return config;
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SniConfigurator.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SniConfigurator.java index 39a339d..596c587 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SniConfigurator.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/http/SniConfigurator.java
@@ -16,6 +16,8 @@ package org.glassfish.jersey.client.innate.http; +import org.glassfish.jersey.client.internal.LocalizationMessages; + import javax.net.ssl.SNIHostName; import javax.net.ssl.SNIServerName; import javax.net.ssl.SSLEngine; @@ -27,12 +29,14 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.logging.Logger; /** * A unified routines to set {@link SNIHostName} for the {@link javax.net.ssl.SSLContext}. * To be reused in connectors. */ final class SniConfigurator { + private static final Logger LOGGER = Logger.getLogger(SniConfigurator.class.getName()); private final String hostName; private SniConfigurator(String hostName) { this.hostName = hostName; @@ -85,6 +89,7 @@ SSLParameters sslParameters = sslEngine.getSSLParameters(); updateSSLParameters(sslParameters); sslEngine.setSSLParameters(sslParameters); + LOGGER.fine(LocalizationMessages.SNI_ON_SSLENGINE()); } /** @@ -95,6 +100,7 @@ SSLParameters sslParameters = sslSocket.getSSLParameters(); updateSSLParameters(sslParameters); sslSocket.setSSLParameters(sslParameters); + LOGGER.fine(LocalizationMessages.SNI_ON_SSLSOCKET()); } private SSLParameters updateSSLParameters(SSLParameters sslParameters) { @@ -103,6 +109,7 @@ serverNames.add(serverName); sslParameters.setServerNames(serverNames); + LOGGER.finer(LocalizationMessages.SNI_UPDATE_SSLPARAMS(hostName)); return sslParameters; }
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionManager.java b/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionManager.java index 7062bab..047bba8 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionManager.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/innate/inject/NonInjectionManager.java
@@ -418,10 +418,31 @@ } ClassBindings<T> classBindings = classBindings(createMe); - return classBindings.create(); + return classBindings.create(true); } - private <T> T justCreate(Class<T> createMe) { + @Override + public <T> T createAndInitialize(Class<T> createMe) { + checkShutdown(); + + if (InjectionManager.class.equals(createMe)) { + return (T) this; + } + if (RequestScope.class.equals(createMe)) { + if (!isRequestScope) { + isRequestScope = true; + return (T) new NonInjectionRequestScope(); + } else { + throw new IllegalStateException(LocalizationMessages.NONINJECT_REQUESTSCOPE_CREATED()); + } + } + + ClassBindings<T> classBindings = classBindings(createMe); + T t = classBindings.create(false); + return t != null ? t : justCreate(createMe); + } + + public <T> T justCreate(Class<T> createMe) { T result = null; try { Constructor<T> mostArgConstructor = findConstructor(createMe); @@ -493,11 +514,6 @@ } @Override - public <T> T createAndInitialize(Class<T> createMe) { - return justCreate(createMe); - } - - @Override public void inject(Object injectMe) { Method postConstruct = getAnnotatedMethod(injectMe, PostConstruct.class); if (postConstruct != null) { @@ -750,7 +766,7 @@ return t; } - X create() { + X create(boolean throwWhenNoBinding) { _checkUnique(); if (!instanceBindings.isEmpty()) { return _getInstance(instanceBindings.get(0)); @@ -762,7 +778,11 @@ return _create(supplierClassBindings.get(0)); } - throw new IllegalStateException(LocalizationMessages.NONINJECT_NO_BINDING(type)); + if (throwWhenNoBinding) { + throw new IllegalStateException(LocalizationMessages.NONINJECT_NO_BINDING(type)); + } else { + return null; + } } protected X getInstance() { @@ -770,7 +790,7 @@ if (instance != null) { return instance; } - return create(); + return create(true); } List<X> allInstances() { @@ -931,7 +951,7 @@ @SuppressWarnings("unchecked") @Override - T create() { + T create(boolean throwWhenNoBinding) { if (ParameterizedType.class.isInstance(type)) { ParameterizedType pt = (ParameterizedType) type; if (Provider.class.equals(pt.getRawType())) { @@ -955,7 +975,7 @@ }; } } - return super.create(); + return super.create(throwWhenNoBinding); } }
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 c7e0ac2..2fdb7e9 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
@@ -345,7 +345,13 @@ final HttpURLConnection uc; final Optional<ClientProxy> proxy = ClientProxy.proxyFromRequest(request); final SSLParamConfigurator sniConfig = SSLParamConfigurator.builder().request(request).build(); - final URI sniUri = sniConfig.isSNIRequired() ? sniConfig.toIPRequestUri() : request.getUri(); + final URI sniUri; + if (sniConfig.isSNIRequired()) { + sniUri = sniConfig.toIPRequestUri(); + LOGGER.fine(LocalizationMessages.SNI_URI_REPLACED(sniUri.getHost(), request.getUri().getHost())); + } else { + sniUri = request.getUri(); + } proxy.ifPresent(clientProxy -> ClientProxy.setBasicAuthorizationHeader(request.getHeaders(), proxy.get())); uc = this.connectionFactory.getConnection(sniUri.toURL(), proxy.isPresent() ? proxy.get().proxy() : null);
diff --git a/core-client/src/main/resources/org/glassfish/jersey/client/internal/jdkconnector/localization.properties b/core-client/src/main/resources/org/glassfish/jersey/client/internal/jdkconnector/localization.properties deleted file mode 100644 index e8f0342..0000000 --- a/core-client/src/main/resources/org/glassfish/jersey/client/internal/jdkconnector/localization.properties +++ /dev/null
@@ -1,73 +0,0 @@ -# -# Copyright (c) 2017, 2018 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 -# - -read.listener.set.only.once="Read listener can be set only once." -async.operation.not.supported="Operation not supported in synchronous mode." -sync.operation.not.supported="Operation not supported in asynchronous mode." -write.when.not.ready="Asynchronous write called when stream is in non-ready state." -stream.closed.for.input="This stream has already been closed for input." -write.listener.set.only.once="Write listener can be set only once." -stream.closed="The stream has been closed." -writing.failed="Writing data failed" -buffer.incorrect.length="Buffer passed for encoding is neither a multiple of chunkSize nor smaller than chunkSize." -connector.configuration="Connector configuration: {0}." -negative.chunk.size="Configured chunk size is negative: {0}, using default value: {1}." -timeout.receiving.response="Timeout receiving response." -timeout.receiving.response.body="Timeout receiving response body." -closed.while.sending.request="Connection closed by the server while sending request". -closed.while.receiving.response="Connection closed by the server while receiving response." -closed.while.receiving.body="Connection closed by the server while receiving response body." -connection.closed="Connection closed by the server." -closed.by.client.while.sending="Connection closed by the client while sending request." -closed.by.client.while.receiving="Connection closed by the client while receiving response." -closed.by.client.while.receiving.body="Connection closed by the client while receiving response body." -connection.timeout="Connection timed out." -connection.changing.state="HTTP connection {0}:{1} changing state {2} -> {3}." -unexpected.data.in.buffer="Unexpected data remain in the buffer after the HTTP response has been parsed." -http.initial.line.overflow="HTTP packet initial line is too large." -http.packet.header.overflow="HTTP packet header is too large." -http.negative.content.length="Content length cannot be less than 0." -http.invalid.content.length="Invalid format of content length code." -http.request.no.body="This HTTP request does not have a body." -http.request.no.buffered.body="Buffered body is available only in buffered body mode." -http.request.body.size.not.available="Body size is not available in chunked body mode." -proxy.user.name.missing="User name is missing" -proxy.password.missing="Password is missing" -proxy.qop.no.supported="The 'qop' (quality of protection) = {0} extension requested by the server is not supported. Cannot authenticate against the server using Http Digest Authentication." -proxy.407.twice="Received 407 for the second time." -proxy.fail.auth.header="Creating authorization header failed." -proxy.connect.fail="Connecting to proxy failed with status {0}." -proxy.missing.auth.header="Proxy-Authenticate header value is missing or empty." -proxy.unsupported.scheme="Unsupported scheme: {0}." -redirect.no.location="Received redirect that does not contain a location or the location is empty." -redirect.error.determining.location="Error determining redirect location." -redirect.infinite.loop="Infinite loop in chained redirects detected." -redirect.limit.reached="Max chained redirect limit ({0}) exceeded." -ssl.session.closed="SSL session has been closed." -http.body.size.overflow="Body size exceeds declared size" -http.invalid.chunk.size.hex.value="Invalid byte representing a hex value within a chunk length encountered : {0}" -http.unexpected.chunk.header="Unexpected HTTP chunk header." -http.chunk.encoding.prefix.overflow="The chunked encoding length prefix is too large." -http.trailer.header.overflow="The chunked encoding trailer header is too large." -transport.connection.not.closed="Could not close a connection." -transport.set.class.loader.failed="Cannot set thread context class loader." -transport.executor.closed="Cannot set thread context class loader." -transport.executor.queue.limit.reached="A limit of client thread pool queue has been reached." -thread.pool.max.size.too.small="Max thread pool size cannot be smaller than 3." -thread.pool.core.size.too.small="Core thread pool size cannot be smaller than 0." -http.connection.establishing.illegal.state="Cannot try to establish connection if the connection is in other than CREATED state\ - . Current state: {0}. -http.connection.not.idle="Http request cannot be sent over a connection that is in other state than IDLE. Current state: {0}"
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 ee80184..291ac98 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
@@ -83,6 +83,10 @@ restricted.header.property.setting.true=Restricted headers are enabled using [{0}] system property(setting only takes effect on\ connections created after the property has been set/changed). request.entity.already.written=The entity was already written in this request. The entity can be written (serialized into the output stream) only once per a request. +sni.on.sslsocket=Setting SNIServerName on SSLSocket +sni.on.sslengine=Setting SNIServerName on SSLEngine +sni.uri.replaced=HTTP Request sent with request to IP address {0} rather than the hostname {1}. +sni.update.sslparams=Updating SSLParameters for SNIServerName={0}. unexpected.error.response.processing=Unexpected error during response processing. use.encoding.ignored=Value {1} of {0} client property will be ignored as it is not a valid supported encoding. \ Valid supported encodings are: {2}
diff --git a/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java b/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java index d5a1658..e71e5e1 100644 --- a/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java +++ b/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023 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 @@ -305,6 +305,22 @@ public static final String JSON_JACKSON_DISABLED_MODULES_SERVER = "jersey.config.server.json.jackson.disabled.modules"; /** + * <p> + * Force the {@link jakarta.ws.rs.ext.ParamConverter} to throw {@link IllegalArgumentException} as mandated in javadoc. + * Must be convertible to {@link Boolean} value. + * </p> + * <p> + * Internally the {@code Exception} is caught by Jersey and usually converted to {@code null}. + * Therefore, the default value is set to {@code false} to speed-up the conversion. + * </p> + * <p> + * The name of the configuration property is <tt>{@value}</tt>. + * </p> + * @since 2.40 + */ + public static final String PARAM_CONVERTERS_THROW_IAE = "jersey.config.paramconverters.throw.iae"; + + /** * Prevent instantiation. */ private CommonProperties() {
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/config/ExternalPropertiesAutoDiscoverable.java b/core-common/src/main/java/org/glassfish/jersey/internal/config/ExternalPropertiesAutoDiscoverable.java deleted file mode 100644 index 8665e2c..0000000 --- a/core-common/src/main/java/org/glassfish/jersey/internal/config/ExternalPropertiesAutoDiscoverable.java +++ /dev/null
@@ -1,35 +0,0 @@ -/* - * Copyright (c) 2019, 2020 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.internal.config; - -import org.glassfish.jersey.internal.spi.AutoDiscoverable; - -import jakarta.annotation.Priority; -import jakarta.ws.rs.ConstrainedTo; -import jakarta.ws.rs.RuntimeType; -import jakarta.ws.rs.core.FeatureContext; - -@ConstrainedTo(RuntimeType.CLIENT) //server is configured directly in ResourceConfig -@Priority(AutoDiscoverable.DEFAULT_PRIORITY) -public class ExternalPropertiesAutoDiscoverable implements AutoDiscoverable { - @Override - public void configure(FeatureContext context) { - if (!context.getConfiguration().isRegistered(ExternalPropertiesConfigurationFeature.class)) { - context.register(ExternalPropertiesConfigurationFeature.class); - } - } -} \ No newline at end of file
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/config/ExternalPropertiesConfigurationFeature.java b/core-common/src/main/java/org/glassfish/jersey/internal/config/ExternalPropertiesConfigurationFeature.java deleted file mode 100644 index 1c10c1c..0000000 --- a/core-common/src/main/java/org/glassfish/jersey/internal/config/ExternalPropertiesConfigurationFeature.java +++ /dev/null
@@ -1,29 +0,0 @@ -/* - * Copyright (c) 2019, 2020 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.internal.config; - -import jakarta.ws.rs.core.Feature; -import jakarta.ws.rs.core.FeatureContext; - -public class ExternalPropertiesConfigurationFeature implements Feature { - - @Override - public boolean configure(FeatureContext configurableContext) { - return ExternalPropertiesConfigurationFactory.configure(configurableContext); - } - -} \ No newline at end of file
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/inject/ParamConverters.java b/core-common/src/main/java/org/glassfish/jersey/internal/inject/ParamConverters.java index b0984f5..0a9aaba 100644 --- a/core-common/src/main/java/org/glassfish/jersey/internal/inject/ParamConverters.java +++ b/core-common/src/main/java/org/glassfish/jersey/internal/inject/ParamConverters.java
@@ -35,10 +35,12 @@ import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.ext.ParamConverter; import jakarta.ws.rs.ext.ParamConverterProvider; +import jakarta.ws.rs.core.Configuration; import jakarta.ws.rs.core.Context; import jakarta.inject.Inject; import jakarta.inject.Singleton; +import org.glassfish.jersey.CommonProperties; import org.glassfish.jersey.internal.LocalizationMessages; import org.glassfish.jersey.internal.util.ReflectionHelper; import org.glassfish.jersey.internal.util.collection.ClassTypePair; @@ -55,12 +57,32 @@ @Singleton public class ParamConverters { - private abstract static class AbstractStringReader<T> implements ParamConverter<T> { + private static class ParamConverterCompliance { + protected final boolean canReturnNull; + + private ParamConverterCompliance(boolean canReturnNull) { + this.canReturnNull = canReturnNull; + } + + protected <T> T nullOrThrow() { + if (canReturnNull) { + return null; + } else { + throw new IllegalArgumentException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value")); + } + } + } + + private abstract static class AbstractStringReader<T> extends ParamConverterCompliance implements ParamConverter<T> { + + private AbstractStringReader(boolean canReturnNull) { + super(canReturnNull); + } @Override public T fromString(final String value) { if (value == null) { - throw new IllegalArgumentException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value")); + return nullOrThrow(); } try { return _fromString(value); @@ -85,7 +107,7 @@ @Override public String toString(final T value) throws IllegalArgumentException { if (value == null) { - throw new IllegalArgumentException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value")); + return nullOrThrow(); } return value.toString(); } @@ -97,7 +119,11 @@ * by invoking a single {@code String} parameter constructor on the target type. */ @Singleton - public static class StringConstructor implements ParamConverterProvider { + public static class StringConstructor extends ParamConverterCompliance implements ParamConverterProvider { + + private StringConstructor(boolean canReturnNull) { + super(canReturnNull); + } @Override public <T> ParamConverter<T> getConverter(final Class<T> rawType, @@ -106,7 +132,7 @@ final Constructor constructor = AccessController.doPrivileged(ReflectionHelper.getStringConstructorPA(rawType)); - return (constructor == null) ? null : new AbstractStringReader<T>() { + return (constructor == null) ? null : new AbstractStringReader<T>(canReturnNull) { @Override protected T _fromString(final String value) throws Exception { @@ -122,7 +148,11 @@ * by invoking a static {@code valueOf(String)} method on the target type. */ @Singleton - public static class TypeValueOf implements ParamConverterProvider { + public static class TypeValueOf extends ParamConverterCompliance implements ParamConverterProvider { + + private TypeValueOf(boolean canReturnNull) { + super(canReturnNull); + } @Override public <T> ParamConverter<T> getConverter(final Class<T> rawType, @@ -131,7 +161,7 @@ final Method valueOf = AccessController.doPrivileged(ReflectionHelper.getValueOfStringMethodPA(rawType)); - return (valueOf == null) ? null : new AbstractStringReader<T>() { + return (valueOf == null) ? null : new AbstractStringReader<T>(canReturnNull) { @Override public T _fromString(final String value) throws Exception { @@ -146,7 +176,11 @@ * by invoking a static {@code fromString(String)} method on the target type. */ @Singleton - public static class TypeFromString implements ParamConverterProvider { + public static class TypeFromString extends ParamConverterCompliance implements ParamConverterProvider { + + private TypeFromString(boolean canReturnNull) { + super(canReturnNull); + } @Override public <T> ParamConverter<T> getConverter(final Class<T> rawType, @@ -155,7 +189,7 @@ final Method fromStringMethod = AccessController.doPrivileged(ReflectionHelper.getFromStringStringMethodPA(rawType)); - return (fromStringMethod == null) ? null : new AbstractStringReader<T>() { + return (fromStringMethod == null) ? null : new AbstractStringReader<T>(canReturnNull) { @Override public T _fromString(final String value) throws Exception { @@ -172,6 +206,10 @@ @Singleton public static class TypeFromStringEnum extends TypeFromString { + private TypeFromStringEnum(boolean canReturnNull) { + super(canReturnNull); + } + @Override public <T> ParamConverter<T> getConverter(final Class<T> rawType, final Type genericType, @@ -181,7 +219,11 @@ } @Singleton - public static class CharacterProvider implements ParamConverterProvider { + public static class CharacterProvider extends ParamConverterCompliance implements ParamConverterProvider { + + private CharacterProvider(boolean canReturnNull) { + super(canReturnNull); + } @Override public <T> ParamConverter<T> getConverter(final Class<T> rawType, @@ -192,8 +234,7 @@ @Override public T fromString(String value) { if (value == null || value.isEmpty()) { - return null; - // throw new IllegalStateException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value")); + return CharacterProvider.this.nullOrThrow(); } if (value.length() == 1) { @@ -206,7 +247,7 @@ @Override public String toString(T value) { if (value == null) { - throw new IllegalArgumentException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value")); + return CharacterProvider.this.nullOrThrow(); } return value.toString(); } @@ -223,7 +264,11 @@ * {@link HttpDateFormat http date formatter} utility class. */ @Singleton - public static class DateProvider implements ParamConverterProvider { + public static class DateProvider extends ParamConverterCompliance implements ParamConverterProvider { + + private DateProvider(boolean canReturnNull) { + super(canReturnNull); + } @Override public <T> ParamConverter<T> getConverter(final Class<T> rawType, @@ -234,7 +279,7 @@ @Override public T fromString(final String value) { if (value == null) { - throw new IllegalArgumentException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value")); + return DateProvider.this.nullOrThrow(); } try { return rawType.cast(HttpDateFormat.readDate(value)); @@ -246,7 +291,7 @@ @Override public String toString(final T value) throws IllegalArgumentException { if (value == null) { - throw new IllegalArgumentException(LocalizationMessages.METHOD_PARAMETER_CANNOT_BE_NULL("value")); + return DateProvider.this.nullOrThrow(); } return value.toString(); } @@ -259,12 +304,13 @@ * by invoking {@link ParamConverterProvider}. */ @Singleton - public static class OptionalCustomProvider implements ParamConverterProvider { + public static class OptionalCustomProvider extends ParamConverterCompliance implements ParamConverterProvider { // Delegates to this provider when the type of Optional is extracted. private final InjectionManager manager; - public OptionalCustomProvider(InjectionManager manager) { + public OptionalCustomProvider(InjectionManager manager, boolean canReturnNull) { + super(canReturnNull); this.manager = manager; } @@ -294,7 +340,7 @@ * In this case we don't send Optional.empty() because 'value' is not null. * But we return null because the provider didn't find how to parse it. */ - return null; + return nullOrThrow(); } } @@ -409,17 +455,20 @@ * Create new aggregated {@link ParamConverterProvider param converter provider}. */ @Inject - public AggregatedProvider(@Context InjectionManager manager) { + public AggregatedProvider(@Context InjectionManager manager, @Context Configuration configuration) { + boolean canThrowNull = !CommonProperties.getValue(configuration.getProperties(), + CommonProperties.PARAM_CONVERTERS_THROW_IAE, + Boolean.FALSE); this.providers = new ParamConverterProvider[] { // ordering is important (e.g. Date provider must be executed before String Constructor // as Date has a deprecated String constructor - new DateProvider(), - new TypeFromStringEnum(), - new TypeValueOf(), - new CharacterProvider(), - new TypeFromString(), - new StringConstructor(), - new OptionalCustomProvider(manager), + new DateProvider(canThrowNull), + new TypeFromStringEnum(canThrowNull), + new TypeValueOf(canThrowNull), + new CharacterProvider(canThrowNull), + new TypeFromString(canThrowNull), + new StringConstructor(canThrowNull), + new OptionalCustomProvider(manager, canThrowNull), new OptionalProvider() }; }
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/util/ReflectionHelper.java b/core-common/src/main/java/org/glassfish/jersey/internal/util/ReflectionHelper.java index 2bd5e39..6383095 100644 --- a/core-common/src/main/java/org/glassfish/jersey/internal/util/ReflectionHelper.java +++ b/core-common/src/main/java/org/glassfish/jersey/internal/util/ReflectionHelper.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2023 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,7 @@ import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Array; import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; import java.lang.reflect.Field; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Member; @@ -444,7 +445,7 @@ * @see AccessController#doPrivileged(java.security.PrivilegedAction) */ public static PrivilegedAction setAccessibleMethodPA(final Method m) { - if (Modifier.isPublic(m.getModifiers())) { + if (isPublic(m)) { return NoOpPrivilegedACTION; } @@ -461,6 +462,24 @@ } /** + * Return {@code true} iff the method is public. + * @param clazz The method in question + * @return {@code true} if mod includes the public modifier; {@code false} otherwise. + */ + public static boolean isPublic(Class<?> clazz) { + return Modifier.isPublic(clazz.getModifiers()); + } + + /** + * Return {@code true} iff the executable is public. + * @param executable The executable in question + * @return {@code true} if the executable includes the public modifier; {@code false} otherwise. + */ + public static boolean isPublic(Executable executable) { + return Modifier.isPublic(executable.getModifiers()); + } + + /** * Get the list of classes that represent the type arguments of a * {@link ParameterizedType parameterized} input type. * <p/> @@ -879,8 +898,7 @@ * @return {@code true} if the method is {@code getter}, {@code false} otherwise. */ public static boolean isGetter(final Method method) { - if (method.getParameterTypes().length == 0 - && Modifier.isPublic(method.getModifiers())) { + if (method.getParameterTypes().length == 0 && isPublic(method)) { final String methodName = method.getName(); if (methodName.startsWith("get") && methodName.length() > 3) { @@ -921,7 +939,7 @@ * @return {@code true} if the method is {@code setter}, {@code false} otherwise. */ public static boolean isSetter(final Method method) { - return Modifier.isPublic(method.getModifiers()) + return isPublic(method) && void.class.equals(method.getReturnType()) && method.getParameterTypes().length == 1 && method.getName().startsWith("set");
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/GuardianStringKeyMultivaluedMap.java b/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/GuardianStringKeyMultivaluedMap.java index 358a329..1ca2549 100644 --- a/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/GuardianStringKeyMultivaluedMap.java +++ b/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/GuardianStringKeyMultivaluedMap.java
@@ -381,6 +381,24 @@ final List<V> sublist = guarded.subList(fromIndex, toIndex); return sublist != null ? new GuardianList<>(sublist, guard) : sublist; } + + @Override + public String toString() { + return guarded.toString(); + } + + @Override + public boolean equals(Object obj) { + if (GuardianList.class.isInstance(obj)) { + return guarded.equals(((GuardianList) obj).guarded); + } + return guarded.equals(obj); + } + + @Override + public int hashCode() { + return guarded.hashCode(); + } } private static class GuardianIterator<V> extends MutableGuardian<V> implements Iterator<V> { @@ -411,6 +429,11 @@ public void forEachRemaining(Consumer<? super V> action) { guarded.forEachRemaining(action); } + + @Override + public String toString() { + return guarded.toString(); + } } private static class GuardianListIterator<V> extends GuardianIterator<V> implements ListIterator<V> {
diff --git a/core-common/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable b/core-common/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable index abc1825..371b37b 100644 --- a/core-common/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable +++ b/core-common/src/main/resources/META-INF/services/org.glassfish.jersey.internal.spi.AutoDiscoverable
@@ -1,2 +1 @@ -org.glassfish.jersey.logging.LoggingFeatureAutoDiscoverable -org.glassfish.jersey.internal.config.ExternalPropertiesAutoDiscoverable \ No newline at end of file +org.glassfish.jersey.logging.LoggingFeatureAutoDiscoverable \ No newline at end of file
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ContainerResponse.java b/core-server/src/main/java/org/glassfish/jersey/server/ContainerResponse.java index 0c7020d..bd7f7a3 100644 --- a/core-server/src/main/java/org/glassfish/jersey/server/ContainerResponse.java +++ b/core-server/src/main/java/org/glassfish/jersey/server/ContainerResponse.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023 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,8 @@ import java.lang.annotation.Annotation; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; import java.net.URI; import java.util.Date; import java.util.Locale; @@ -308,6 +310,18 @@ if (parameterizedType.getRawType().equals(GenericEntity.class)) { t = parameterizedType.getActualTypeArguments()[0]; } + } else if (type instanceof TypeVariable) { + final TypeVariable typeVariable = (TypeVariable) type; + final Type[] bounds = typeVariable.getBounds(); + if (bounds.length == 1) { + t = bounds[0]; + } + } else if (type instanceof WildcardType) { + final WildcardType wildcardType = (WildcardType) type; + final Type[] bounds = wildcardType.getUpperBounds(); + if (bounds.length == 1) { + t = bounds[0]; + } } messageContext.setEntityType(t);
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/model/internal/AbstractJavaResourceMethodDispatcher.java b/core-server/src/main/java/org/glassfish/jersey/server/model/internal/AbstractJavaResourceMethodDispatcher.java index 0a3d6a3..b54300a 100644 --- a/core-server/src/main/java/org/glassfish/jersey/server/model/internal/AbstractJavaResourceMethodDispatcher.java +++ b/core-server/src/main/java/org/glassfish/jersey/server/model/internal/AbstractJavaResourceMethodDispatcher.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2023 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 @@ -32,6 +32,7 @@ import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.SecurityContext; +import org.glassfish.jersey.internal.util.ReflectionHelper; import org.glassfish.jersey.message.internal.OutboundJaxrsResponse; import org.glassfish.jersey.message.internal.OutboundMessageContext; import org.glassfish.jersey.message.internal.TracingLogger; @@ -68,12 +69,23 @@ AbstractJavaResourceMethodDispatcher(final Invocable resourceMethod, final InvocationHandler methodHandler, final ConfiguredValidator validator) { - this.method = resourceMethod.getDefinitionMethod(); + this.method = getPublic(resourceMethod.getHandlingMethod(), resourceMethod.getDefinitionMethod()); this.methodHandler = methodHandler; this.resourceMethod = resourceMethod; this.validator = validator; } + private Method getPublic(Method handlingMethod, Method definitionMethod) { + if (handlingMethod == definitionMethod) { + return handlingMethod; + } + + boolean publicHandling = ReflectionHelper.isPublic(handlingMethod) + && ReflectionHelper.isPublic(handlingMethod.getDeclaringClass()); + + return publicHandling ? handlingMethod : definitionMethod; + } + @Override public final Response dispatch(Object resource, ContainerRequest request) throws ProcessingException { Response response = null;
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/ParamConverterInternalTest.java b/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/ParamConverterInternalTest.java index b1f1ff8..8413a07 100644 --- a/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/ParamConverterInternalTest.java +++ b/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/ParamConverterInternalTest.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018 Payara Foundation and/or its affiliates. * * This program and the accompanying materials are made available under the @@ -35,6 +35,7 @@ import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.Configuration; import jakarta.ws.rs.core.UriBuilder; import jakarta.ws.rs.ext.ParamConverter; import jakarta.ws.rs.ext.ParamConverterProvider; @@ -43,6 +44,8 @@ import org.glassfish.jersey.internal.inject.ParamConverters; import org.glassfish.jersey.internal.util.ReflectionHelper; import org.glassfish.jersey.internal.util.collection.ClassTypePair; +import org.glassfish.jersey.model.internal.CommonConfig; +import org.glassfish.jersey.model.internal.ComponentBag; import org.glassfish.jersey.server.ApplicationHandler; import org.glassfish.jersey.server.ContainerResponse; import org.glassfish.jersey.server.RequestContextBuilder; @@ -284,8 +287,9 @@ @Test public void testDateParamConverterIsChosenForDateString() { initiateWebApplication(); + final Configuration configuration = new CommonConfig(null, ComponentBag.EXCLUDE_EMPTY); final ParamConverter<Date> converter = - new ParamConverters.AggregatedProvider(null).getConverter(Date.class, Date.class, null); + new ParamConverters.AggregatedProvider(null, configuration).getConverter(Date.class, Date.class, null); assertEquals(ParamConverters.DateProvider.class, converter.getClass().getEnclosingClass(), "Unexpected date converter provider class");
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/model/ResourceMethodDispatcherInheritanceTest.java b/core-server/src/test/java/org/glassfish/jersey/server/model/ResourceMethodDispatcherInheritanceTest.java new file mode 100644 index 0000000..d614263 --- /dev/null +++ b/core-server/src/test/java/org/glassfish/jersey/server/model/ResourceMethodDispatcherInheritanceTest.java
@@ -0,0 +1,70 @@ +/* + * Copyright (c) 2023 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.server.model; + +import org.glassfish.jersey.server.ApplicationHandler; +import org.glassfish.jersey.server.ContainerResponse; +import org.glassfish.jersey.server.RequestContextBuilder; +import org.glassfish.jersey.server.ResourceConfig; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import java.util.concurrent.ExecutionException; + +public class ResourceMethodDispatcherInheritanceTest { + public interface ResourceIfc1 { + @GET + public void get(); + } + + @Path("/") + static class ResourceClass1 implements ResourceIfc1 { + public void get() { + + } + } + + interface ResourceIfc2 { + @GET + public void get(); + } + + @Path("/") + public static class ResourceClass2 implements ResourceIfc2 { + public void get() { + + } + } + + @Test + public void testInheritedMethodPublicClass() throws ExecutionException, InterruptedException { + ApplicationHandler app = new ApplicationHandler(new ResourceConfig(ResourceClass2.class)); + ContainerResponse response; + response = app.apply(RequestContextBuilder.from("/", "GET").accept("text/plain").build()).get(); + Assertions.assertEquals(204, response.getStatus()); + } + + @Test + public void testInheritedMethodPublicIface() throws ExecutionException, InterruptedException { + ApplicationHandler app = new ApplicationHandler(new ResourceConfig(ResourceClass1.class)); + ContainerResponse response; + response = app.apply(RequestContextBuilder.from("/", "GET").accept("text/plain").build()).get(); + Assertions.assertEquals(204, response.getStatus()); + } +}
diff --git a/docs/src/main/docbook/appendix-properties.xml b/docs/src/main/docbook/appendix-properties.xml index 938e440..716f9b9 100644 --- a/docs/src/main/docbook/appendix-properties.xml +++ b/docs/src/main/docbook/appendix-properties.xml
@@ -1,7 +1,7 @@ <?xml version="1.0"?> <!-- - Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2013, 2023 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 @@ -184,6 +184,21 @@ </entry> </row> <row> + <entry>&jersey.common.CommonProperties.PARAM_CONVERTERS_THROW_IAE;(Jersey 2.40 or later) + </entry> + <entry> + <literal>jersey.config.paramconverters.throw.iae</literal> + </entry> + <entry> + Force the &jaxrs.ext.ParamConverter; to throw <literal>IllegalArgumentException</literal> as mandated in javadoc. + Must be convertible to &lit.jdk6.Boolean; value. + </entry> + <entry> + Internally the <literal>Exception</literal> is caught by Jersey and usually converted to <literal>null</literal> + Therefore, the default value is set to &lit.false; to speed up the conversion. + </entry> + </row> + <row> <entry>&jersey.logging.LoggingFeature.LOGGING_FEATURE_LOGGER_NAME; </entry> <entry> @@ -917,6 +932,53 @@ </entry> </row> <row> + <entry>&jersey.client.ClientProperties.CONNECTOR_PROVIDER;(Jersey 2.40 or later)</entry> + <entry><literal>jersey.config.client.connector.provider</literal></entry> + <entry> + <para> + Sets the &jersey.client.ConnectorProvider; class. Overrides the value from META-INF/services. + </para> + <para> + The value MUST be an instance of &lit.jdk6.String;. + </para> + <para> + The property is recognized by &lit.jaxrs.client.ClientBuilder;. + </para> + </entry> + </row> + <row> + <entry>&jersey.client.ClientProperties.DIGESTAUTH_URI_CACHE_SIZELIMIT;</entry> + <entry><literal>jersey.config.client.digestAuthUriCacheSizeLimit</literal></entry> + <entry> + <para> + The property defines a URI of a HTTP proxy the client connector should use. + </para> + </entry> + </row> + <row> + <entry>&jersey.client.ClientProperties.EXPECT_100_CONTINUE;</entry> + <entry><literal>jersey.config.client.request.expect.100.continue.processing</literal></entry> + <entry> + <para> + Allows for HTTP Expect:100-Continue being handled by the HttpUrlConnector (default Jersey + connector). <literal>Since 2.32</literal> + </para> + </entry> + </row> + <row> + <entry>&jersey.client.ClientProperties.EXPECT_100_CONTINUE_THRESHOLD_SIZE;</entry> + <entry><literal>jersey.config.client.request.expect.100.continue.threshold.size</literal></entry> + <entry> + <para> + Property for threshold size for content length after which Expect:100-Continue header would be applied + before the main request. + Default threshold size (64kb) after which which Expect:100-Continue header would be applied before + the main request. + <literal>Since 2.32</literal> + </para> + </entry> + </row> + <row> <entry>&jersey.client.ClientProperties.FEATURE_AUTO_DISCOVERY_DISABLE;</entry> <entry><literal>jersey.config.client.disableAutoDiscovery</literal></entry> <entry> @@ -1056,38 +1118,6 @@ </entry> </row> <row> - <entry>&jersey.client.ClientProperties.DIGESTAUTH_URI_CACHE_SIZELIMIT;</entry> - <entry><literal>jersey.config.client.digestAuthUriCacheSizeLimit</literal></entry> - <entry> - <para> - The property defines a URI of a HTTP proxy the client connector should use. - </para> - </entry> - </row> - <row> - <entry>&jersey.client.ClientProperties.EXPECT_100_CONTINUE;</entry> - <entry><literal>jersey.config.client.request.expect.100.continue.processing</literal></entry> - <entry> - <para> - Allows for HTTP Expect:100-Continue being handled by the HttpUrlConnector (default Jersey - connector). <literal>Since 2.32</literal> - </para> - </entry> - </row> - <row> - <entry>&jersey.client.ClientProperties.EXPECT_100_CONTINUE_THRESHOLD_SIZE;</entry> - <entry><literal>jersey.config.client.request.expect.100.continue.threshold.size</literal></entry> - <entry> - <para> - Property for threshold size for content length after which Expect:100-Continue header would be applied - before the main request. - Default threshold size (64kb) after which which Expect:100-Continue header would be applied before - the main request. - <literal>Since 2.32</literal> - </para> - </entry> - </row> - <row> <entry>&jersey.logging.LoggingFeature.LOGGING_FEATURE_LOGGER_NAME_CLIENT; </entry> <entry>
diff --git a/docs/src/main/docbook/client.xml b/docs/src/main/docbook/client.xml index e19ffe0..1c0e17f 100644 --- a/docs/src/main/docbook/client.xml +++ b/docs/src/main/docbook/client.xml
@@ -1,7 +1,7 @@ <?xml version="1.0"?> <!-- - Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2010, 2023 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 @@ -761,6 +761,16 @@ register &lit.jersey.client.Connector; instances in the Jersey &jersey.client.ClientConfig;. The new &lit.jersey.client.ConnectorProvider; SPI must be used instead to configure a custom client-side transport connector. </para> + <para> + A &jersey.client.ConnectorProvider; can also be set by a property on a &lit.jaxrs.client.ClientBuilder; starting with + Jersey 2.40. The following example shows how to setup the custom Grizzly Asynchronous HTTP Client based + &lit.jersey.client.ConnectorProvider; in a Jersey client instance: + <programlisting language="java" linenumbering="numbered">Client client = ClientBuilder.newBuilder() + .property(ClientProperties.CONNECTOR_PROVIDER, "org.glassfish.jersey.grizzly.connector.GrizzlyConnectorProvider") + .build();</programlisting> + + For more information about the property see <xref linkend="appendix-properties"/>. + </para> <section> <title>Client Connectors Properties</title> <para>
diff --git a/docs/src/main/docbook/jersey.ent b/docs/src/main/docbook/jersey.ent index e947990..99dc355 100644 --- a/docs/src/main/docbook/jersey.ent +++ b/docs/src/main/docbook/jersey.ent
@@ -1,7 +1,7 @@ <?xml version="1.0" encoding="iso-8859-1" ?> <!-- - Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2010, 2023 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 @@ -242,6 +242,7 @@ <!ENTITY jaxrs.ext.ExceptionMapper "<link xlink:href='&jaxrs.javadoc.uri;/ext/ExceptionMapper.html'>ExceptionMapper<E extends Throwable></link>"> <!ENTITY jaxrs.ext.MessageBodyReader "<link xlink:href='&jaxrs.javadoc.uri;/ext/MessageBodyReader.html'>MessageBodyReader<T></link>"> <!ENTITY jaxrs.ext.MessageBodyWriter "<link xlink:href='&jaxrs.javadoc.uri;/ext/MessageBodyWriter.html'>MessageBodyWriter<T></link>"> +<!ENTITY jaxrs.ext.ParamConverter "<link xlink:href='&jaxrs.javadoc.uri;/ext/ParamConverter.html'>ParamConverter<T></link>"> <!ENTITY jaxrs.ext.Provider "<link xlink:href='&jaxrs.javadoc.uri;/ext/Provider.html'>@Provider</link>"> <!ENTITY jaxrs.ext.Providers "<link xlink:href='&jaxrs.javadoc.uri;/ext/Providers.html'>Providers</link>"> <!ENTITY jaxrs.ext.RuntimeDelegate "<link xlink:href='&jaxrs.javadoc.uri;/ext/RuntimeDelegate.html'>RuntimeDelegate</link>"> @@ -338,6 +339,7 @@ <!ENTITY jersey.client.ClientProperties.BUFFER_RESPONSE_ENTITY_ON_EXCEPTION "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#BUFFER_RESPONSE_ENTITY_ON_EXCEPTION'>ClientProperties.BUFFER_RESPONSE_ENTITY_ON_EXCEPTION</link>" > <!ENTITY jersey.client.ClientProperties.CHUNKED_ENCODING_SIZE "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#CHUNKED_ENCODING_SIZE'>ClientProperties.CHUNKED_ENCODING_SIZE</link>" > <!ENTITY jersey.client.ClientProperties.CONNECT_TIMEOUT "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#CONNECT_TIMEOUT'>ClientProperties.CONNECT_TIMEOUT</link>" > +<!ENTITY jersey.client.ClientProperties.CONNECTOR_PROVIDER "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#CONNECTOR_PROVIDER'>ClientProperties.CONNECTOR_PROVIDER</link>" > <!ENTITY jersey.client.ClientProperties.DEFAULT_CHUNK_SIZE "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#DEFAULT_CHUNK_SIZE'>ClientProperties.DEFAULT_CHUNK_SIZE</link>" > <!ENTITY jersey.client.ClientProperties.FEATURE_AUTO_DISCOVERY_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#FEATURE_AUTO_DISCOVERY_DISABLE'>ClientProperties.FEATURE_AUTO_DISCOVERY_DISABLE</link>" > <!ENTITY jersey.client.ClientProperties.FOLLOW_REDIRECTS "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#FOLLOW_REDIRECTS'>ClientProperties.FOLLOW_REDIRECTS</link>" > @@ -402,6 +404,7 @@ <!ENTITY jersey.common.CommonProperties.JSON_JACKSON_DISABLED_MODULES "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_JACKSON_DISABLED_MODULES'>CommonProperties.JSON_JACKSON_DISABLED_MODULES</link>" > <!ENTITY jersey.common.CommonProperties.JSON_JACKSON_DISABLED_MODULES_CLIENT "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_JACKSON_DISABLED_MODULES'>CommonProperties.JSON_JACKSON_DISABLED_MODULES_CLIENT</link>" > <!ENTITY jersey.common.CommonProperties.JSON_JACKSON_DISABLED_MODULES_SERVER "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_JACKSON_DISABLED_MODULES'>CommonProperties.JSON_JACKSON_DISABLED_MODULES_SERVER</link>" > +<!ENTITY jersey.common.CommonProperties.PARAM_CONVERTERS_THROW_IAE "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#PARAM_CONVERTERS_THROW_IAE'>CommonProperties.PARAM_CONVERTERS_THROW_IAE</link>" > <!ENTITY jersey.common.internal.inject.DisposableSupplier "<link xlink:href='&jersey.javadoc.uri.prefix;/internal/inject/DisposableSupplier.html'>DisposableSupplier</link>"> <!ENTITY jersey.common.internal.inject.InjectionManager "<link xlink:href='&jersey.javadoc.uri.prefix;/internal/inject/InjectionManager.html'>InjectionManager</link>"> <!ENTITY jersey.common.internal.inject.AbstractBinder "<link xlink:href='&jersey.javadoc.uri.prefix;/internal/inject/AbstractBinder.html'>AbstractBinder</link>">
diff --git a/examples/configured-client/README.MD b/examples/configured-client/README.MD new file mode 100644 index 0000000..94a66be --- /dev/null +++ b/examples/configured-client/README.MD
@@ -0,0 +1,40 @@ +[//]: # " Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. " +[//]: # " " +[//]: # " This program and the accompanying materials are made available under the " +[//]: # " terms of the Eclipse Distribution License v. 1.0, which is available at " +[//]: # " http://www.eclipse.org/org/documents/edl-v10.php. " +[//]: # " " +[//]: # " SPDX-License-Identifier: BSD-3-Clause " + +Client Configured by Property File Example +========================================== + +This example demonstrates configuration of a Client using property file. +The property file microprofile-config.properties is consumed by +Microprofile Config implementation and the properties from the +property file are set to Jersey Configuration. + +The following properties are defined in `microprofile-config.properties` property file: + * jersey.config.client.connector.provider - jersey property name for the connector to be used + * entity.value - user defined property to be be sent as an echo message + + +Contents +-------- + +The mapping of the URI path space is presented in the following table: + +URI path | Resource class | HTTP methods | Notes +-------------------- | ------------------- |--------------| -------------------------------------------------------- +**_/helloworld_** | HelloWorldResource | POST | Echoes the message sent + +Running the Example +------------------- + +Run the example as follows: + +> mvn clean compile exec:java + +This deploys the example using [Grizzly](http://grizzly.java.net/) container. + +- <http://localhost:8080/base/helloworld>
diff --git a/examples/configured-client/pom.xml b/examples/configured-client/pom.xml new file mode 100644 index 0000000..ff4aa99 --- /dev/null +++ b/examples/configured-client/pom.xml
@@ -0,0 +1,118 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Distribution License v. 1.0, which is available at + http://www.eclipse.org/org/documents/edl-v10.php. + + SPDX-License-Identifier: BSD-3-Clause + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.glassfish.jersey.examples</groupId> + <artifactId>project</artifactId> + <version>3.0.99-SNAPSHOT</version> + </parent> + + <artifactId>configured-client</artifactId> + <packaging>jar</packaging> + <name>jersey-examples-configured-client</name> + + <description>Jersey client configured by a property file example.</description> + + <dependencies> + <dependency> + <groupId>org.glassfish.jersey.containers</groupId> + <artifactId>jersey-container-grizzly2-http</artifactId> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.inject</groupId> + <artifactId>jersey-hk2</artifactId> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.connectors</groupId> + <artifactId>jersey-apache5-connector</artifactId> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.ext.microprofile</groupId> + <artifactId>jersey-mp-config</artifactId> + </dependency> + + <dependency> + <groupId>io.helidon.microprofile.config</groupId> + <artifactId>helidon-microprofile-config</artifactId> + <version>${helidon.version}</version> + <exclusions> + <exclusion> + <groupId>org.eclipse.microprofile.config</groupId> + <artifactId>microprofile-config-api</artifactId> + </exclusion> + </exclusions> + </dependency> + +<!-- Instead of helidon-microprofile-config, smallrye-config can be used --> +<!-- <dependency>--> +<!-- <groupId>io.smallrye</groupId>--> +<!-- <artifactId>smallrye-config</artifactId>--> +<!-- <version>${smallrye.config.version}</version>--> +<!-- <exclusions>--> +<!-- <exclusion>--> +<!-- <groupId>org.eclipse.microprofile.config</groupId>--> +<!-- <artifactId>microprofile-config-api</artifactId>--> +<!-- </exclusion>--> +<!-- </exclusions>--> +<!-- </dependency>--> + + <dependency> + <groupId>org.glassfish.jersey.test-framework</groupId> + <artifactId>jersey-test-framework-util</artifactId> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.test-framework.providers</groupId> + <artifactId>jersey-test-framework-provider-bundle</artifactId> + <type>pom</type> + <scope>test</scope> + </dependency> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <configuration> + <mainClass>org.glassfish.jersey.examples.configured.client.App</mainClass> + </configuration> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>pre-release</id> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + </plugin> + </plugins> + </build> + </profile> + </profiles> +</project>
diff --git a/examples/configured-client/src/main/java/org/glassfish/jersey/examples/configured/client/App.java b/examples/configured-client/src/main/java/org/glassfish/jersey/examples/configured/client/App.java new file mode 100644 index 0000000..0f6d49b --- /dev/null +++ b/examples/configured-client/src/main/java/org/glassfish/jersey/examples/configured/client/App.java
@@ -0,0 +1,74 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.glassfish.jersey.examples.configured.client; + +import java.io.IOException; +import java.net.URI; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; +import org.glassfish.jersey.server.ResourceConfig; + +import org.glassfish.grizzly.http.server.HttpServer; + +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; + +/** + * Hello world! + */ +public class App { + + private static final URI BASE_URI = URI.create("http://localhost:8080/base/"); + public static final String ROOT_PATH = "helloworld"; + /* package */ static final String ENTITY_PROPERTY = "entity.value"; + + public static void main(String[] args) { + try { + System.out.println("\"Hello World\" Jersey Example App"); + + final ResourceConfig resourceConfig = new ResourceConfig(HelloWorldResource.class); + final HttpServer server = GrizzlyHttpServerFactory.createHttpServer(BASE_URI, resourceConfig, false); + Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { + @Override + public void run() { + server.shutdownNow(); + } + })); + server.start(); + + WebTarget target = ClientBuilder.newClient().target(BASE_URI); + Object entity = target.getConfiguration().getProperty(ENTITY_PROPERTY); + Object provider = target.getConfiguration().getProperty(ClientProperties.CONNECTOR_PROVIDER); + + System.out + .append(" Application started.\n") + .append(" Sending entity \"").append((String) entity).append("\"") + .append(" using ").append((String) provider).append(" connector provider") + .append(" to echo resource ").append(BASE_URI.toASCIIString()).println(ROOT_PATH); + + try (Response response = target.path(ROOT_PATH).request().post(Entity.entity(entity, MediaType.TEXT_PLAIN_TYPE))) { + System.out.append(" Recieved: \"").append(response.readEntity(String.class)).println("\""); + } + + server.stop(); + System.exit(0); + } catch (IOException ex) { + Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex); + } + + } +}
diff --git a/examples/configured-client/src/main/java/org/glassfish/jersey/examples/configured/client/HelloWorldResource.java b/examples/configured-client/src/main/java/org/glassfish/jersey/examples/configured/client/HelloWorldResource.java new file mode 100644 index 0000000..3c25599 --- /dev/null +++ b/examples/configured-client/src/main/java/org/glassfish/jersey/examples/configured/client/HelloWorldResource.java
@@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.glassfish.jersey.examples.configured.client; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.Configuration; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; + + +@Path("helloworld") +public class HelloWorldResource { + @Context + Configuration configuration; + + @POST + @Produces("text/plain") + public String postHello(String helloMsg) { + return helloMsg; + } + + @GET + @Path("agent") + @Produces(MediaType.TEXT_PLAIN) + public String getAgent(@Context HttpHeaders headers) { + return headers.getHeaderString(HttpHeaders.USER_AGENT); + } + +}
diff --git a/examples/configured-client/src/main/resources/META-INF/microprofile-config.properties b/examples/configured-client/src/main/resources/META-INF/microprofile-config.properties new file mode 100644 index 0000000..5c6cbb2 --- /dev/null +++ b/examples/configured-client/src/main/resources/META-INF/microprofile-config.properties
@@ -0,0 +1,12 @@ +# +# Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Distribution License v. 1.0, which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +jersey.config.client.connector.provider=org.glassfish.jersey.apache5.connector.Apache5ConnectorProvider +entity.value=Hello World! \ No newline at end of file
diff --git a/examples/configured-client/src/test/java/org/glassfish/jersey/examples/configured/client/HelloWorldTest.java b/examples/configured-client/src/test/java/org/glassfish/jersey/examples/configured/client/HelloWorldTest.java new file mode 100644 index 0000000..7499c2b --- /dev/null +++ b/examples/configured-client/src/test/java/org/glassfish/jersey/examples/configured/client/HelloWorldTest.java
@@ -0,0 +1,71 @@ +/* + * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0, which is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +package org.glassfish.jersey.examples.configured.client; + +import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; + +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.glassfish.jersey.test.TestProperties; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.parallel.Execution; +import org.junit.jupiter.api.parallel.ExecutionMode; +import org.junit.jupiter.api.parallel.ResourceAccessMode; +import org.junit.jupiter.api.parallel.ResourceLock; + +import static org.glassfish.jersey.examples.configured.client.App.ENTITY_PROPERTY; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class HelloWorldTest extends JerseyTest { + + @Override + protected ResourceConfig configure() { + // mvn test -Djersey.config.test.container.factory=org.glassfish.jersey.test.inmemory.InMemoryTestContainerFactory + // mvn test -Djersey.config.test.container.factory=org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory + // mvn test -Djersey.config.test.container.factory=org.glassfish.jersey.test.jdkhttp.JdkHttpServerTestContainerFactory + // mvn test -Djersey.config.test.container.factory=org.glassfish.jersey.test.simple.SimpleTestContainerFactory + enable(TestProperties.LOG_TRAFFIC); + // enable(TestProperties.DUMP_ENTITY); + return new ResourceConfig(HelloWorldResource.class); + } + + @Test + @Execution(ExecutionMode.CONCURRENT) + @ResourceLock(value = "dummy", mode = ResourceAccessMode.READ) + public void testEntity() { + WebTarget target = target("helloworld"); + Object entity = target.getConfiguration().getProperty(ENTITY_PROPERTY); + try (Response response = target.request().post(Entity.entity(entity, MediaType.TEXT_PLAIN_TYPE))) { + Assertions.assertEquals(200, response.getStatus()); + String readEntity = response.readEntity(String.class); + System.out.println(entity); + Assertions.assertEquals(entity, readEntity); + } + } + + @Test + @Execution(ExecutionMode.CONCURRENT) + @ResourceLock(value = "dummy", mode = ResourceAccessMode.READ) + public void testConnector() { + try (Response response = target("helloworld").path("agent").request().get()) { + Assertions.assertEquals(200, response.getStatus()); + String entity = response.readEntity(String.class); + System.out.println(entity); + Assertions.assertTrue(entity.contains("Apache HttpClient 5")); + } + } +}
diff --git a/examples/pom.xml b/examples/pom.xml index de547df..48a1f51 100644 --- a/examples/pom.xml +++ b/examples/pom.xml
@@ -60,6 +60,7 @@ <module>cdi-webapp</module> <module>clipboard</module> <module>clipboard-programmatic</module> + <module>configured-client</module> <module>declarative-linking</module> <module>entity-filtering</module> <module>entity-filtering-selectable</module>
diff --git a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ProxyInvocationHandler.java b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ProxyInvocationHandler.java index b8192e5..0fd557e 100644 --- a/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ProxyInvocationHandler.java +++ b/ext/microprofile/mp-rest-client/src/main/java/org/glassfish/jersey/microprofile/restclient/ProxyInvocationHandler.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2023 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 @@ -18,6 +18,7 @@ import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; +import java.lang.reflect.Proxy; import java.util.concurrent.atomic.AtomicBoolean; import jakarta.ws.rs.client.Client; @@ -56,6 +57,18 @@ if (method.getName().equals("toString") && (args == null || args.length == 0)) { return restClientModel.toString(); } + + if (args == null && method.getName().equals("hashCode")) { + return hashCode(); + } + + if (args != null && args.length == 1 && method.getName().equals("equals")) { + if (!(args[0] instanceof Proxy)) { + return false; + } + return equals(Proxy.getInvocationHandler(args[0])); + } + if (method.getName().equals("close") && (args == null || args.length == 0)) { closed.set(true); if (null != client) {
diff --git a/pom.xml b/pom.xml index 910f57a..229c0c6 100644 --- a/pom.xml +++ b/pom.xml
@@ -2258,7 +2258,7 @@ <guava.version>31.1-jre</guava.version> <hamcrest.version>2.2</hamcrest.version> - <!--<helidon.version>1.4.9</helidon.version>--> + <helidon.version>1.4.13</helidon.version> <helidon.jersey.connector.version>3.0.2</helidon.jersey.connector.version> <xmlunit.version>2.9.0</xmlunit.version> <hk2.osgi.version>org.glassfish.hk2.*;version="[2.5,4)"</hk2.osgi.version>
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/ParamConvertersTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/ParamConvertersTest.java new file mode 100644 index 0000000..67048f8 --- /dev/null +++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/ParamConvertersTest.java
@@ -0,0 +1,105 @@ +/* + * Copyright (c) 2023 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.common.internal; + +import org.glassfish.jersey.CommonProperties; +import org.glassfish.jersey.internal.inject.Bindings; +import org.glassfish.jersey.internal.inject.InjectionManager; +import org.glassfish.jersey.internal.inject.Injections; +import org.glassfish.jersey.internal.inject.ParamConverterConfigurator; +import org.glassfish.jersey.internal.inject.Providers; +import org.glassfish.jersey.model.internal.CommonConfig; +import org.glassfish.jersey.model.internal.ComponentBag; +import org.glassfish.jersey.model.internal.RankedComparator; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import jakarta.ws.rs.core.Configuration; +import jakarta.ws.rs.ext.ParamConverter; +import jakarta.ws.rs.ext.ParamConverterProvider; +import java.util.Date; + +public class ParamConvertersTest { + private CommonConfig config; + + @BeforeEach + public void setUp() throws Exception { + config = new CommonConfig(null, ComponentBag.INCLUDE_ALL); + } + + @Test + public void paramConvertersReturnNull() { + ParamConverter<String> converter = getParamConverter(String.class); + assertNull(String.class); + assertNull(Date.class); + assertNull(Character.class); + } + + @Test + public void paramConvertersThrow() { + config.property(CommonProperties.PARAM_CONVERTERS_THROW_IAE, true); + + assertThrow(String.class); + assertThrow(Date.class); + assertThrow(Character.class); + } + + private <T> void assertNull(Class<T> clazz) { + ParamConverter<T> converter = getParamConverter(clazz); + Assertions.assertNotNull(converter); + Assertions.assertNull(converter.fromString(null)); + Assertions.assertNull(converter.toString(null)); + } + + private <T> void assertThrow(Class<T> clazz) { + ParamConverter<T> converter = getParamConverter(clazz); + Assertions.assertNotNull(converter); + + try { + converter.fromString(null); + throw new RuntimeException("The IAE was not thrown"); + } catch (IllegalArgumentException illegalArgumentException) { + //expected + } + + try { + converter.toString(null); + throw new RuntimeException("The IAE was not thrown"); + } catch (IllegalArgumentException illegalArgumentException) { + //expected + } + } + + private <T> ParamConverter<T> getParamConverter(Class<T> clazz) { + InjectionManager injectionManager = Injections.createInjectionManager(); + new ParamConverterConfigurator().init(injectionManager, null); + injectionManager.register(Bindings.service(config).to(Configuration.class)); + injectionManager.completeRegistration(); + + final Iterable<ParamConverterProvider> allProviders = + Providers.getAllProviders(injectionManager, ParamConverterProvider.class, new RankedComparator<>()); + for (ParamConverterProvider provider : allProviders) { + ParamConverter<T> converter = provider.getConverter(clazz, clazz, null); + if (converter != null) { + return converter; + } + } + return null; + } + +}
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CompletionStageTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CompletionStageTest.java index 0355f04..0d44ac2 100644 --- a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CompletionStageTest.java +++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/CompletionStageTest.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023 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 @@ -158,7 +158,15 @@ @Test public void testCompletionStageUnwrappedInGenericType() { - try (Response r = target("cs/databeanlist").request().get()){ + try (Response r = target("cs/databeanlist").request().get()) { + assertEquals(200, r.getStatus()); + assertTrue(r.readEntity(String.class).startsWith(ENTITY)); + } + } + + @Test + void testExtends() { + try (Response r = target("cs/csextends").request().get()) { assertEquals(200, r.getStatus()); assertTrue(r.readEntity(String.class).startsWith(ENTITY)); } @@ -288,6 +296,12 @@ return cs; } + @GET + @Path("csextends") + public CompletionStage<? extends CharSequence> csExtends() { + return CompletableFuture.completedFuture(ENTITY); + } + private void delaySubmit(Runnable runnable) { EXECUTOR_SERVICE.submit(() -> { try {
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/TypedVariableTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/TypedVariableTest.java new file mode 100644 index 0000000..8c3485b --- /dev/null +++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/TypedVariableTest.java
@@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 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.server; + +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.jupiter.api.Test; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.Response; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class TypedVariableTest extends JerseyTest { + + private static final String ENTITY = "entity"; + + @Path("/typed") + public static class Resource { + @GET + @Path("extends") + public <T extends CharSequence> T justExtends() { + return (T) ENTITY; + } + } + + @Override + protected Application configure() { + return new ResourceConfig(Resource.class); + } + + @Test + void testExtends() { + try (Response r = target("typed/extends").request().get()) { + assertEquals(200, r.getStatus()); + assertTrue(r.readEntity(String.class).startsWith(ENTITY)); + } + } +}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/ClientTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/ClientTest.java index f8307a3..e14b461 100644 --- a/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/ClientTest.java +++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/e2e/ClientTest.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023 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,8 +16,10 @@ package org.glassfish.jersey.tests.e2e; +import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Set; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.GET; @@ -32,12 +34,14 @@ import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.HttpHeaders; import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MultivaluedMap; import jakarta.ws.rs.core.Response; import jakarta.ws.rs.core.Variant; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.test.JerseyTest; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -80,6 +84,30 @@ return sb.toString(); } + + @GET + @Path("/tostring") + public String headersGet(@Context HttpHeaders hs) { + StringBuilder sb = new StringBuilder(); + List<String> myHeaders = Arrays.asList("Accept", "Content-Type"); + + try { + MultivaluedMap<String, String> rqhdrs = hs.getRequestHeaders(); + Set<String> keys = rqhdrs.keySet(); + sb.append("getRequestHeaders= "); + for (String header : myHeaders) { + if (keys.contains(header)) { + sb.append( + "Found " + header + ": " + hs.getRequestHeader(header) + "; "); + } + } + } catch (Throwable ex) { + sb.append("Unexpected exception thrown in getRequestHeaders: " + + ex.getMessage()); + ex.printStackTrace(); + } + return sb.toString(); + } } @Override @@ -98,6 +126,26 @@ } @Test + public void testHeadersToString() { + try (Response response = target("headers").path("tostring").request() + .header(HttpHeaders.ACCEPT, "text/*, text/html, text/html;level=1, */*") + .header(HttpHeaders.CONTENT_TYPE, "application/xml;charset=utf8") + .get()) { + String content = response.readEntity(String.class); + int index = -1; + Assertions.assertTrue((index = content.indexOf("getRequestHeaders=")) != -1); + Assertions.assertTrue((index = content.indexOf("Accept:")) != -1); + Assertions.assertTrue((index = content.indexOf("text/*")) != -1); + Assertions.assertTrue((index = content.indexOf("text/html")) != -1); + Assertions.assertTrue((index = content.indexOf("text/html")) != -1); + Assertions.assertTrue((index = content.indexOf("*/*")) != -1); + Assertions.assertTrue((index = content.indexOf("Content-Type:")) != -1); + Assertions.assertTrue((index = content.indexOf("application/xml")) != -1); + Assertions.assertTrue((index = content.indexOf("charset=utf8")) != -1); + } + } + + @Test public void testAccesingMissingResource() { final WebTarget missingResource = target().path("missing"); final Response r = missingResource.request().get();
diff --git a/tests/release-test/pom.xml b/tests/release-test/pom.xml index 00fa896..6f7ad39 100644 --- a/tests/release-test/pom.xml +++ b/tests/release-test/pom.xml
@@ -99,6 +99,12 @@ <version>${maven.version}</version> <scope>provided</scope> </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>${httpclient.version}</version> + <scope>test</scope> + </dependency> <dependency> <groupId>org.apache.maven.plugin-testing</groupId>
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 01ba01e..99c94ee 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
@@ -21,6 +21,7 @@ import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.impl.DefaultServiceLocator; import org.eclipse.aether.repository.LocalRepository; +import org.eclipse.aether.resolution.ArtifactResolutionException; import org.eclipse.aether.spi.connector.RepositoryConnectorFactory; import org.eclipse.aether.spi.connector.transport.TransporterFactory; import org.eclipse.aether.transport.http.HttpTransporterFactory; @@ -51,60 +52,97 @@ @Test public void testDownloadBomPomDependencies() throws Exception { -// RepositorySystem repositorySystem = (RepositorySystem) lookup(RepositorySystem.class.getName()); - DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator(); - locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class); - locator.addService(TransporterFactory.class, HttpTransporterFactory.class); - RepositorySystem repositorySystem = locator.getService(RepositorySystem.class); - - RepositorySystemSession repoSession = getRepoSession(repositorySystem); - List<RemoteRepository> remoteRepos = getRemoteRepositories(repoSession); - - Properties properties = MavenUtil.getMavenProperties(); - String jerseyVersion = MavenUtil.getJerseyVersion(properties); + MavenEnvironment mavenEnvironment = new MavenEnvironment(); List<Dependency> memberDeps = MavenUtil.streamJerseyJars().collect(Collectors.toList()); for (Dependency member : memberDeps) { - member.setVersion(jerseyVersion); - Artifact m = DependencyResolver.resolveArtifact(member, remoteRepos, repositorySystem, repoSession); + 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()); } } - private List<RemoteRepository> getRemoteRepositories(RepositorySystemSession session) throws Exception { - File pom = lookupResourcesPom("/release-test-pom.xml"); - MavenExecutionRequest request = new DefaultMavenExecutionRequest(); - request.setPom(pom); - request.addActiveProfile("staging"); - ProjectBuildingRequest buildingRequest = request - .getProjectBuildingRequest() - .setRepositorySession(session) - .setResolveDependencies(true); + @Test + public void testDownloadNonBomPomDependencies() throws Exception { + MavenEnvironment mavenEnvironment = new MavenEnvironment(); + MavenProject project = mavenEnvironment.getMavenProjectForResourceFile("/non-bom-pom-deps.xml"); + for (Dependency dependency : project.getDependencies()) { + if (dependency.getArtifactId().contains("jackson1") && mavenEnvironment.jerseyVersion.startsWith("3")) { + continue; + } - ProjectBuilder projectBuilder = lookup(ProjectBuilder.class); - ProjectBuildingResult projectBuildingResult = projectBuilder.build(pom, buildingRequest); - MavenProject project = projectBuildingResult.getProject(); - - List<RemoteRepository> remoteArtifactRepositories = project.getRemoteProjectRepositories(); - return remoteArtifactRepositories; + Artifact m = mavenEnvironment.resolveArtifact(dependency); + System.out.append("Resolved ").append(dependency.getGroupId()).append(":") + .append(dependency.getArtifactId()).append(":") + .append(dependency.getVersion()).append(" to ").println(m.getFile().getName()); + } } - private static RepositorySystemSession getRepoSession(RepositorySystem repositorySystem) { - DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession(); - LocalRepository localRepo = new LocalRepository(MavenUtil.getLocalMavenRepository().getAbsolutePath()); - session.setLocalRepositoryManager(repositorySystem.newLocalRepositoryManager(session, localRepo)); - return session; - } + private class MavenEnvironment { + private final RepositorySystem repositorySystem; + private final RepositorySystemSession repoSession; + private final List<RemoteRepository> remoteRepos; + private final String jerseyVersion; - private static File lookupResourcesPom(String pomFile) throws URISyntaxException { - URL resource = DownloadBomPomDependencies.class.getResource(pomFile); - if (resource == null) { - throw new IllegalStateException("Pom file " + pomFile + " was not located on classpath!"); + MavenEnvironment() throws Exception { + DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator(); + locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class); + locator.addService(TransporterFactory.class, HttpTransporterFactory.class); + + repositorySystem = locator.getService(RepositorySystem.class); + repoSession = getRepoSession(); + + remoteRepos = getRemoteRepositories(); + + Properties properties = MavenUtil.getMavenProperties(); + jerseyVersion = MavenUtil.getJerseyVersion(properties); } - File file = new File(resource.toURI()); - if (!file.exists()) { - throw new IllegalStateException("Cannot locate test pom xml file!"); + + Artifact resolveArtifact(Dependency dependency) throws ArtifactResolutionException { + dependency.setVersion(jerseyVersion); + return DependencyResolver.resolveArtifact(dependency, remoteRepos, repositorySystem, repoSession); } - return file; + + private List<RemoteRepository> getRemoteRepositories() throws Exception { + MavenProject project = getMavenProjectForResourceFile("/release-test-pom.xml"); + List<RemoteRepository> remoteArtifactRepositories = project.getRemoteProjectRepositories(); + return remoteArtifactRepositories; + } + + private MavenProject getMavenProjectForResourceFile(String resourceFile) + throws Exception { + File pom = lookupResourcesPom(resourceFile); + MavenExecutionRequest request = new DefaultMavenExecutionRequest(); + request.setPom(pom); + request.addActiveProfile("staging"); + ProjectBuildingRequest buildingRequest = request + .getProjectBuildingRequest() + .setRepositorySession(repoSession) + .setResolveDependencies(true); + + ProjectBuilder projectBuilder = lookup(ProjectBuilder.class); + ProjectBuildingResult projectBuildingResult = projectBuilder.build(pom, buildingRequest); + MavenProject project = projectBuildingResult.getProject(); + + return project; + } + + private RepositorySystemSession getRepoSession() { + DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession(); + LocalRepository localRepo = new LocalRepository(MavenUtil.getLocalMavenRepository().getAbsolutePath()); + session.setLocalRepositoryManager(repositorySystem.newLocalRepositoryManager(session, localRepo)); + return session; + } + + private File lookupResourcesPom(String pomFile) throws URISyntaxException { + URL resource = DownloadBomPomDependencies.class.getResource(pomFile); + if (resource == null) { + throw new IllegalStateException("Pom file " + pomFile + " was not located on classpath!"); + } + File file = new File(resource.toURI()); + if (!file.exists()) { + throw new IllegalStateException("Cannot locate test pom xml file!"); + } + return file; + } } }
diff --git a/tests/release-test/src/test/resources/non-bom-pom-deps.xml b/tests/release-test/src/test/resources/non-bom-pom-deps.xml new file mode 100644 index 0000000..7ced6b0 --- /dev/null +++ b/tests/release-test/src/test/resources/non-bom-pom-deps.xml
@@ -0,0 +1,77 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2023 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 + +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.eclipse.ee4j</groupId> + <artifactId>project</artifactId> + <version>1.0.8</version> + </parent> + + <groupId>org.glassfish.jersey.tests</groupId> + <artifactId>release-test-test</artifactId> + <version>0.0.1-SNAPSHOT</version> + + <dependencies> + <dependency> + <groupId>org.glassfish.jersey.media</groupId> + <artifactId>jersey-media-json-jackson1</artifactId> + <version>2.27</version> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.security</groupId> + <artifactId>oauth1-client</artifactId> + <version>2.27</version> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.security</groupId> + <artifactId>oauth1-server</artifactId> + <version>2.27</version> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.security</groupId> + <artifactId>oauth1-signature</artifactId> + <version>2.27</version> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.incubator</groupId> + <artifactId>jersey-injectless-client</artifactId> + <version>2.27</version> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.incubator</groupId> + <artifactId>jersey-open-tracing</artifactId> + <version>2.27</version> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.media</groupId> + <artifactId>jersey-media-kryo</artifactId> + <version>2.27</version> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.ext</groupId> + <artifactId>jersey-declarative-linking</artifactId> + <version>2.27</version> + </dependency> + </dependencies> + +</project> \ No newline at end of file
diff --git a/tests/release-test/src/test/resources/release-test-pom.xml b/tests/release-test/src/test/resources/release-test-pom.xml index d8aa486..4fac652 100644 --- a/tests/release-test/src/test/resources/release-test-pom.xml +++ b/tests/release-test/src/test/resources/release-test-pom.xml
@@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2022, 2023 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,7 +24,7 @@ <parent> <groupId>org.eclipse.ee4j</groupId> <artifactId>project</artifactId> - <version>1.0.7</version> + <version>1.0.8</version> </parent> <groupId>org.glassfish.jersey.tests</groupId>
diff --git a/tests/version-agnostic/pom.xml b/tests/version-agnostic/pom.xml index 979fed4..c4c44f5 100644 --- a/tests/version-agnostic/pom.xml +++ b/tests/version-agnostic/pom.xml
@@ -80,6 +80,17 @@ <profiles> <profile> + <id>noTests</id> + <activation> + <property> + <name>skipTests</name> + </property> + </activation> + <properties> + <maven.test.skip>true</maven.test.skip> + </properties> + </profile> + <profile> <id>version-agnostic</id> <activation> <property>
diff --git a/tests/version-agnostic/src/test/java/org/glassfish/jersey/test/agnostic/JettyHeaderTest.java b/tests/version-agnostic/src/test/java/org/glassfish/jersey/test/agnostic/JettyHeaderTest.java index 01187a2..e720080 100644 --- a/tests/version-agnostic/src/test/java/org/glassfish/jersey/test/agnostic/JettyHeaderTest.java +++ b/tests/version-agnostic/src/test/java/org/glassfish/jersey/test/agnostic/JettyHeaderTest.java
@@ -24,14 +24,11 @@ import jakarta.ws.rs.core.Response; import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.jetty.connector.JettyConnectorProvider; -import org.glassfish.jersey.logging.LoggingFeature; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.test.JerseyTest; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import java.util.logging.Level; - public class JettyHeaderTest extends JerseyTest { @Path("/") public static class JettyHeaderTestResource {