merge of the actual 3.0 into the 3.1
diff --git a/NOTICE.md b/NOTICE.md index dac1f90..bd12480 100644 --- a/NOTICE.md +++ b/NOTICE.md
@@ -1,4 +1,4 @@ -# Notice for Jersey +# Notice for Jersey This content is produced and maintained by the Eclipse Jersey project. * Project home: https://projects.eclipse.org/projects/ee4j.jersey @@ -57,25 +57,25 @@ * Project: http://getbootstrap.com * Copyright: 2011-2016 Twitter, Inc -Google Guava Version 18.0 +Google Guava Version 33.3.0-jre * License: Apache License, 2.0 -* Copyright (C) 2009 The Guava Authors +* Copyright (C) 2009, 2024 The Guava Authors -jakarta.inject Version: 1 +jakarta.inject Version: 2.0.1 * License: Apache License, 2.0 -* Copyright (C) 2009 The JSR-330 Expert Group +* Copyright (C) 2009, 2021 The JSR-330 Expert Group Javassist Version 3.30.2-GA * License: Apache License, 2.0 * Project: http://www.javassist.org/ * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. -Jackson JAX-RS Providers Version 2.17.1 +Jackson JAX-RS Providers Version 2.17.2 * License: Apache License, 2.0 * Project: https://github.com/FasterXML/jackson-jaxrs-providers * Copyright: (c) 2009-2024 FasterXML, LLC. All rights reserved unless otherwise indicated. -jQuery v1.12.4 +jQuery v3.7.1 * License: jquery.org/license * Project: jquery.org * Copyright: (c) jQuery Foundation
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 88a3d01..364bff0 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
@@ -241,10 +241,33 @@ public static final String OUTBOUND_CONTENT_LENGTH_BUFFER = CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER_CLIENT; /** + * If {@code true} then disable configuration of Json Binding (JSR-367) + * feature on client. + * <p> + * By default, Json Binding on client is automatically enabled if global + * property + * {@value org.glassfish.jersey.CommonProperties#JSON_BINDING_FEATURE_DISABLE} + * is not disabled. If set then the client property value overrides the + * global property value. + * <p> + * The default value is {@code false}. + * </p> + * <p> + * The name of the configuration property is <tt>{@value}</tt>. + * </p> + * <p>This constant is an alias for {@link CommonProperties#JSON_BINDING_FEATURE_DISABLE_CLIENT}.</p> + * + * @see org.glassfish.jersey.CommonProperties#JSON_BINDING_FEATURE_DISABLE + * @since 2.45 + */ + @PropertyAlias + public static final String JSON_BINDING_FEATURE_DISABLE = CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT; + + /** * If {@code true} then disable configuration of Json Processing (JSR-353) * feature on client. * <p> - * By default Json Processing on client is automatically enabled if global + * By default, Json Processing on client is automatically enabled if global * property * {@value org.glassfish.jersey.CommonProperties#JSON_PROCESSING_FEATURE_DISABLE} * is not disabled. If set then the client property value overrides the @@ -265,7 +288,7 @@ /** * If {@code true} then disable META-INF/services lookup on client. * <p> - * By default Jersey looks up SPI implementations described by {@code META-INF/services/*} files. + * By default, Jersey looks up SPI implementations described by {@code META-INF/services/*} files. * Then you can register appropriate provider classes by {@link jakarta.ws.rs.core.Application}. * </p> * <p>
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java b/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java index 90d138d..306e336 100644 --- a/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java +++ b/core-client/src/main/java/org/glassfish/jersey/client/HttpUrlConnectorProvider.java
@@ -21,6 +21,9 @@ import java.net.Proxy; import java.net.URL; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Logger; import jakarta.ws.rs.client.Client; @@ -295,9 +298,26 @@ private static class DefaultConnectionFactory implements ConnectionFactory { + private final ConcurrentHashMap<URL, Lock> locks = new ConcurrentHashMap<>(); + @Override public HttpURLConnection getConnection(final URL url) throws IOException { - return (HttpURLConnection) url.openConnection(); + return connect(url, null); + } + + @Override + public HttpURLConnection getConnection(URL url, Proxy proxy) throws IOException { + return connect(url, proxy); + } + + private HttpURLConnection connect(URL url, Proxy proxy) throws IOException { + Lock lock = locks.computeIfAbsent(url, u -> new ReentrantLock()); + lock.lock(); + try { + return (proxy == null) ? (HttpURLConnection) url.openConnection() : (HttpURLConnection) url.openConnection(proxy); + } finally { + lock.unlock(); + } } }
diff --git a/core-common/src/main/java/org/glassfish/jersey/ApplicationSupplier.java b/core-common/src/main/java/org/glassfish/jersey/ApplicationSupplier.java new file mode 100644 index 0000000..6ef17b9 --- /dev/null +++ b/core-common/src/main/java/org/glassfish/jersey/ApplicationSupplier.java
@@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + + +package org.glassfish.jersey; + +import jakarta.ws.rs.core.Application; + +/** + * Implementation of this interface is capable of returning {@link Application}. + */ +public interface ApplicationSupplier { + /** + * Get Application. + * + * @return Application. + */ + Application getApplication(); + +}
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 ced63b3..308ff94 100644 --- a/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java +++ b/core-common/src/main/java/org/glassfish/jersey/CommonProperties.java
@@ -71,7 +71,7 @@ /** * If {@code true} then disable feature auto discovery globally on client/server. * <p> - * By default auto discovery is automatically enabled. The value of this property may be overridden by the client/server + * By default, auto discovery is automatically enabled. The value of this property may be overridden by the client/server * variant of this property. * <p> * The default value is {@code false}. @@ -98,10 +98,55 @@ */ public static final String FEATURE_AUTO_DISCOVERY_DISABLE_SERVER = "jersey.config.server.disableAutoDiscovery"; + + /** + * If {@code true} then disable configuration of Json Binding (JSR-367) feature. + * <p> + * By default, Json Binding is automatically enabled. The value of this property may be overridden by the client/server + * variant of this property. + * <p> + * The default value is {@code false}. + * </p> + * <p> + * The name of the configuration property is <tt>{@value}</tt>. + * </p> + * @since 2.45 + */ + public static final String JSON_BINDING_FEATURE_DISABLE = "jersey.config.disableJsonBinding"; + + /** + * Client-specific version of {@link CommonProperties#JSON_BINDING_FEATURE_DISABLE}. + * + * If present, it overrides the generic one for the client environment. + * @since 2.45 + */ + public static final String JSON_BINDING_FEATURE_DISABLE_CLIENT = "jersey.config.client.disableJsonBinding"; + + /** + * Server-specific version of {@link CommonProperties#JSON_BINDING_FEATURE_DISABLE}. + * + * If present, it overrides the generic one for the server environment. + * @since 2.45 + */ + public static final String JSON_BINDING_FEATURE_DISABLE_SERVER = "jersey.config.server.disableJsonBinding"; + + /** + * Disables configuration of Json Binding (JSR-367) feature for {@link jakarta.ws.rs.core.Application} subclasses whose + * package names are specified as a value. The value is comma-separated string defining prefixes of the application + * package names. + * <p> + * By default, Json Binding is automatically enabled. + * <p> + * The name of the configuration property is <tt>{@value}</tt>. + * </p> + * @since 2.45 + */ + public static final String JSON_BINDING_FEATURE_DISABLE_APPLICATION = "jersey.config.application.disableJsonBinding"; + /** * If {@code true} then disable configuration of Json Processing (JSR-353) feature. * <p> - * By default Json Processing is automatically enabled. The value of this property may be overridden by the client/server + * By default, Json Processing is automatically enabled. The value of this property may be overridden by the client/server * variant of this property. * <p> * The default value is {@code false}. @@ -131,7 +176,7 @@ /** * If {@code true} then disable META-INF/services lookup globally on client/server. * <p> - * By default Jersey looks up SPI implementations described by META-INF/services/* files. + * By default, Jersey looks up SPI implementations described by META-INF/services/* files. * Then you can register appropriate provider classes by {@link jakarta.ws.rs.core.Application}. * </p> * <p> @@ -164,7 +209,7 @@ /** * If {@code true} then disable configuration of MOXy Json feature. * <p> - * By default MOXy Json is automatically enabled. The value of this property may be overridden by the client/server + * By default, MOXy Json is automatically enabled. The value of this property may be overridden by the client/server * variant of this property. * <p> * The default value is {@code false}.
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/util/PropertiesHelper.java b/core-common/src/main/java/org/glassfish/jersey/internal/util/PropertiesHelper.java index 5500e54..97dee37 100644 --- a/core-common/src/main/java/org/glassfish/jersey/internal/util/PropertiesHelper.java +++ b/core-common/src/main/java/org/glassfish/jersey/internal/util/PropertiesHelper.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -390,6 +390,27 @@ } /** + * Converts the property value to {@code boolean} and checks it is {@code true} or empty. + * Returns {@code true} if the value is {@code true} or empty but not {@code null}. + * + * <p> + * The rationale behind this is that system property {@code -Dprop=true} is the same as {@code -Dprop}. + * The property {@code -Dprop=false} behaves as if the {@code -Dprop} is not set at all. + * </p> + * + * @param value property value. + * @return {@code boolean} property value or {@code true} if the property value is not set or {@code false} if the property + * is otherwise not convertible. + */ + public static boolean isPropertyOrNotSet(final Object value) { + if (value instanceof Boolean) { + return Boolean.class.cast(value); + } else { + return value != null && ("".equals(value.toString()) || Boolean.parseBoolean(value.toString())); + } + } + + /** * Faster replacement of {@code RuntimeType#name().toLowerCase(Locale.ROOT)} * @param runtimeType The runtime type to lower case * @return the lower-cased variant of the {@link RuntimeType}.
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Views.java b/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Views.java index 32e2640..4765056 100644 --- a/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Views.java +++ b/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Views.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -24,13 +24,12 @@ import java.util.List; import java.util.ListIterator; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; -import static org.glassfish.jersey.internal.guava.Preconditions.checkNotNull; - /** * Collections utils, which provide transforming views for {@link List} and {@link Map}. * @@ -197,8 +196,8 @@ * @return union view of given sets. */ public static <E> Set<E> setUnionView(final Set<? extends E> set1, final Set<? extends E> set2) { - checkNotNull(set1, "set1"); - checkNotNull(set2, "set2"); + Objects.requireNonNull(set1, "set1"); + Objects.requireNonNull(set2, "set2"); return new AbstractSet<E>() { @Override @@ -220,18 +219,19 @@ } /** - * Create a view of a difference of provided sets. + * Create a view of a difference of provided sets, i.e. the diff filters out from the first set the items included + * in the second set. * <p> * View is updated whenever any of the provided set changes. * * @param set1 first set. * @param set2 second set. * @param <E> set item type. - * @return union view of given sets. + * @return view that is a difference of given sets. */ public static <E> Set<E> setDiffView(final Set<? extends E> set1, final Set<? extends E> set2) { - checkNotNull(set1, "set1"); - checkNotNull(set2, "set2"); + Objects.requireNonNull(set1, "set1"); + Objects.requireNonNull(set2, "set2"); return new AbstractSet<E>() { @Override
diff --git a/core-common/src/main/java/org/glassfish/jersey/io/package-info.java b/core-common/src/main/java/org/glassfish/jersey/io/package-info.java new file mode 100644 index 0000000..f913ae6 --- /dev/null +++ b/core-common/src/main/java/org/glassfish/jersey/io/package-info.java
@@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/** + * Common Jersey core io classes. + */ +package org.glassfish.jersey.io;
diff --git a/core-common/src/main/java/org/glassfish/jersey/io/spi/FlushedCloseable.java b/core-common/src/main/java/org/glassfish/jersey/io/spi/FlushedCloseable.java new file mode 100644 index 0000000..12aa714 --- /dev/null +++ b/core-common/src/main/java/org/glassfish/jersey/io/spi/FlushedCloseable.java
@@ -0,0 +1,55 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.jersey.io.spi; + +import java.io.Closeable; +import java.io.Flushable; +import java.io.IOException; +import java.io.OutputStream; + +/** + * A marker interface that the stream provided to Jersey can implement, + * noting that the stream does not need to call {@link #flush()} prior to {@link #close()}. + * That way, {@link #flush()} method is not called twice. + * + * <p> + * Usable by {@link javax.ws.rs.client.ClientRequestContext#setEntityStream(OutputStream)}. + * Usable by {@link javax.ws.rs.container.ContainerResponseContext#setEntityStream(OutputStream)}. + * </p> + * + * <p> + * This marker interface can be useful for the customer OutputStream to know the {@code flush} did not come from + * Jersey before close. By default, when the entity stream is to be closed by Jersey, {@code flush} is called first. + * </p> + */ +public interface FlushedCloseable extends Flushable, Closeable { + /** + * Flushes this stream by writing any buffered output to the underlying stream. + * Then closes this stream and releases any system resources associated + * with it. If the stream is already closed then invoking this + * method has no effect. + * + * <p> As noted in {@link AutoCloseable#close()}, cases where the + * close may fail require careful attention. It is strongly advised + * to relinquish the underlying resources and to internally + * <em>mark</em> the {@code Closeable} as closed, prior to throwing + * the {@code IOException}. + * + * @throws IOException if an I/O error occurs + */ + public void close() throws IOException; +}
diff --git a/core-common/src/main/java/org/glassfish/jersey/io/spi/package-info.java b/core-common/src/main/java/org/glassfish/jersey/io/spi/package-info.java new file mode 100644 index 0000000..7a70945 --- /dev/null +++ b/core-common/src/main/java/org/glassfish/jersey/io/spi/package-info.java
@@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +/** + * Common Jersey core io SPI classes. + */ +package org.glassfish.jersey.io.spi;
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/OutboundMessageContext.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/OutboundMessageContext.java index c69f173..b1b7745 100644 --- a/core-common/src/main/java/org/glassfish/jersey/message/internal/OutboundMessageContext.java +++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/OutboundMessageContext.java
@@ -46,6 +46,7 @@ import org.glassfish.jersey.internal.util.collection.LazyValue; import org.glassfish.jersey.internal.util.collection.Value; import org.glassfish.jersey.internal.util.collection.Values; +import org.glassfish.jersey.io.spi.FlushedCloseable; /** * Base outbound message context implementation. @@ -561,11 +562,13 @@ if (hasEntity()) { try { final OutputStream es = getEntityStream(); - es.flush(); + if (!FlushedCloseable.class.isInstance(es)) { + es.flush(); + } es.close(); } catch (IOException e) { // Happens when the client closed connection before receiving the full response. - // This is OK and not interesting in vast majority of the cases + // This is OK and not interesting in the vast majority of the cases // hence the log level set to FINE to make sure it does not flood the log unnecessarily // (especially for clients disconnecting from SSE listening, which is very common). Logger.getLogger(OutboundMessageContext.class.getName()).log(Level.FINE, e.getMessage(), e);
diff --git a/core-common/src/test/java/org/glassfish/jersey/internal/util/PropertiesHelperTest.java b/core-common/src/test/java/org/glassfish/jersey/internal/util/PropertiesHelperTest.java index 67df369..237e749 100644 --- a/core-common/src/test/java/org/glassfish/jersey/internal/util/PropertiesHelperTest.java +++ b/core-common/src/test/java/org/glassfish/jersey/internal/util/PropertiesHelperTest.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -199,4 +199,15 @@ } + @Test + public void isPropertyOrNotSetTest() { + assertEquals(false, PropertiesHelper.isPropertyOrNotSet((Boolean) null)); + assertEquals(true, PropertiesHelper.isPropertyOrNotSet(Boolean.TRUE)); + assertEquals(false, PropertiesHelper.isPropertyOrNotSet(Boolean.FALSE)); + assertEquals(false, PropertiesHelper.isPropertyOrNotSet((String) null)); + assertEquals(true, PropertiesHelper.isPropertyOrNotSet("")); + assertEquals(false, PropertiesHelper.isPropertyOrNotSet("treu")); // false for non-boolean values + assertEquals(true, PropertiesHelper.isPropertyOrNotSet("TRUE")); + assertEquals(false, PropertiesHelper.isPropertyOrNotSet("false")); + } }
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java b/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java index ae39a68..6fc7a2a 100644 --- a/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java +++ b/core-server/src/main/java/org/glassfish/jersey/server/ResourceConfig.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -39,6 +39,7 @@ import jakarta.ws.rs.core.Configuration; import jakarta.ws.rs.core.Feature; +import org.glassfish.jersey.ApplicationSupplier; import org.glassfish.jersey.internal.Errors; import org.glassfish.jersey.internal.config.ExternalPropertiesConfigurationFactory; import org.glassfish.jersey.internal.inject.Binder; @@ -70,7 +71,7 @@ * @author Michal Gajdos * @author Marek Potociar */ -public class ResourceConfig extends Application implements Configurable<ResourceConfig>, ServerConfig { +public class ResourceConfig extends Application implements Configurable<ResourceConfig>, ServerConfig, ApplicationSupplier { private static final Logger LOGGER = Logger.getLogger(ResourceConfig.class.getName());
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ServerProperties.java b/core-server/src/main/java/org/glassfish/jersey/server/ServerProperties.java index 5d8a3ad..3ef8565 100644 --- a/core-server/src/main/java/org/glassfish/jersey/server/ServerProperties.java +++ b/core-server/src/main/java/org/glassfish/jersey/server/ServerProperties.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -304,7 +304,7 @@ /** * If {@code true} then disable auto discovery on server. * - * By default auto discovery is automatically enabled if global property + * By default, auto discovery is automatically enabled if global property * {@value org.glassfish.jersey.CommonProperties#FEATURE_AUTO_DISCOVERY_DISABLE} is not disabled. If set then the server * property value overrides the global property value. * <p> @@ -345,9 +345,28 @@ public static final String OUTBOUND_CONTENT_LENGTH_BUFFER = CommonProperties.OUTBOUND_CONTENT_LENGTH_BUFFER_SERVER; /** + * If {@code true} then disable configuration of Json Binding (JSR-367) feature on server. + * + * By default, Json Binding is automatically enabled if global property + * {@value org.glassfish.jersey.CommonProperties#JSON_BINDING_FEATURE_DISABLE} is not disabled. If set then the server + * property value overrides the global property value. + * <p> + * The default value is {@code false}. + * </p> + * <p> + * The name of the configuration property is <tt>{@value}</tt>. + * </p> + * <p>This constant is an alias for {@link CommonProperties#JSON_BINDING_FEATURE_DISABLE_SERVER}</p> + * + * @see org.glassfish.jersey.CommonProperties#JSON_BINDING_FEATURE_DISABLE + */ + @PropertyAlias + public static final String JSON_BINDING_FEATURE_DISABLE = CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER; + + /** * If {@code true} then disable configuration of Json Processing (JSR-353) feature on server. * - * By default Json Processing is automatically enabled if global property + * By default, Json Processing is automatically enabled if global property * {@value org.glassfish.jersey.CommonProperties#JSON_PROCESSING_FEATURE_DISABLE} is not disabled. If set then the server * property value overrides the global property value. * <p> @@ -366,7 +385,7 @@ /** * If {@code true} then disable META-INF/services lookup on server. * - * By default Jersey looks up SPI implementations described by META-INF/services/* files. + * By default, Jersey looks up SPI implementations described by META-INF/services/* files. * Then you can register appropriate provider classes by {@link jakarta.ws.rs.core.Application}. * <p> * The default value is {@code false}. @@ -385,7 +404,7 @@ /** * If {@code true} then disable configuration of MOXy Json feature on server. * - * By default MOXy Json is automatically enabled if global property + * By default, MOXy Json is automatically enabled if global property * {@value org.glassfish.jersey.CommonProperties#MOXY_JSON_FEATURE_DISABLE} is not disabled. If set then the server * property value overrides the global property value. * <p>
diff --git a/docs/src/main/docbook/appendix-properties.xml b/docs/src/main/docbook/appendix-properties.xml index 02cf239..4294bae 100644 --- a/docs/src/main/docbook/appendix-properties.xml +++ b/docs/src/main/docbook/appendix-properties.xml
@@ -72,6 +72,40 @@ </entry> </row> <row> + <entry>&jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE; / + &jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT; / + &jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER;</entry> + <entry><literal>jersey.config.disableJsonBinding</literal> / + <literal>jersey.config.client.disableJsonBinding</literal> / + <literal>jersey.config.server.disableJsonBinding</literal></entry> + <entry> + <para> + Disables configuration of Json Binding (JSR-367) feature. Default value is <literal>false</literal>. + Can also be set as a system property. + </para> + <para> + Since 2.45. + </para> + </entry> + </row> + <row> + <entry>&jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION; </entry> + <entry><literal>jersey.config.application.disableJsonBinding</literal></entry> + <entry> + <para> + Disables configuration of Json Binding (JSR-367) feature for <literal>jakarta.ws.rs.core.Application</literal> + subclasses whose package names are specified as a value. The value is comma-separated string + defining prefixes of the application package names. Can also be set as a system property. + </para> + <para> + By default, Json Binding is automatically enabled. + </para> + <para> + Since 2.45. + </para> + </entry> + </row> + <row> <entry>&jersey.common.CommonProperties.JSON_PROCESSING_FEATURE_DISABLE; / &jersey.common.CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_CLIENT; / &jersey.common.CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_SERVER;</entry> @@ -416,6 +450,15 @@ </entry> </row> <row> + <entry>&jersey.server.ServerProperties.JSON_BINDING_FEATURE_DISABLE;</entry> + <entry><literal>jersey.config.server.disableJsonBinding</literal></entry> + <entry> + <para> + Disables configuration of Json Processing (JSR-353) feature. Default value is <literal>false</literal>. + </para> + </entry> + </row> + <row> <entry>&jersey.server.ServerProperties.JSON_PROCESSING_FEATURE_DISABLE;</entry> <entry><literal>jersey.config.server.disableJsonProcessing</literal></entry> <entry> @@ -1106,6 +1149,15 @@ </entry> </row> <row> + <entry>&jersey.client.ClientProperties.JSON_BINDING_FEATURE_DISABLE;</entry> + <entry><literal>jersey.config.client.disableJsonBinding</literal></entry> + <entry> + <para> + Disables configuration of Json Binding (JSR-367) feature. Default value is <literal>false</literal>. + </para> + </entry> + </row> + <row> <entry>&jersey.client.ClientProperties.JSON_PROCESSING_FEATURE_DISABLE;</entry> <entry><literal>jersey.config.client.disableJsonProcessing</literal></entry> <entry>
diff --git a/docs/src/main/docbook/jersey.ent b/docs/src/main/docbook/jersey.ent index 1893612..5fe6f8a 100644 --- a/docs/src/main/docbook/jersey.ent +++ b/docs/src/main/docbook/jersey.ent
@@ -351,6 +351,7 @@ <!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>" > +<!ENTITY jersey.client.ClientProperties.JSON_BINDING_FEATURE_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#JSON_BINDING_FEATURE_DISABLE'>ClientProperties.JSON_BINDING_FEATURE_DISABLE</link>" > <!ENTITY jersey.client.ClientProperties.JSON_PROCESSING_FEATURE_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#JSON_PROCESSING_FEATURE_DISABLE'>ClientProperties.JSON_PROCESSING_FEATURE_DISABLE</link>" > <!ENTITY jersey.client.ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#METAINF_SERVICES_LOOKUP_DISABLE'>ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE</link>" > <!ENTITY jersey.client.ClientProperties.MOXY_JSON_FEATURE_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/client/ClientProperties.html#MOXY_JSON_FEATURE_DISABLE'>ClientProperties.MOXY_JSON_FEATURE_DISABLE</link>" > @@ -396,6 +397,10 @@ <!ENTITY jersey.common.CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#FEATURE_AUTO_DISCOVERY_DISABLE'>CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE</link>" > <!ENTITY jersey.common.CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE_CLIENT "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#FEATURE_AUTO_DISCOVERY_DISABLE_CLIENT'>CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE_CLIENT</link>" > <!ENTITY jersey.common.CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE_SERVER "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#FEATURE_AUTO_DISCOVERY_DISABLE_SERVER'>CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE_SERVER</link>" > +<!ENTITY jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_BINDING_FEATURE_DISABLE'>CommonProperties.JSON_BINDING_FEATURE_DISABLE</link>" > +<!ENTITY jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_BINDING_FEATURE_DISABLE_CLIENT'>CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT</link>" > +<!ENTITY jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_BINDING_FEATURE_DISABLE_SERVER'>CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER</link>" > +<!ENTITY jersey.common.CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_BINDING_FEATURE_DISABLE_APPLICATION'>CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION</link>" > <!ENTITY jersey.common.CommonProperties.JSON_PROCESSING_FEATURE_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_PROCESSING_FEATURE_DISABLE'>CommonProperties.JSON_PROCESSING_FEATURE_DISABLE</link>" > <!ENTITY jersey.common.CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_CLIENT "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_PROCESSING_FEATURE_DISABLE_CLIENT'>CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_CLIENT</link>" > <!ENTITY jersey.common.CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_SERVER "<link xlink:href='&jersey.javadoc.uri.prefix;/CommonProperties.html#JSON_PROCESSING_FEATURE_DISABLE_SERVER'>CommonProperties.JSON_PROCESSING_FEATURE_DISABLE_SERVER</link>" > @@ -626,6 +631,7 @@ <!ENTITY jersey.server.ServerProperties.BV_SEND_ERROR_IN_RESPONSE "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#BV_SEND_ERROR_IN_RESPONSE'>ServerProperties.BV_SEND_ERROR_IN_RESPONSE</link>" > <!ENTITY jersey.server.ServerProperties.FEATURE_AUTO_DISCOVERY_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#FEATURE_AUTO_DISCOVERY_DISABLE'>ServerProperties.FEATURE_AUTO_DISCOVERY_DISABLE</link>" > <!ENTITY jersey.server.ServerProperties.HTTP_METHOD_OVERRIDE "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#HTTP_METHOD_OVERRIDE'>ServerProperties.HTTP_METHOD_OVERRIDE</link>" > +<!ENTITY jersey.server.ServerProperties.JSON_BINDING_FEATURE_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#JSON_BINDING_FEATURE_DISABLE'>ServerProperties.JSON_BINDING_FEATURE_DISABLE</link>" > <!ENTITY jersey.server.ServerProperties.JSON_PROCESSING_FEATURE_DISABLE "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#JSON_PROCESSING_FEATURE_DISABLE'>ServerProperties.JSON_PROCESSING_FEATURE_DISABLE</link>" > <!ENTITY jersey.server.ServerProperties.LANGUAGE_MAPPINGS "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#LANGUAGE_MAPPINGS'>ServerProperties.LANGUAGE_MAPPINGS</link>" > <!ENTITY jersey.server.ServerProperties.MEDIA_TYPE_MAPPINGS "<link xlink:href='&jersey.javadoc.uri.prefix;/server/ServerProperties.html#MEDIA_TYPE_MAPPINGS'>ServerProperties.MEDIA_TYPE_MAPPINGS</link>" >
diff --git a/examples/NOTICE.md b/examples/NOTICE.md index 4fa2d36..6f522b3 100644 --- a/examples/NOTICE.md +++ b/examples/NOTICE.md
@@ -1,4 +1,4 @@ -# Notice for Jersey +# Notice for Jersey This content is produced and maintained by the Eclipse Jersey project. * Project home: https://projects.eclipse.org/projects/ee4j.jersey @@ -39,8 +39,8 @@ Bean Validation API 3.0.2 * License: Apache License, 2.0 -* Project: http://beanvalidation.org/1.1/ -* Copyright: 2009, Red Hat, Inc. and/or its affiliates, and individual contributors +* Project: http://beanvalidation.org/3.0/ +* Copyright: 2009, 2020 Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. Hibernate Validator CDI, 8.0.1.Final @@ -58,25 +58,25 @@ * Project: http://www.seamframework.org/Weld * Copyright 2010, Red Hat, Inc., and individual contributors by the @authors tag. -Google Guava Version 18.0 +Google Guava Version 33.3.0-jre * License: Apache License, 2.0 -* Copyright (C) 2009 The Guava Authors +* Copyright (C) 2009, 2024 The Guava Authors -jakarta.inject Version: 1 +jakarta.inject Version: 2.0.1 * License: Apache License, 2.0 -* Copyright (C) 2009 The JSR-330 Expert Group +* Copyright (C) 2009, 2021 The JSR-330 Expert Group Javassist Version 3.30.2-GA * License: Apache License, 2.0 * Project: http://www.javassist.org/ * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved. -Jackson JAX-RS Providers Version 2.17.1 +Jackson JAX-RS Providers Version 2.17.2 * License: Apache License, 2.0 * Project: https://github.com/FasterXML/jackson-jaxrs-providers * Copyright: (c) 2009-2023 FasterXML, LLC. All rights reserved unless otherwise indicated. -jQuery v1.12.4 +jQuery v3.7.1 * License: jquery.org/license * Project: jquery.org * Copyright: (c) jQuery Foundation
diff --git a/examples/extended-wadl-webapp/README.MD b/examples/extended-wadl-webapp/README.MD index d7a59d1..6c4f676 100644 --- a/examples/extended-wadl-webapp/README.MD +++ b/examples/extended-wadl-webapp/README.MD
@@ -15,9 +15,6 @@ Contents -------- -The description of what's done here you'll find in the [jersey 1 -wiki](https://wikis.oracle.com/display/Jersey/HowToConfigureExtendedWADL). - The difference in configuration against jersey 1.x is in property configuring the custom WadlGeneratorConfig. Instead of property key 'com.sun.jersey.config.property.WadlGeneratorConfig' use the property @@ -48,6 +45,8 @@ instructions at [the module README file](../../README.html) in order to deploy the example. +NOTE: the example must be run with a JDK prior to JDK 13 otherwise javadoc plugin won't work properly. + Otherwise, you can run the example using embedded GlassFish as follows: You can run the example using Grizzly as follows:
diff --git a/examples/extended-wadl-webapp/pom.xml b/examples/extended-wadl-webapp/pom.xml index 37d5044..6cc3283 100644 --- a/examples/extended-wadl-webapp/pom.xml +++ b/examples/extended-wadl-webapp/pom.xml
@@ -108,7 +108,7 @@ <!-- logging --> <dependency> <groupId>org.slf4j</groupId> - <artifactId>slf4j-log4j12</artifactId> + <artifactId>slf4j-reload4j</artifactId> <version>${slf4j.version}</version> <scope>test</scope> </dependency> @@ -150,7 +150,7 @@ <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>jaxb2-maven-plugin</artifactId> - <version>2.5.0</version> + <version>3.2.0</version> <executions> <execution> <id>xjc</id> @@ -291,6 +291,57 @@ <profiles> <profile> + <id>javadocAndTestsSkipJDK13</id> + <activation> + <jdk>[13,)</jdk> + </activation> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <skip>true</skip> + </configuration> + </plugin> + <plugin> + <artifactId>maven-antrun-plugin</artifactId> + <executions> + <execution> + <phase>generate-resources</phase> + <goals> + <goal>run</goal> + </goals> + <configuration> + <target> + <echo>****************************************************</echo> + <echo>****THIS EXAMPLE WORKS ONLY ON JDKs PRIOR to 13!****</echo> + <echo>********CURRENT JDK IS NOT SUPPORTED!***************</echo> + <echo>****************************************************</echo> + </target> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.jvnet.jaxb2.maven2</groupId> + <artifactId>maven-jaxb2-plugin</artifactId> + <version>0.14.0</version> + <configuration> + <verbose>false</verbose> + </configuration> + </plugin> + </plugins> + </build> + </profile> + <profile> <id>pre-release</id> <build> <plugins>
diff --git a/examples/osgi-http-service/functional-test/pom.xml b/examples/osgi-http-service/functional-test/pom.xml index 576fb1c..6e74fc8 100644 --- a/examples/osgi-http-service/functional-test/pom.xml +++ b/examples/osgi-http-service/functional-test/pom.xml
@@ -144,7 +144,7 @@ <!-- Logging dependencies--> <dependency> <groupId>org.slf4j</groupId> - <artifactId>slf4j-log4j12</artifactId> + <artifactId>slf4j-reload4j</artifactId> <version>${slf4j.version}</version> <scope>test</scope> </dependency>
diff --git a/examples/servlet3-webapp/pom.xml b/examples/servlet3-webapp/pom.xml index 1a6968d..96f742a 100644 --- a/examples/servlet3-webapp/pom.xml +++ b/examples/servlet3-webapp/pom.xml
@@ -112,6 +112,15 @@ <profiles> <profile> + <id>jdk8_tests</id> + <activation> + <jdk>1.8</jdk> + </activation> + <properties> + <junit5.version>${junit5.jdk8.version}</junit5.version> + </properties> + </profile> + <profile> <id>pre-release</id> <build> <plugins>
diff --git a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProvider.java b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProvider.java index e41d4c9..a47aced 100644 --- a/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProvider.java +++ b/ext/cdi/jersey-cdi1x/src/main/java/org/glassfish/jersey/ext/cdi1x/internal/CdiComponentProvider.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2022 Payara Foundation and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the @@ -45,7 +45,6 @@ import jakarta.inject.Singleton; import jakarta.ws.rs.core.Application; - import jakarta.annotation.ManagedBean; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.context.RequestScoped; @@ -143,6 +142,8 @@ private volatile Map<Class<?>, Set<Method>> methodsToSkip = new HashMap<>(); private volatile Map<Class<?>, Set<Field>> fieldsToSkip = new HashMap<>(); + private boolean initialized = false; + public CdiComponentProvider() { customHk2TypesProvider = CdiUtil.lookupService(Hk2CustomBoundTypesProvider.class); injectionManagerStore = CdiUtil.createHk2InjectionManagerStore(); @@ -154,7 +155,7 @@ this.injectionManager = injectionManager; this.beanManager = CdiUtil.getBeanManager(); - if (beanManager != null) { + if (beanManager != null && !injectionManager.getClass().getSimpleName().equals("NonInjectionManager")) { // Try to get CdiComponentProvider created by CDI. final CdiComponentProvider extension = beanManager.getExtension(CdiComponentProvider.class); @@ -167,18 +168,19 @@ bindHk2ClassAnalyzer(); LOGGER.config(LocalizationMessages.CDI_PROVIDER_INITIALIZED()); + initialized = true; } } } @Override public boolean bind(final Class<?> clazz, final Set<Class<?>> providerContracts) { - return bind(clazz, providerContracts, ContractProvider.NO_PRIORITY); + return initialized && bind(clazz, providerContracts, ContractProvider.NO_PRIORITY); } @Override public boolean bind(Class<?> component, ContractProvider contractProvider) { - return contractProvider != null + return initialized && contractProvider != null ? bind(component, contractProvider.getContracts(), contractProvider.getPriority(component)) : bind(component, Collections.EMPTY_SET); } @@ -628,11 +630,8 @@ ClassAnalyzer defaultClassAnalyzer = injectionManager.getInstance(ClassAnalyzer.class, ClassAnalyzer.DEFAULT_IMPLEMENTATION_NAME); - int skippedElements = methodsToSkip.size() + fieldsToSkip.size(); - - ClassAnalyzer customizedClassAnalyzer = skippedElements > 0 - ? new InjecteeSkippingAnalyzer(defaultClassAnalyzer, methodsToSkip, fieldsToSkip, beanManager) - : defaultClassAnalyzer; + ClassAnalyzer customizedClassAnalyzer = + new InjecteeSkippingAnalyzer(defaultClassAnalyzer, methodsToSkip, fieldsToSkip, beanManager); Binder binder = new AbstractBinder() { @Override
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/BeanHelper.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/BeanHelper.java index b653b54..a1c5032 100644 --- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/BeanHelper.java +++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/BeanHelper.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -129,13 +129,7 @@ * CDI does not provide sufficient support for ThreadScoped Supplier */ if (binding.getScope() == PerThread.class) { - BeanManagerImpl manager; - if (beanManager instanceof BeanManagerProxy) { - manager = ((BeanManagerProxy) beanManager).unwrap(); - } else { - manager = (BeanManagerImpl) beanManager; - } - abd.addBean(new InitializableSupplierThreadScopeBean(runtimeType, binding, manager)); + abd.addBean(new InitializableSupplierThreadScopeBean(runtimeType, binding, beanManagerImpl(beanManager))); } else { abd.addBean(new InitializableSupplierInstanceBean<>(runtimeType, binding)); abd.addBean(new InitializableSupplierInstanceBeanBridge<>(runtimeType, binding)); @@ -164,12 +158,18 @@ InjectionTarget<Supplier<T>> jit = getJerseyInjectionTarget(supplierClass, injectionTarget, supplierBean, resolvers); supplierBean.setInjectionTarget(jit); - final SupplierBeanBridge supplierBeanBridge = new SupplierBeanBridge(runtimeType, binding, beanManager); - - abd.addBean(supplierBean); - abd.addBean(supplierBeanBridge); - - return new BindingBeanPair(binding, supplierBean, supplierBeanBridge); + /* + * CDI does not provide sufficient support for ThreadScoped Supplier + */ + if (binding.getScope() == PerThread.class) { + abd.addBean(new SupplierThreadScopeClassBean(runtimeType, binding, supplierBean, beanManagerImpl(beanManager))); + return null; + } else { + final SupplierBeanBridge supplierBeanBridge = new SupplierBeanBridge(runtimeType, binding, beanManager); + abd.addBean(supplierBean); + abd.addBean(supplierBeanBridge); + return new BindingBeanPair(binding, supplierBean, supplierBeanBridge); + } } /** @@ -258,6 +258,14 @@ return null; } + private static BeanManagerImpl beanManagerImpl(BeanManager beanManager) { + if (beanManager instanceof BeanManagerProxy) { + return ((BeanManagerProxy) beanManager).unwrap(); + } else { + return (BeanManagerImpl) beanManager; + } + } + private static <T> InjectionTarget<T> getJerseyInjectionTarget(Class<T> clazz, InjectionTarget<T> injectionTarget, Bean<T> bean, Collection<InjectionResolver> resolvers) { BasicInjectionTarget<T> it = (BasicInjectionTarget<T>) injectionTarget;
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierThreadScopeBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierThreadScopeBean.java index c5f211e..3415b46 100644 --- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierThreadScopeBean.java +++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierThreadScopeBean.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -111,31 +111,4 @@ ProxyFactory<T> factory = new ProxyFactory<>(contextId, getBeanClass(), getTypes(), this); return factory.create(beanInstance); } - - private static class ThreadScopeBeanInstance<T> extends ContextBeanInstance<T> { - - private final WeakHashMap<Thread, Object> instances = new WeakHashMap<>(); - - private final Supplier<T> supplier; - - /** - * Creates a new invocation handler with supplier which provides a current injected value in proper scope. - * - * @param supplier provider of the value. - */ - private ThreadScopeBeanInstance(Supplier<T> supplier, Bean<T> bean, String contextId) { - super(bean, new StringBeanIdentifier(((PassivationCapable) bean).getId()), contextId); - this.supplier = supplier; - } - - @Override - public Object invoke(Object obj, Method method, Object... arguments) throws Throwable { - Object instance = instances.computeIfAbsent(Thread.currentThread(), thread -> supplier.get()); - return super.invoke(instance, method, arguments); - } - - public void dispose() { - this.instances.clear(); - } - } }
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/SupplierThreadScopeClassBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/SupplierThreadScopeClassBean.java new file mode 100644 index 0000000..fe3e8b4 --- /dev/null +++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/SupplierThreadScopeClassBean.java
@@ -0,0 +1,114 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.jersey.inject.weld.internal.bean; + +import org.glassfish.jersey.internal.inject.SupplierClassBinding; +import org.glassfish.jersey.internal.inject.SupplierInstanceBinding; +import org.glassfish.jersey.internal.util.collection.LazyValue; +import org.glassfish.jersey.internal.util.collection.Value; +import org.glassfish.jersey.internal.util.collection.Values; +import org.jboss.weld.bean.proxy.BeanInstance; +import org.jboss.weld.bean.proxy.ProxyFactory; +import org.jboss.weld.manager.BeanManagerImpl; + +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.context.spi.CreationalContext; +import jakarta.ws.rs.RuntimeType; +import java.lang.annotation.Annotation; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; + + +/** + * Creates an implementation of {@link jakarta.enterprise.inject.spi.Bean} interface using Jersey's {@link SupplierInstanceBinding}. + * Binding provides the information about the bean also called {@link jakarta.enterprise.inject.spi.BeanAttributes} information. + * The {@code Bean} does not use {@link org.glassfish.jersey.inject.weld.internal.injector.JerseyInjectionTarget} because serves already + * created proxy, therefore the create operation just return provided instance without any other contextual operation + * (produce, inject, destroy). + * <p> + * This bean is special and is used only for service registered as a {@link org.glassfish.jersey.internal.inject.PerThread} and + * works through the proxy which serves the correct instance per the given thread. + * <p> + * Register example: + * <pre> + * AbstractBinder { + * @Override + * protected void configure() { + * bindFactory(MyFactoryInjectionSupplier.class) + * .to(MyBean.class) + * .in(PerThread.class); + * } + * } + * </pre> + * Inject example: + * <pre> + * @Path("/") + * public class MyResource { + * @Inject + * private MyBean myBean; + * } + * </pre> + */ +class SupplierThreadScopeClassBean extends JerseyBean<Object> { + private final LazyValue<ThreadScopeBeanInstance<Object>> beanInstance; + private final SupplierClassBinding binding; + private final LazyValue<Object> proxy; + private final AtomicReference<CreationalContext> creationalContextAtomicReference = new AtomicReference<>(); + + SupplierThreadScopeClassBean(RuntimeType runtimeType, + SupplierClassBinding binding, + SupplierClassBean supplierClassBean, + BeanManagerImpl beanManager) { + super(runtimeType, binding); + this.binding = binding; + this.beanInstance = Values.lazy((Value<ThreadScopeBeanInstance<Object>>) () -> { + Supplier supplierInstance = supplierClassBean.create(creationalContextAtomicReference.get()); + ThreadScopeBeanInstance scopeBeanInstance = + new ThreadScopeBeanInstance(supplierInstance, this, beanManager.getContextId()); + return scopeBeanInstance; + }); + this.proxy = Values.lazy((Value<Object>) () -> createClientProxy(beanInstance.get(), beanManager.getContextId())); + } + + @Override + public Class<? extends Annotation> getScope() { + return Dependent.class; + } + + @Override + public Object create(CreationalContext<Object> ctx) { + creationalContextAtomicReference.set(ctx); + return proxy.get(); + } + + @Override + public void destroy(Object instance, CreationalContext<Object> creationalContext) { + if (beanInstance.isInitialized()) { + this.beanInstance.get().dispose(); + } + } + + @Override + public Class<?> getBeanClass() { + return (Class<?>) this.binding.getContracts().iterator().next(); + } + + private <T> T createClientProxy(BeanInstance beanInstance, String contextId) { + ProxyFactory<T> factory = new ProxyFactory<>(contextId, getBeanClass(), getTypes(), this); + return factory.create(beanInstance); + } +}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/ThreadScopeBeanInstance.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/ThreadScopeBeanInstance.java new file mode 100644 index 0000000..73ac651 --- /dev/null +++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/ThreadScopeBeanInstance.java
@@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.jersey.inject.weld.internal.bean; + +import org.jboss.weld.bean.StringBeanIdentifier; +import org.jboss.weld.bean.proxy.ContextBeanInstance; + +import jakarta.enterprise.inject.spi.Bean; +import jakarta.enterprise.inject.spi.PassivationCapable; +import java.lang.reflect.Method; +import java.util.WeakHashMap; +import java.util.function.Supplier; + +/** + * {@link org.glassfish.jersey.internal.inject.PerThread} scope bean instance used from + * {@link InitializableSupplierThreadScopeBean} and {@link SupplierThreadScopeClassBean}. + * + * @param <T> Typed of the bean supplied by a {@code Supplier}. + */ +class ThreadScopeBeanInstance<T> extends ContextBeanInstance<T> { + + private final WeakHashMap<Thread, Object> instances = new WeakHashMap<>(); + + private final Supplier<T> supplier; + + /** + * Creates a new invocation handler with supplier which provides a current injected value in proper scope. + * + * @param supplier provider of the value. + */ + ThreadScopeBeanInstance(Supplier<T> supplier, Bean<T> bean, String contextId) { + super(bean, new StringBeanIdentifier(((PassivationCapable) bean).getId()), contextId); + this.supplier = supplier; + } + + @Override + public Object invoke(Object obj, Method method, Object... arguments) throws Throwable { + Object instance = instances.computeIfAbsent(Thread.currentThread(), thread -> supplier.get()); + return super.invoke(instance, method, arguments); + } + + public void dispose() { + this.instances.clear(); + } +}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/BinderRegisterExtension.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/BinderRegisterExtension.java index 60d48e4..8917bb0 100644 --- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/BinderRegisterExtension.java +++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/BinderRegisterExtension.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -347,8 +347,10 @@ } BindingBeanPair pair = BeanHelper.registerSupplier( runtimeType, (SupplierClassBinding<?>) binding, abd, injectionResolvers, beanManager); - for (Type contract : ((SupplierClassBinding<?>) binding).getContracts()) { - supplierClassBindings.add(contract, pair); + if (pair != null) { + for (Type contract : ((SupplierClassBinding<?>) binding).getContracts()) { + supplierClassBindings.add(contract, pair); + } } } else if (InitializableInstanceBinding.class.isAssignableFrom(binding.getClass())) { if (RuntimeType.SERVER == runtimeType
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/CzechGreeting.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/CzechGreeting.java index 68b57d9..14bd268 100644 --- a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/CzechGreeting.java +++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/CzechGreeting.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -26,9 +26,11 @@ static final String GREETING = "Ahoj"; + private String greeting = GREETING + "#" + Thread.currentThread().getName(); + @Override public String getGreeting() { - return GREETING + "#" + Thread.currentThread().getName(); + return greeting; } @Override
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestPreinitialization.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestPreinitialization.java index b7806c1..97d4a49 100644 --- a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestPreinitialization.java +++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestPreinitialization.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -97,6 +97,13 @@ binder.bindFactory(new ThreadScopeTest.SupplierGreeting2(ThreadScopeTest.EnglishGreeting2.GREETING)) .to(ThreadScopeTest.EnglishGreeting2.class) .in(PerThread.class); + + //testSupplierClassBindingThreadScopedInSingletonScope + binder.bindAsContract(ThreadScopeTest.SingletonObject3.class) + .in(Singleton.class); + binder.bindFactory(ThreadScopeTest.SupplierGreeting3.class) + .to(ThreadScopeTest.Greeting3.class) + .in(PerThread.class); } //ClientInstanceInjectionTest
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ThreadScopeTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ThreadScopeTest.java index 144c333..7c959fe 100644 --- a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ThreadScopeTest.java +++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ThreadScopeTest.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -18,6 +18,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; import jakarta.enterprise.context.RequestScoped; @@ -181,7 +182,7 @@ } @Test - public void testThreadScopedInSingletonScope() { + public void testThreadScopedInSingletonScope() throws InterruptedException { // InjectionManager injectionManager = BindingTestHelper.createInjectionManager(); // BindingTestHelper.bind(injectionManager, binder -> { // binder.bindAsContract(SingletonObject.class) @@ -202,6 +203,52 @@ assertNotNull(greeting2); assertEquals(greeting1, greeting2); + + final AtomicReference<String> greetingAtomicReference = new AtomicReference<>(); + Runnable runnable = () -> + greetingAtomicReference.set(injectionManager.getInstance(SingletonObject.class).getGreeting().getGreeting()); + + Thread newThread = new Thread(runnable); + newThread.start(); + newThread.join(); + + assertEquals(greeting1.getGreeting(), greeting2.getGreeting()); + assertNotEquals(greeting1.getGreeting(), greetingAtomicReference.get()); + } + + @Test + public void testSupplierClassBindingThreadScopedInSingletonScope() throws InterruptedException { +// InjectionManager injectionManager = BindingTestHelper.createInjectionManager(); +// BindingTestHelper.bind(injectionManager, binder -> { +// binder.bindAsContract(SingletonObject.class) +// .in(Singleton.class); +// +// binder.bindFactory(SupplierGreeting.class) +// .to(Greeting.class) +// .in(PerThread.class); +// }); + + SingletonObject3 instance1 = injectionManager.getInstance(SingletonObject3.class); + Greeting3 greeting1 = instance1.getGreeting(); + assertNotNull(greeting1); + + // Precisely the same object + SingletonObject3 instance2 = injectionManager.getInstance(SingletonObject3.class); + Greeting3 greeting2 = instance2.getGreeting(); + assertNotNull(greeting2); + + assertEquals(greeting1, greeting2); + + final AtomicReference<String> greetingAtomicReference = new AtomicReference<>(); + Runnable runnable = () -> + greetingAtomicReference.set(injectionManager.getInstance(SingletonObject3.class).getGreeting().getGreeting()); + + Thread newThread = new Thread(runnable); + newThread.start(); + newThread.join(); + + assertEquals(greeting1.getGreeting(), greeting2.getGreeting()); + assertNotEquals(greeting1.getGreeting(), greetingAtomicReference.get()); } @RequestScoped @@ -227,6 +274,17 @@ } @Singleton + public static class SingletonObject3 { + + @Inject + Greeting3 greeting; + + public Greeting3 getGreeting() { + return greeting; + } + } + + @Singleton public static class SingletonObject { @Inject @@ -260,6 +318,14 @@ } @Vetoed + static class SupplierGreeting3 implements Supplier<Greeting3> { + @Override + public Greeting3 get() { + return new CzechGreeting3(); + } + } + + @Vetoed static class SupplierGreeting2 implements Supplier<Greeting2> { private final String greetingType; @@ -291,13 +357,33 @@ } @Vetoed + static class CzechGreeting3 implements Greeting3 { + + static final String GREETING = "Ahoj"; + + private String greeting = GREETING + "#" + Thread.currentThread().getName(); + + @Override + public String getGreeting() { + return greeting; + } + + @Override + public String toString() { + return "CzechGreeting"; + } + } + + @Vetoed static class CzechGreeting2 implements Greeting2 { static final String GREETING = "Ahoj"; + private String greeting = GREETING + "#" + Thread.currentThread().getName(); + @Override public String getGreeting() { - return GREETING + "#" + Thread.currentThread().getName(); + return greeting; } @Override @@ -374,9 +460,11 @@ static final String GREETING = "Ahoj"; + private String greeting = GREETING + "#" + Thread.currentThread().getName(); + @Override public String getGreeting() { - return GREETING + "#" + Thread.currentThread().getName(); + return greeting; } @Override @@ -386,6 +474,11 @@ } @FunctionalInterface + static interface Greeting3 { + String getGreeting(); + } + + @FunctionalInterface static interface Greeting2 { String getGreeting(); }
diff --git a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/BeanHelper.java b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/BeanHelper.java index 584193f..053dbe8 100644 --- a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/BeanHelper.java +++ b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/BeanHelper.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -116,18 +116,11 @@ * @param <T> type of the instance which is registered. */ public static <T> void registerSupplier(SupplierInstanceBinding<T> binding, AfterBeanDiscovery abd, BeanManager beanManager) { - BeanManagerImpl manager; - if (beanManager instanceof BeanManagerProxy) { - manager = ((BeanManagerProxy) beanManager).unwrap(); - } else { - manager = (BeanManagerImpl) beanManager; - } - /* * CDI does not provide sufficient support for ThreadScoped Supplier */ if (binding.getScope() == PerThread.class) { - abd.addBean(new SupplierThreadScopeBean(binding, manager)); + abd.addBean(new SupplierThreadScopeBean(binding, beanManagerImpl(beanManager))); } else { abd.addBean(new SupplierInstanceBean<>(binding)); abd.addBean(new SupplierInstanceBeanBridge<>(binding)); @@ -156,8 +149,23 @@ InjectionTarget<Supplier<T>> jit = getJerseyInjectionTarget(supplierClass, injectionTarget, supplierBean, resolvers); supplierBean.setInjectionTarget(jit); - abd.addBean(supplierBean); - abd.addBean(new SupplierBeanBridge(binding, beanManager)); + /* + * CDI does not provide sufficient support for ThreadScoped Supplier + */ + if (binding.getScope() == PerThread.class) { + abd.addBean(new SupplierThreadScopeClassBean(binding, supplierBean, beanManagerImpl(beanManager))); + } else { + abd.addBean(supplierBean); + abd.addBean(new SupplierBeanBridge(binding, beanManager)); + } + } + + private static BeanManagerImpl beanManagerImpl(BeanManager beanManager) { + if (beanManager instanceof BeanManagerProxy) { + return ((BeanManagerProxy) beanManager).unwrap(); + } else { + return (BeanManagerImpl) beanManager; + } } private static <T> InjectionTarget<T> getJerseyInjectionTarget(Class<T> clazz, InjectionTarget<T> injectionTarget,
diff --git a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/SupplierThreadScopeBean.java b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/SupplierThreadScopeBean.java index a0c0d34..b95ae0a 100644 --- a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/SupplierThreadScopeBean.java +++ b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/SupplierThreadScopeBean.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -17,20 +17,13 @@ package org.glassfish.jersey.inject.cdi.se.bean; import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.WeakHashMap; -import java.util.function.Supplier; import jakarta.enterprise.context.Dependent; import jakarta.enterprise.context.spi.CreationalContext; -import jakarta.enterprise.inject.spi.Bean; -import jakarta.enterprise.inject.spi.PassivationCapable; import org.glassfish.jersey.internal.inject.SupplierInstanceBinding; -import org.jboss.weld.bean.StringBeanIdentifier; import org.jboss.weld.bean.proxy.BeanInstance; -import org.jboss.weld.bean.proxy.ContextBeanInstance; import org.jboss.weld.bean.proxy.ProxyFactory; import org.jboss.weld.manager.BeanManagerImpl; @@ -107,31 +100,4 @@ ProxyFactory<T> factory = new ProxyFactory<>(contextId, getBeanClass(), getTypes(), this); return factory.create(beanInstance); } - - private static class ThreadScopeBeanInstance<T> extends ContextBeanInstance<T> { - - private final WeakHashMap<Thread, Object> instances = new WeakHashMap<>(); - - private final Supplier<T> supplier; - - /** - * Creates a new invocation handler with supplier which provides a current injected value in proper scope. - * - * @param supplier provider of the value. - */ - private ThreadScopeBeanInstance(Supplier<T> supplier, Bean<T> bean, String contextId) { - super(bean, new StringBeanIdentifier(((PassivationCapable) bean).getId()), contextId); - this.supplier = supplier; - } - - @Override - public Object invoke(Object obj, Method method, Object... arguments) throws Throwable { - Object instance = instances.computeIfAbsent(Thread.currentThread(), thread -> supplier.get()); - return super.invoke(instance, method, arguments); - } - - public void dispose() { - this.instances.clear(); - } - } }
diff --git a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/SupplierThreadScopeClassBean.java b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/SupplierThreadScopeClassBean.java new file mode 100644 index 0000000..698bfb0 --- /dev/null +++ b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/SupplierThreadScopeClassBean.java
@@ -0,0 +1,111 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.jersey.inject.cdi.se.bean; + +import java.lang.annotation.Annotation; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; + +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.context.spi.CreationalContext; + +import org.glassfish.jersey.internal.inject.SupplierClassBinding; +import org.glassfish.jersey.internal.inject.SupplierInstanceBinding; +import org.glassfish.jersey.internal.util.collection.LazyValue; +import org.glassfish.jersey.internal.util.collection.Value; +import org.glassfish.jersey.internal.util.collection.Values; +import org.jboss.weld.bean.proxy.BeanInstance; +import org.jboss.weld.bean.proxy.ProxyFactory; +import org.jboss.weld.manager.BeanManagerImpl; + + +/** + * Creates an implementation of {@link jakarta.enterprise.inject.spi.Bean} interface using Jersey's {@link SupplierInstanceBinding}. + * Binding provides the information about the bean also called {@link jakarta.enterprise.inject.spi.BeanAttributes} information. + * The {@code Bean} does not use {@link org.glassfish.jersey.inject.cdi.se.injector.JerseyInjectionTarget} because serves already + * created proxy, therefore the create operation just return provided instance without any other contextual operation + * (produce, inject, destroy). + * <p> + * This bean is special and is used only for service registered as a {@link org.glassfish.jersey.internal.inject.PerThread} and + * works through the proxy which serves the correct instance per the given thread. + * <p> + * Register example: + * <pre> + * AbstractBinder { + * @Override + * protected void configure() { + * bindFactory(MyFactoryInjectionSupplier.class) + * .to(MyBean.class) + * .in(PerThread.class); + * } + * } + * </pre> + * Inject example: + * <pre> + * @Path("/") + * public class MyResource { + * @Inject + * private MyBean myBean; + * } + * </pre> + */ +class SupplierThreadScopeClassBean extends JerseyBean<Object> { + private final LazyValue<ThreadScopeBeanInstance<Object>> beanInstance; + private final SupplierClassBinding binding; + private final LazyValue<Object> proxy; + private final AtomicReference<CreationalContext> creationalContextAtomicReference = new AtomicReference<>(); + + SupplierThreadScopeClassBean(SupplierClassBinding binding, SupplierClassBean supplierClassBean, BeanManagerImpl beanManager) { + super(binding); + this.binding = binding; + this.beanInstance = Values.lazy((Value<ThreadScopeBeanInstance<Object>>) () -> { + Supplier supplierInstance = supplierClassBean.create(creationalContextAtomicReference.get()); + ThreadScopeBeanInstance scopeBeanInstance = + new ThreadScopeBeanInstance(supplierInstance, this, beanManager.getContextId()); + return scopeBeanInstance; + }); + this.proxy = Values.lazy((Value<Object>) () -> createClientProxy(beanInstance.get(), beanManager.getContextId())); + } + + @Override + public Class<? extends Annotation> getScope() { + return Dependent.class; + } + + @Override + public Object create(CreationalContext<Object> ctx) { + creationalContextAtomicReference.set(ctx); + return proxy.get(); + } + + @Override + public void destroy(Object instance, CreationalContext<Object> creationalContext) { + if (beanInstance.isInitialized()) { + this.beanInstance.get().dispose(); + } + } + + @Override + public Class<?> getBeanClass() { + return (Class<?>) this.binding.getContracts().iterator().next(); + } + + private <T> T createClientProxy(BeanInstance beanInstance, String contextId) { + ProxyFactory<T> factory = new ProxyFactory<>(contextId, getBeanClass(), getTypes(), this); + return factory.create(beanInstance); + } +}
diff --git a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/ThreadScopeBeanInstance.java b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/ThreadScopeBeanInstance.java new file mode 100644 index 0000000..a200960 --- /dev/null +++ b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/bean/ThreadScopeBeanInstance.java
@@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.jersey.inject.cdi.se.bean; + +import org.jboss.weld.bean.StringBeanIdentifier; +import org.jboss.weld.bean.proxy.ContextBeanInstance; + +import java.lang.reflect.Method; +import java.util.WeakHashMap; +import java.util.function.Supplier; + +import jakarta.enterprise.inject.spi.Bean; +import jakarta.enterprise.inject.spi.PassivationCapable; + +/** + * {@link org.glassfish.jersey.internal.inject.PerThread} scope bean instance used from + * {@link SupplierThreadScopeBean} and {@link SupplierThreadScopeClassBean}. + * + * @param <T> Typed of the bean supplied by a {@code Supplier}. + */ +class ThreadScopeBeanInstance<T> extends ContextBeanInstance<T> { + + private final WeakHashMap<Thread, Object> instances = new WeakHashMap<>(); + + private final Supplier<T> supplier; + + /** + * Creates a new invocation handler with supplier which provides a current injected value in proper scope. + * + * @param supplier provider of the value. + */ + ThreadScopeBeanInstance(Supplier<T> supplier, Bean<T> bean, String contextId) { + super(bean, new StringBeanIdentifier(((PassivationCapable) bean).getId()), contextId); + this.supplier = supplier; + } + + @Override + public Object invoke(Object obj, Method method, Object... arguments) throws Throwable { + Object instance = instances.computeIfAbsent(Thread.currentThread(), thread -> supplier.get()); + return super.invoke(instance, method, arguments); + } + + public void dispose() { + this.instances.clear(); + } +}
diff --git a/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/CzechGreeting.java b/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/CzechGreeting.java index fd4ae86..3f4f924 100644 --- a/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/CzechGreeting.java +++ b/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/CzechGreeting.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -26,9 +26,11 @@ static final String GREETING = "Ahoj"; + private String greeting = GREETING + "#" + Thread.currentThread().getName(); + @Override public String getGreeting() { - return GREETING + "#" + Thread.currentThread().getName(); + return greeting; } @Override
diff --git a/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/ThreadScopeTest.java b/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/ThreadScopeTest.java index cf377c1..1fe627a 100644 --- a/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/ThreadScopeTest.java +++ b/inject/cdi2-se/src/test/java/org/glassfish/jersey/inject/cdi/se/ThreadScopeTest.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -17,6 +17,7 @@ package org.glassfish.jersey.inject.cdi.se; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicReference; import jakarta.enterprise.context.RequestScoped; import jakarta.inject.Inject; @@ -167,7 +168,7 @@ } @Test - public void testThreadScopedInSingletonScope() { + public void testThreadScopedInSingletonScope() throws InterruptedException { InjectionManager injectionManager = BindingTestHelper.createInjectionManager(); BindingTestHelper.bind(injectionManager, binder -> { binder.bindAsContract(SingletonObject.class) @@ -188,6 +189,52 @@ assertNotNull(greeting2); assertEquals(greeting1, greeting2); + + final AtomicReference<String> greetingAtomicReference = new AtomicReference<>(); + Runnable runnable = () -> + greetingAtomicReference.set(injectionManager.getInstance(SingletonObject.class).getGreeting().getGreeting()); + + Thread newThread = new Thread(runnable); + newThread.start(); + newThread.join(); + + assertEquals(greeting1.getGreeting(), greeting2.getGreeting()); + assertNotEquals(greeting1.getGreeting(), greetingAtomicReference.get()); + } + + @Test + public void testSupplierClassBindingThreadScopedInSingletonScope() throws InterruptedException { + InjectionManager injectionManager = BindingTestHelper.createInjectionManager(); + BindingTestHelper.bind(injectionManager, binder -> { + binder.bindAsContract(SingletonObject.class) + .in(Singleton.class); + + binder.bindFactory(SupplierGreeting.class) + .to(Greeting.class) + .in(PerThread.class); + }); + + SingletonObject instance1 = injectionManager.getInstance(SingletonObject.class); + Greeting greeting1 = instance1.getGreeting(); + assertNotNull(greeting1); + + // Precisely the same object + SingletonObject instance2 = injectionManager.getInstance(SingletonObject.class); + Greeting greeting2 = instance2.getGreeting(); + assertNotNull(greeting2); + + assertEquals(greeting1, greeting2); + + final AtomicReference<String> greetingAtomicReference = new AtomicReference<>(); + Runnable runnable = () -> + greetingAtomicReference.set(injectionManager.getInstance(SingletonObject.class).getGreeting().getGreeting()); + + Thread newThread = new Thread(runnable); + newThread.start(); + newThread.join(); + + assertEquals(greeting1.getGreeting(), greeting2.getGreeting()); + assertNotEquals(greeting1.getGreeting(), greetingAtomicReference.get()); } @RequestScoped
diff --git a/media/json-binding/src/main/java/org/glassfish/jersey/jsonb/JsonBindingFeature.java b/media/json-binding/src/main/java/org/glassfish/jersey/jsonb/JsonBindingFeature.java index b80ac9e..a41afb0 100644 --- a/media/json-binding/src/main/java/org/glassfish/jersey/jsonb/JsonBindingFeature.java +++ b/media/json-binding/src/main/java/org/glassfish/jersey/jsonb/JsonBindingFeature.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -16,16 +16,25 @@ package org.glassfish.jersey.jsonb; +import jakarta.ws.rs.RuntimeType; +import jakarta.ws.rs.core.Application; import jakarta.ws.rs.core.Configuration; import jakarta.ws.rs.core.Feature; import jakarta.ws.rs.core.FeatureContext; +import org.glassfish.jersey.ApplicationSupplier; import org.glassfish.jersey.CommonProperties; import org.glassfish.jersey.internal.InternalProperties; +import org.glassfish.jersey.internal.inject.InjectionManagerSupplier; import org.glassfish.jersey.internal.util.PropertiesHelper; import org.glassfish.jersey.jsonb.internal.JsonBindingAutoDiscoverable; import org.glassfish.jersey.jsonb.internal.JsonBindingProvider; +import java.security.AccessController; +import java.util.HashSet; +import java.util.Set; +import java.util.logging.Logger; + /** * Feature used to register JSON-B providers. * <p> @@ -50,12 +59,85 @@ */ public class JsonBindingFeature implements Feature { + private static final Logger LOGGER = Logger.getLogger(JsonBindingFeature.class.getName()); private static final String JSON_FEATURE = JsonBindingFeature.class.getSimpleName(); @Override public boolean configure(final FeatureContext context) { final Configuration config = context.getConfiguration(); + // ---- Allow to disable for compatibility with Pre JAX-RS 2.1 Jersey. + + /* Either system properties */ + final String bindingDisabledBySystemProperty = AccessController.doPrivileged( + PropertiesHelper.getSystemProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE)); + + final String bindingDisabledBySystemPropertyClient = AccessController.doPrivileged( + PropertiesHelper.getSystemProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT)); + + final String bindingDisabledBySystemPropertyServer = AccessController.doPrivileged( + PropertiesHelper.getSystemProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER)); + + final RuntimeType runtimeType = config.getRuntimeType(); + + boolean bindingDisabledBySystem = PropertiesHelper.isPropertyOrNotSet(bindingDisabledBySystemProperty) + || (runtimeType == RuntimeType.CLIENT + && PropertiesHelper.isPropertyOrNotSet(bindingDisabledBySystemPropertyClient)) + || (runtimeType == RuntimeType.SERVER + && PropertiesHelper.isPropertyOrNotSet(bindingDisabledBySystemPropertyServer)); + + /* Or config property */ + final Boolean bindingDisabled = CommonProperties.getValue(config.getProperties(), runtimeType, + CommonProperties.JSON_BINDING_FEATURE_DISABLE, Boolean.class); + + /* Config property takes precedence */ + if ((bindingDisabledBySystem && !Boolean.FALSE.equals(bindingDisabled)) || Boolean.TRUE.equals(bindingDisabled)) { + return false; + } + + final Set<String> disabledPackageNames = new HashSet<>(); + + /* Only a certain package names */ + final String bindingDisabledPackageBySystemProperty = RuntimeType.SERVER == runtimeType + ? AccessController.doPrivileged(PropertiesHelper.getSystemProperty( + CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION)) + : null; + + final String bindingDisabledPackage = RuntimeType.SERVER == runtimeType + ? CommonProperties.getValue(config.getProperties(), runtimeType, + CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION, String.class) + : null; + + separatePackageNames(disabledPackageNames, bindingDisabledPackageBySystemProperty); + separatePackageNames(disabledPackageNames, bindingDisabledPackage); + + if (!disabledPackageNames.isEmpty() && !Boolean.FALSE.equals(bindingDisabled)) { + try { + Application app = null; + if (InjectionManagerSupplier.class.isInstance(context)) { + app = ((InjectionManagerSupplier) context).getInjectionManager().getInstance(Application.class); + if (app != null) { + while (ApplicationSupplier.class.isInstance(app) && ((ApplicationSupplier) app).getApplication() != app) { + app = ((ApplicationSupplier) app).getApplication(); + } + for (String disabledPackageName : disabledPackageNames) { + if (app.getClass().getName().startsWith(disabledPackageName)) { + return false; + } + } + } + } + if (app == null) { + LOGGER.warning(LocalizationMessages.ERROR_JSONB_DETECTING_APPLICATION( + LocalizationMessages.ERROR_JSONB_APPLICATION_NOT_FOUND())); + } + } catch (Throwable throwable) { + LOGGER.warning(LocalizationMessages.ERROR_JSONB_DETECTING_APPLICATION(throwable.getMessage())); + } + } + + // ---- End of disabling for compatibility with Pre JAX-RS 2.1 Jersey. + final String jsonFeature = CommonProperties.getValue( config.getProperties(), config.getRuntimeType(), @@ -74,4 +156,12 @@ return true; } + + private static void separatePackageNames(Set<String> set, String packages) { + if (packages != null) { + for (String packageName : packages.split(",")) { + set.add(packageName.trim()); + } + } + } }
diff --git a/media/json-binding/src/main/resources/org/glassfish/jersey/jsonb/localization.properties b/media/json-binding/src/main/resources/org/glassfish/jersey/jsonb/localization.properties index 4eee493..371e641 100644 --- a/media/json-binding/src/main/resources/org/glassfish/jersey/jsonb/localization.properties +++ b/media/json-binding/src/main/resources/org/glassfish/jersey/jsonb/localization.properties
@@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2019 Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved. # # This program and the accompanying materials are made available under the # terms of the Eclipse Public License v. 2.0, which is available at @@ -14,6 +14,8 @@ # SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 # +error.jsonb.application.not.found=Application not found. +error.jsonb.detecting.application=JSON-B could not detect the application name: {0}. error.jsonb.serialization=Error writing JSON-B serialized object. error.jsonb.deserialization=Error deserializing object from entity stream. error.jsonb.emptystream=JSON-B cannot parse empty input stream.
diff --git a/media/json-binding/src/test/java/org/glassfish/jersey/jsonb/internal/JsonbDisabledTest.java b/media/json-binding/src/test/java/org/glassfish/jersey/jsonb/internal/JsonbDisabledTest.java new file mode 100644 index 0000000..7dc8a3f --- /dev/null +++ b/media/json-binding/src/test/java/org/glassfish/jersey/jsonb/internal/JsonbDisabledTest.java
@@ -0,0 +1,213 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.jersey.jsonb.internal; + +import org.glassfish.jersey.CommonProperties; +import org.glassfish.jersey.internal.inject.AbstractBinder; +import org.glassfish.jersey.internal.inject.InjectionManager; +import org.glassfish.jersey.internal.inject.InjectionManagerSupplier; +import org.glassfish.jersey.internal.inject.Injections; +import org.glassfish.jersey.jsonb.JsonBindingFeature; +import org.glassfish.jersey.model.internal.CommonConfig; +import org.glassfish.jersey.model.internal.ComponentBag; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import jakarta.ws.rs.RuntimeType; +import jakarta.ws.rs.core.Application; +import jakarta.ws.rs.core.FeatureContext; +import java.lang.reflect.Proxy; +import java.util.concurrent.atomic.AtomicReference; + +public class JsonbDisabledTest { + @Test + public void testDisabled() { + AtomicReference<CommonConfig> configReference = new AtomicReference<>(); + FeatureContext featureContext1 = featureContextForConfig(configReference); + + CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + configReference.set(config1); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + + CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + config2.property(CommonProperties.JSON_BINDING_FEATURE_DISABLE, true); + configReference.set(config2); + Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1)); + } + + @Test + public void testDisabledBySystemProperty() { + AtomicReference<CommonConfig> configReference = new AtomicReference<>(); + FeatureContext featureContext1 = featureContextForConfig(configReference); + + CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + configReference.set(config1); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + + CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER, "true"); + configReference.set(config2); + Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1)); + System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER); + } + + @Test + public void testDisabledBySystemPropertyOverridenByConfigProperty() { + AtomicReference<CommonConfig> configReference = new AtomicReference<>(); + FeatureContext featureContext1 = featureContextForConfig(configReference); + + CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + configReference.set(config1); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + + CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE, "true"); + config2.property(CommonProperties.JSON_BINDING_FEATURE_DISABLE, false); + configReference.set(config2); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE); + } + + @Test + public void testDisabledByPropertyApplicationPackage() { + Application application = new Application() { + }; + InjectionManager injectionManager = Injections.createInjectionManager(); + injectionManager.register(new AbstractBinder() { + @Override + protected void configure() { + bind(application).to(Application.class); + } + }); + AtomicReference<InjectionManager> injectionManagerReference = new AtomicReference<>(injectionManager); + AtomicReference<CommonConfig> configReference = new AtomicReference<>(); + FeatureContext featureContext1 = featureContextForConfig(configReference, injectionManagerReference); + + CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + configReference.set(config1); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + + System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION, + "some.does.not.matter, org.glassfish.jersey.jsonb.internal"); + CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + configReference.set(config2); + Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1)); + System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION); + } + + @Test + public void disableOnClientOnlyTest() { + AtomicReference<CommonConfig> configReference = new AtomicReference<>(); + FeatureContext featureContext1 = featureContextForConfig(configReference); + + CommonConfig config1 = new CommonConfig(RuntimeType.CLIENT, ComponentBag.INCLUDE_ALL); + configReference.set(config1); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + + config1.property(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER, true); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + + config1.property(CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT, true); + Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1)); + + CommonConfig config2 = new CommonConfig(RuntimeType.CLIENT, ComponentBag.INCLUDE_ALL); + System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER, "true"); + configReference.set(config2); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + + System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT, "true"); + Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1)); + + System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_SERVER); + System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_CLIENT); + } + + @Test + public void testDisabledBySystemPropertyApplicationPackage() { + Application application = new Application() { + }; + InjectionManager injectionManager = Injections.createInjectionManager(); + injectionManager.register(new AbstractBinder() { + @Override + protected void configure() { + bind(application).to(Application.class); + } + }); + AtomicReference<InjectionManager> injectionManagerReference = new AtomicReference<>(injectionManager); + AtomicReference<CommonConfig> configReference = new AtomicReference<>(); + FeatureContext featureContext1 = featureContextForConfig(configReference, injectionManagerReference); + + System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION, + "some.does.not.matter, org.glassfish.jersey.jsonb.internal"); + + CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + configReference.set(config1); + Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1)); + + CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + configReference.set(config2); + Assertions.assertFalse(new JsonBindingFeature().configure(featureContext1)); + System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION); + } + + @Test + public void testDisabledBySystemPropertyApplicationPackageEnabledByProperty() { + Application application = new Application() { + }; + InjectionManager injectionManager = Injections.createInjectionManager(); + injectionManager.register(new AbstractBinder() { + @Override + protected void configure() { + bind(application).to(Application.class); + } + }); + AtomicReference<InjectionManager> injectionManagerReference = new AtomicReference<>(injectionManager); + AtomicReference<CommonConfig> configReference = new AtomicReference<>(); + FeatureContext featureContext1 = featureContextForConfig(configReference, injectionManagerReference); + + CommonConfig config1 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + configReference.set(config1); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + + System.setProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION, + "some.does.not.matter, org.glassfish.jersey.jsonb.internal"); + + CommonConfig config2 = new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL); + config2.property(CommonProperties.JSON_BINDING_FEATURE_DISABLE, Boolean.FALSE); + configReference.set(config2); + Assertions.assertTrue(new JsonBindingFeature().configure(featureContext1)); + System.clearProperty(CommonProperties.JSON_BINDING_FEATURE_DISABLE_APPLICATION); + } + + private static FeatureContext featureContextForConfig(AtomicReference<CommonConfig> configReference) { + return featureContextForConfig(configReference, new AtomicReference<>()); + } + private static FeatureContext featureContextForConfig(AtomicReference<CommonConfig> configReference, + AtomicReference<InjectionManager> injectionManager) { + return (FeatureContext) Proxy.newProxyInstance( + JsonbDisabledTest.class.getClassLoader(), + new Class[] {FeatureContext.class, InjectionManagerSupplier.class}, (proxy, method, args) -> { + switch (method.getName()) { + case "getConfiguration": + return configReference.get(); + case "getInjectionManager": + return injectionManager.get(); + } + return null; + }); + } +}
diff --git a/media/json-gson/pom.xml b/media/json-gson/pom.xml index e856c38..2a3b5db 100644 --- a/media/json-gson/pom.xml +++ b/media/json-gson/pom.xml
@@ -71,6 +71,12 @@ <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> + <exclusions> + <exclusion> + <groupId>com.google.errorprone</groupId> + <artifactId>error_prone_annotations</artifactId> + </exclusion> + </exclusions> </dependency> <dependency> <groupId>org.junit.jupiter</groupId>
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java index d7b9f9c..a209c27 100644 --- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java +++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/DefaultJacksonJaxbJsonProvider.java
@@ -59,10 +59,6 @@ //do not register JaxbAnnotationModule because it brakes default annotations processing private static final String[] EXCLUDE_MODULE_NAMES = {"JaxbAnnotationModule", "JakartaXmlBindAnnotationModule"}; - public DefaultJacksonJaxbJsonProvider() { - super(new JacksonMapperConfigurator(null, DEFAULT_ANNOTATIONS)); - } - public DefaultJacksonJaxbJsonProvider(Providers providers, Configuration config, Annotations... annotationsToUse) { super(new JacksonMapperConfigurator(null, annotationsToUse)); this.commonConfig = config; @@ -147,4 +143,4 @@ ); } } -} \ No newline at end of file +}
diff --git a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/PackageVersion.java b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/PackageVersion.java index 5d328da..56b1bf6 100644 --- a/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/PackageVersion.java +++ b/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/jackson/jaxrs/json/PackageVersion.java
@@ -11,7 +11,7 @@ */ public final class PackageVersion implements Versioned { public final static Version VERSION = VersionUtil.parseVersion( - "2.17.1", "com.fasterxml.jackson.jaxrs", "jackson-jaxrs-json-provider"); + "2.17.2", "com.fasterxml.jackson.jaxrs", "jackson-jaxrs-json-provider"); @Override public Version version() {
diff --git a/media/json-jackson/src/main/resources/META-INF/NOTICE.markdown b/media/json-jackson/src/main/resources/META-INF/NOTICE.markdown index 4edecfc..9440229 100644 --- a/media/json-jackson/src/main/resources/META-INF/NOTICE.markdown +++ b/media/json-jackson/src/main/resources/META-INF/NOTICE.markdown
@@ -31,7 +31,7 @@ ## Third-party Content -Jackson JAX-RS Providers version 2.17.1 +Jackson JAX-RS Providers version 2.17.2 * License: Apache License, 2.0 * Project: https://github.com/FasterXML/jackson-jaxrs-providers * Copyright: (c) 2009-2023 FasterXML, LLC. All rights reserved unless otherwise indicated.
diff --git a/pom.xml b/pom.xml index cdb2009..eb00a8c 100644 --- a/pom.xml +++ b/pom.xml
@@ -153,14 +153,14 @@ <url>http://www.eclipse.org/legal/epl-2.0</url> <distribution>repo</distribution> <comments>Except for 3rd content and examples. - See also https://github.com/eclipse-ee4j/jersey/blob/master/NOTICE.md</comments> + See also https://github.com/eclipse-ee4j/jersey/blob/master/NOTICE.md</comments> </license> <license> <name>GPL2 w/ CPE</name> <url>https://www.gnu.org/software/classpath/license.html</url> <distribution>repo</distribution> <comments>Except for 3rd content and examples. - See also https://github.com/eclipse-ee4j/jersey/blob/master/NOTICE.md</comments> + See also https://github.com/eclipse-ee4j/jersey/blob/master/NOTICE.md</comments> </license> <license> <name>EDL 1.0</name> @@ -179,9 +179,9 @@ <url>http://www.apache.org/licenses/LICENSE-2.0.html</url> <distribution>repo</distribution> <comments>Google Guava @ org.glassfish.jersey.internal.guava, - Dropwizard Monitoring inspired classes @ org.glassfish.jersey.server.internal.monitoring.core, - Hibernate Validation classes @ org.glassfish.jersey.server.validation.internal.hibernate, and - Jackson JAX-RS Providers @ org.glassfish.jersey.jackson.internal.jackson.jaxrs</comments> + Dropwizard Monitoring inspired classes @ org.glassfish.jersey.server.internal.monitoring.core, + Hibernate Validation classes @ org.glassfish.jersey.server.validation.internal.hibernate, and + Jackson JAX-RS Providers @ org.glassfish.jersey.jackson.internal.jackson.jaxrs</comments> </license> <license> <name>Public Domain</name> @@ -206,7 +206,7 @@ <url>http://www.opensource.org/licenses/mit-license.php</url> <distribution>repo</distribution> <comments>AngularJS, Bootstrap v3.3.7, - jQuery Barcode plugin 0.3, KineticJS v4.7.1</comments> + jQuery Barcode plugin 0.3, KineticJS v4.7.1</comments> </license> <license> <name>W3C license</name> @@ -902,7 +902,7 @@ </property> </activation> <properties> -<!-- <release.tests.args>-Dskip.tests=true</release.tests.args>--> + <!-- <release.tests.args>-Dskip.tests=true</release.tests.args>--> <skip.tests>true</skip.tests> </properties> </profile> @@ -929,7 +929,7 @@ <activation> <activeByDefault>false</activeByDefault> <property> - <name>!tests.excluded</name> + <name>!tests.excluded</name> </property> </activation> <modules> @@ -1025,10 +1025,10 @@ <artifactId>maven-enforcer-plugin</artifactId> <executions> <execution> - <id>enforce-property</id> - <goals> - <goal>enforce</goal> - </goals> + <id>enforce-property</id> + <goals> + <goal>enforce</goal> + </goals> <configuration> <rules> <requireProperty> @@ -1650,7 +1650,7 @@ <groupId>org.simpleframework</groupId> <artifactId>simple-http</artifactId> <version>${simple.version}</version> - </dependency> + </dependency> <dependency> <groupId>org.simpleframework</groupId> @@ -2023,9 +2023,9 @@ </dependency> <dependency> - <groupId>com.google.code.gson</groupId> - <artifactId>gson</artifactId> - <version>${gson.version}</version> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>${gson.version}</version> </dependency> <dependency> @@ -2059,8 +2059,8 @@ <!-- <netbeans.hint.license>gf-cddl-gpl</netbeans.hint.license>--> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> -<!-- <release.tests.args>-Dmaven.test.skip=false</release.tests.args>--> -<!-- <release.preparationGoals>clean install</release.preparationGoals>--> + <!-- <release.tests.args>-Dmaven.test.skip=false</release.tests.args>--> + <!-- <release.preparationGoals>clean install</release.preparationGoals>--> <skip.tests>false</skip.tests> <xdk.absolute.path /> <surefire.security.argline /> @@ -2073,13 +2073,13 @@ <antrun.mvn.plugin.version>3.1.0</antrun.mvn.plugin.version> <mvn.ant.version>1.10.14</mvn.ant.version> <assembly.mvn.plugin.version>3.7.1</assembly.mvn.plugin.version> - <clean.mvn.plugin.version>3.3.2</clean.mvn.plugin.version> - <enforcer.mvn.plugin.version>3.4.1</enforcer.mvn.plugin.version> - <exec.mvn.plugin.version>3.2.0</exec.mvn.plugin.version> - <buildhelper.mvn.plugin.version>3.5.0</buildhelper.mvn.plugin.version> + <clean.mvn.plugin.version>3.4.0</clean.mvn.plugin.version> + <enforcer.mvn.plugin.version>3.5.0</enforcer.mvn.plugin.version> + <exec.mvn.plugin.version>3.4.1</exec.mvn.plugin.version> + <buildhelper.mvn.plugin.version>3.6.0</buildhelper.mvn.plugin.version> <buildnumber.mvn.plugin.version>3.2.0</buildnumber.mvn.plugin.version> - <checkstyle.mvn.plugin.version>3.3.1</checkstyle.mvn.plugin.version> - <checkstyle.version>10.16.0</checkstyle.version> + <checkstyle.mvn.plugin.version>3.4.0</checkstyle.mvn.plugin.version> + <checkstyle.version>10.17.0</checkstyle.version> <compiler.mvn.plugin.version>3.13.0</compiler.mvn.plugin.version> <!-- Special version of the compiler plugin just for the jersey-common. All versions above @@ -2088,25 +2088,25 @@ but the jersey-common module which has to have the separate version for OSGi reasons. --> <compiler.common.mvn.plugin.version>3.9.0</compiler.common.mvn.plugin.version> - <cyclonedx.mvn.plugin.version>2.8.0</cyclonedx.mvn.plugin.version> - <dependency.mvn.plugin.version>3.6.1</dependency.mvn.plugin.version> + <cyclonedx.mvn.plugin.version>2.8.1</cyclonedx.mvn.plugin.version> + <dependency.mvn.plugin.version>3.7.1</dependency.mvn.plugin.version> <deploy.mvn.plugin.version>3.1.2</deploy.mvn.plugin.version> <ear.mvn.plugin.version>3.3.0</ear.mvn.plugin.version> - <failsafe.mvn.plugin.version>3.2.5</failsafe.mvn.plugin.version> + <failsafe.mvn.plugin.version>3.3.1</failsafe.mvn.plugin.version> <felix.mvn.plugin.version>5.1.9</felix.mvn.plugin.version> <findbugs.mvn.plugin.version>3.0.5</findbugs.mvn.plugin.version> <gfembedded.mvn.plugin.version>5.1</gfembedded.mvn.plugin.version> <install.mvn.plugin.version>3.1.2</install.mvn.plugin.version> <istack.mvn.plugin.version>4.2.0</istack.mvn.plugin.version> - <jar.mvn.plugin.version>3.4.1</jar.mvn.plugin.version> - <javadoc.mvn.plugin.version>3.6.3</javadoc.mvn.plugin.version> - <jxr.mvn.plugin.version>3.3.2</jxr.mvn.plugin.version> + <jar.mvn.plugin.version>3.4.2</jar.mvn.plugin.version> + <javadoc.mvn.plugin.version>3.8.0</javadoc.mvn.plugin.version> + <jxr.mvn.plugin.version>3.4.0</jxr.mvn.plugin.version> <paxexam.mvn.plugin.version>1.2.4</paxexam.mvn.plugin.version> - <project.info.reports.mvn.plugin.version>3.5.0</project.info.reports.mvn.plugin.version> + <project.info.reports.mvn.plugin.version>3.6.2</project.info.reports.mvn.plugin.version> <resources.mvn.plugin.version>3.3.1</resources.mvn.plugin.version> - <shade.mvn.plugin.version>3.5.3</shade.mvn.plugin.version> + <shade.mvn.plugin.version>3.6.0</shade.mvn.plugin.version> <source.mvn.plugin.version>3.3.1</source.mvn.plugin.version> - <surefire.mvn.plugin.version>3.2.5</surefire.mvn.plugin.version> + <surefire.mvn.plugin.version>3.3.1</surefire.mvn.plugin.version> <war.mvn.plugin.version>3.4.0</war.mvn.plugin.version> <wiremock.mvn.plugin.version>2.11.0</wiremock.mvn.plugin.version> <xml.mvn.plugin.version>1.1.0</xml.mvn.plugin.version> @@ -2121,25 +2121,25 @@ <!-- see core-server/src/main/java/jersey/repackaged/asm/.. --> <asm.version>9.7</asm.version> <!--required for spring (ext) modules integration --> - <aspectj.weaver.version>1.9.22</aspectj.weaver.version> -<!-- <bnd.plugin.version>2.3.6</bnd.plugin.version>--> + <aspectj.weaver.version>1.9.22.1</aspectj.weaver.version> + <!-- <bnd.plugin.version>2.3.6</bnd.plugin.version>--> <bouncycastle.version>1.70</bouncycastle.version> <commons.io.version>2.16.1</commons.io.version> <commons.codec.version>1.16.1</commons.codec.version> -<!-- <commons-lang3.version>3.3.2</commons-lang3.version>--> - <commons.logging.version>1.3.1</commons.logging.version> + <!-- <commons-lang3.version>3.3.2</commons-lang3.version>--> + <commons.logging.version>1.3.3</commons.logging.version> <fasterxml.classmate.version>1.7.0</fasterxml.classmate.version> <felix.eventadmin.version>1.6.4</felix.eventadmin.version> <felix.framework.security.version>2.8.4</felix.framework.security.version> <felix.framework.version>7.0.5</felix.framework.version> <findbugs.glassfish.version>1.7</findbugs.glassfish.version> - <freemarker.version>2.3.32</freemarker.version> - <gae.version>2.0.26</gae.version> - <groovy.version>4.0.21</groovy.version> - <gson.version>2.10.1</gson.version> + <freemarker.version>2.3.33</freemarker.version> + <gae.version>2.0.29</gae.version> + <groovy.version>4.0.23</groovy.version> + <gson.version>2.11.0</gson.version> <!--versions, extracted here due to maven-enforcer-plugin --> -<!-- <commons.codec.version>1.15</commons.codec.version>--> + <!-- <commons.codec.version>1.15</commons.codec.version>--> <com.uber.jaeger.version>0.27.0</com.uber.jaeger.version> <org.codehaus.gmavenplus.version>3.0.2</org.codehaus.gmavenplus.version> <!-- end of versions extracted here due to maven-enforcer-plugin --> @@ -2156,12 +2156,12 @@ <helidon.config.11.version>1.4.14</helidon.config.11.version> <!-- JDK 11- support --> <smallrye.config.version>3.7.1</smallrye.config.version> - <guava.version>33.1.0-jre</guava.version> - <hamcrest.version>2.2</hamcrest.version> + <guava.version>33.3.0-jre</guava.version> + <hamcrest.version>3.0</hamcrest.version> <xmlunit.version>2.10.0</xmlunit.version> <httpclient.version>4.5.14</httpclient.version> <httpclient5.version>5.3.1</httpclient5.version> - <jackson.version>2.17.1</jackson.version> + <jackson.version>2.17.2</jackson.version> <javassist.version>3.30.2-GA</javassist.version> <jettison.version>1.3.7</jettison.version> <!-- TODO: 1.3.8 doesn't work; AbstractJsonTest complexBeanWithAttributes --> <jboss.vfs.version>3.3.2.Final</jboss.vfs.version> @@ -2169,13 +2169,13 @@ <jmh.version>1.37</jmh.version> <jmockit.version>1.49</jmockit.version> <junit4.version>4.13.2</junit4.version> - <junit5.version>5.10.2</junit5.version> - <junit-platform-suite.version>1.10.2</junit-platform-suite.version> + <junit5.version>5.11.0</junit5.version> + <junit-platform-suite.version>1.11.0</junit-platform-suite.version> <junit-platform-suite.legacy.version>1.10.0</junit-platform-suite.legacy.version> <kryo.version>4.0.3</kryo.version> <mockito.version>4.11.0</mockito.version> <!-- CQ 17673 --> - <mustache.version>0.9.12</mustache.version> - <netty.version>4.1.109.Final</netty.version> + <mustache.version>0.9.14</mustache.version> + <netty.version>4.1.112.Final</netty.version> <opentracing.version>0.33.0</opentracing.version> <osgi.version>6.0.0</osgi.version> <osgi.framework.version>1.10.0</osgi.framework.version> @@ -2193,8 +2193,8 @@ <simple.version>6.0.1</simple.version> <slf4j.version>2.0.13</slf4j.version> <spring6.version>6.0.18</spring6.version> - <testng.version>7.9.0</testng.version> - <testng6.version>6.9.13.6</testng6.version> + <testng.version>7.10.2</testng.version> + <testng6.version>6.14.3</testng6.version> <thymeleaf.version>3.1.2.RELEASE</thymeleaf.version> <!-- Jakartified, eligible for CQ --> <weld.version>5.1.1.Final</weld.version> @@ -2205,7 +2205,7 @@ <xerces.version>2.12.2</xerces.version> <!-- Graal VM --> - <graalvm.version>20.3.14</graalvm.version> + <graalvm.version>20.3.15</graalvm.version> <!-- do not need CQs (below this line till the end of version properties)--> <gf.impl.version>7.0.6</gf.impl.version> @@ -2240,15 +2240,15 @@ <jaxrs.api.spec.version>3.1</jaxrs.api.spec.version> <jaxrs.api.impl.version>3.1.0</jaxrs.api.impl.version> <jetty.osgi.version>org.eclipse.jetty.*;version="[11,15)"</jetty.osgi.version> - <jetty.version>12.0.7</jetty.version> - <jetty9.version>9.4.54.v20240208</jetty9.version> - <jetty11.version>11.0.20</jetty11.version> + <jetty.version>12.0.14</jetty.version> + <jetty9.version>9.4.55.v20240627</jetty9.version> + <jetty11.version>11.0.24</jetty11.version> <jetty.plugin.version>12.0.8</jetty.plugin.version> <jsonb.api.version>3.0.1</jsonb.api.version> <jsonp.ri.version>1.1.5</jsonp.ri.version> <jsonp.jaxrs.version>1.1.5</jsonp.jaxrs.version> - <moxy.version>4.0.2</moxy.version> - <yasson.version>3.0.3</yasson.version> + <moxy.version>4.0.4</moxy.version> + <yasson.version>3.0.4</yasson.version> <!-- END of Jakartified --> <javax.annotation.version>1.3.2</javax.annotation.version> <!--Deprecated, used only for @generated annotation in perf tests -->
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/OutboundMessageContextTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/OutboundMessageContextTest.java index bd6e3c5..817170c 100644 --- a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/OutboundMessageContextTest.java +++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/message/internal/OutboundMessageContextTest.java
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -16,6 +16,9 @@ package org.glassfish.jersey.tests.e2e.common.message.internal; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.text.ParseException; @@ -33,10 +36,13 @@ import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.ext.RuntimeDelegate; +import org.glassfish.jersey.io.spi.FlushedCloseable; import org.glassfish.jersey.message.internal.CookieProvider; import org.glassfish.jersey.message.internal.OutboundMessageContext; import org.glassfish.jersey.tests.e2e.common.TestRuntimeDelegate; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import static org.hamcrest.Matchers.contains; @@ -271,4 +277,38 @@ newCtx.setMediaType(MediaType.APPLICATION_XML_TYPE); // new value Assertions.assertEquals(MediaType.APPLICATION_XML_TYPE, newCtx.getMediaType()); } + + @Test + public void OutboundMessageContextFlushTest() throws IOException { + FlushCountOutputStream os = new FlushCountOutputStream(); + OutboundMessageContext ctx = new OutboundMessageContext((Configuration) null); + ctx.setEntity("Anything"); + ctx.setEntityStream(os); + os.flush(); + ctx.close(); + MatcherAssert.assertThat(os.flushedCnt, Matchers.is(2)); + + os = new FlushedClosableOutputStream(); + ctx = new OutboundMessageContext((Configuration) null); + ctx.setEntity("Anything2"); + ctx.setEntityStream(os); + os.flush(); + ctx.close(); + MatcherAssert.assertThat(os.flushedCnt, Matchers.is(1)); + } + + private static class FlushCountOutputStream extends ByteArrayOutputStream { + private int flushedCnt = 0; + + @Override + public void flush() throws IOException { + flushedCnt++; + super.flush(); + } + } + + private static class FlushedClosableOutputStream extends FlushCountOutputStream implements FlushedCloseable { + + } } +
diff --git a/tests/integration/cdi-integration/cdi-skipping-analyzer/pom.xml b/tests/integration/cdi-integration/cdi-skipping-analyzer/pom.xml new file mode 100644 index 0000000..15c7518 --- /dev/null +++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/pom.xml
@@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> + +<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"> + <parent> + <artifactId>cdi-integration-project</artifactId> + <groupId>org.glassfish.jersey.tests.integration.cdi</groupId> + <version>3.1.99-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>cdi-skipping-analyzer</artifactId> + + <dependencies> + <dependency> + <groupId>jakarta.ws.rs</groupId> + <artifactId>jakarta.ws.rs-api</artifactId> + </dependency> + <dependency> + <groupId>jakarta.annotation</groupId> + <artifactId>jakarta.annotation-api</artifactId> + </dependency> + <dependency> + <groupId>jakarta.enterprise</groupId> + <artifactId>jakarta.enterprise.cdi-api</artifactId> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.ext.cdi</groupId> + <artifactId>jersey-cdi1x</artifactId> + </dependency> + <dependency> + <groupId>org.jboss.weld.se</groupId> + <artifactId>weld-se-core</artifactId> + <scope>test</scope> + </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> + <dependency> + <groupId>org.glassfish.jersey.incubator</groupId> + <artifactId>jersey-injectless-client</artifactId> + <version>${jersey.version}</version> + </dependency> + </dependencies> +</project>
diff --git a/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiService.java b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiService.java new file mode 100644 index 0000000..44d56d2 --- /dev/null +++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiService.java
@@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.jersey.tests.cdi.skippinganalyzer; + +public interface CdiService<T> { + void doService(T t); +}
diff --git a/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiServiceExtension.java b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiServiceExtension.java new file mode 100644 index 0000000..a7e5130 --- /dev/null +++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiServiceExtension.java
@@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.jersey.tests.cdi.skippinganalyzer; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.event.Observes; +import jakarta.enterprise.inject.spi.AfterBeanDiscovery; +import jakarta.enterprise.inject.spi.Extension; +import java.io.IOException; + +public class CdiServiceExtension implements Extension { + public void observe(@Observes AfterBeanDiscovery event) throws IOException, ClassNotFoundException { + event.addBean() + .addType(CdiService.class) + .beanClass(CdiService.class) + .scope(ApplicationScoped.class) + .createWith(context -> new CdiServiceImpl()); + } + +}
diff --git a/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiServiceImpl.java b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiServiceImpl.java new file mode 100644 index 0000000..6406346 --- /dev/null +++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/CdiServiceImpl.java
@@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.jersey.tests.cdi.skippinganalyzer; + +import jakarta.enterprise.inject.spi.BeanManager; +import jakarta.inject.Inject; + +public class CdiServiceImpl implements CdiService<StringBuilder> { + + @Inject + BeanManager beanManager; + + @Override + public void doService(StringBuilder sb) { + sb.append(getClass().getSimpleName()); + } +}
diff --git a/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/WeldDiscoveredBean.java b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/WeldDiscoveredBean.java new file mode 100644 index 0000000..ce459d6 --- /dev/null +++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/WeldDiscoveredBean.java
@@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.jersey.tests.cdi.skippinganalyzer; + +import jakarta.enterprise.context.ApplicationScoped; + +@ApplicationScoped +public class WeldDiscoveredBean { + +}
diff --git a/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/resources/META-INF/beans.xml b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/resources/META-INF/beans.xml new file mode 100644 index 0000000..56ad04f --- /dev/null +++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> + + +<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd" + bean-discovery-mode="annotated" version="2.0"> +</beans> \ No newline at end of file
diff --git a/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension new file mode 100644 index 0000000..7bfc71c --- /dev/null +++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
@@ -0,0 +1 @@ +org.glassfish.jersey.tests.cdi.skippinganalyzer.CdiServiceExtension \ No newline at end of file
diff --git a/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/webapp/WEB-INF/web.xml b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..e038a3a --- /dev/null +++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + + This program and the accompanying materials are made available under the + terms of the Eclipse Public License v. 2.0, which is available at + http://www.eclipse.org/legal/epl-2.0. + + This Source Code may also be made available under the following Secondary + Licenses when the conditions for such availability set forth in the + Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + version 2 with the GNU Classpath Exception, which is available at + https://www.gnu.org/software/classpath/license.html. + + SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + +--> + +<web-app xmlns="http://java.sun.com/xml/ns/javaee" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" + version="3.0"> +</web-app>
diff --git a/tests/integration/cdi-integration/cdi-skipping-analyzer/src/test/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/SkippingAnalyzerTest.java b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/test/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/SkippingAnalyzerTest.java new file mode 100644 index 0000000..698e496 --- /dev/null +++ b/tests/integration/cdi-integration/cdi-skipping-analyzer/src/test/java/org/glassfish/jersey/tests/cdi/skippinganalyzer/SkippingAnalyzerTest.java
@@ -0,0 +1,79 @@ +/* + * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0, which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package org.glassfish.jersey.tests.cdi.skippinganalyzer; + +import org.glassfish.hk2.api.ClassAnalyzer; +import org.glassfish.jersey.ext.cdi1x.internal.CdiComponentProvider; +import org.glassfish.jersey.ext.cdi1x.internal.InjecteeSkippingAnalyzer; +import org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory; +import org.glassfish.jersey.internal.inject.InjectionManager; +import org.glassfish.jersey.internal.inject.Injections; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.jboss.weld.environment.se.Weld; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import jakarta.enterprise.inject.spi.BeanManager; +import jakarta.enterprise.inject.spi.CDI; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Map; +import java.util.Set; + +public class SkippingAnalyzerTest { + private Weld weld; + + @BeforeEach + public void setup() { + Assumptions.assumeTrue(Hk2InjectionManagerFactory.isImmediateStrategy()); + } + + @BeforeEach + public void setUp() throws Exception { + if (Hk2InjectionManagerFactory.isImmediateStrategy()) { + weld = new Weld(); + weld.initialize(); + } + } + + @AfterEach + public void tearDown() throws Exception { + weld.shutdown(); + } + + @Test + public void testInjecteeSkippingAnalyzerWithZeroFieldsToSkip() throws Exception { + BeanManager beanManager = CDI.current().getBeanManager(); + CdiComponentProvider provider = beanManager.getExtension(CdiComponentProvider.class); + Method method = provider.getClass().getDeclaredMethod("getFieldsToSkip"); + method.setAccessible(true); + Map fieldMap = (Map) method.invoke(provider); + MatcherAssert.assertThat(0, Matchers.is(fieldMap.size())); + + InjectionManager injectionManager = Injections.createInjectionManager(); + provider.initialize(injectionManager); + injectionManager.completeRegistration(); + ClassAnalyzer analyzer = injectionManager.getInstance(ClassAnalyzer.class, CdiComponentProvider.CDI_CLASS_ANALYZER); + MatcherAssert.assertThat(InjecteeSkippingAnalyzer.class, Matchers.is(analyzer.getClass())); + + Set<Field> fieldSet = analyzer.getFields(CdiServiceImpl.class); + MatcherAssert.assertThat(0, Matchers.is(fieldSet.size())); + } +}
diff --git a/tests/integration/cdi-integration/pom.xml b/tests/integration/cdi-integration/pom.xml index a0b11ae..6bf68e5 100644 --- a/tests/integration/cdi-integration/pom.xml +++ b/tests/integration/cdi-integration/pom.xml
@@ -43,6 +43,7 @@ <module>cdi-multipart-webapp</module> <module>cdi-resource-with-at-context</module> <module>cdi-singleton</module> + <module>cdi-skipping-analyzer</module> <module>cdi-test-webapp</module> <module>cdi-with-jersey-injection-custom-cfg-webapp</module> <module>cdi-with-jersey-injection-custom-hk2-banned-webapp</module>