Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
* Copyright (c) 2026 Contributors to the Eclipse Foundation
* Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018 Payara Foundation and/or its affiliates.
*
Expand Down Expand Up @@ -425,12 +426,21 @@ private ClientRuntime initRuntime() {

injectionManager.completeRegistration();

bootstrapConfigurators.forEach(configurator -> configurator.postInit(injectionManager, preInit.bootstrapBag));
bootstrapConfigurators.forEach(configurator -> {
if (!configurator.equals(preInit.clientComponentConfigurator)) {
configurator.postInit(injectionManager, preInit.bootstrapBag);
}
});


final ClientConfig configuration = new ClientConfig(runtimeCfgState);
final Connector connector = connectorProvider.getConnector(client, configuration);
final ClientRuntime crt = new ClientRuntime(configuration, connector, injectionManager, preInit.bootstrapBag);

// We call postInit here to clean up thread locals,
// while other configurators need to be postInit earlier because they set up dependencies for ClientRuntime
preInit.clientComponentConfigurator.postInit(injectionManager, preInit.bootstrapBag);

client.registerShutdownHook(crt);
preInit.messageBodyWorkersConfigurator.setClientRuntime(crt);

Expand Down Expand Up @@ -479,6 +489,7 @@ public int hashCode() {
private final ClientBootstrapBag bootstrapBag;
private final List<BootstrapConfigurator> bootstrapConfigurators;
private final ClientMessageBodyFactory.MessageBodyWorkersConfigurator messageBodyWorkersConfigurator;
private final ClientComponentConfigurator clientComponentConfigurator;

/* package */ PreInitialization(InjectionManager injectionManager) {
this(new State(new JerseyClient()), injectionManager, null, null);
Expand All @@ -496,9 +507,9 @@ public int hashCode() {
bootstrapBag.setManagedObjectsFinalizer(new ManagedObjectsFinalizer(injectionManager));

messageBodyWorkersConfigurator = new ClientMessageBodyFactory.MessageBodyWorkersConfigurator(); // 2020
clientComponentConfigurator = new ClientComponentConfigurator();

bootstrapConfigurators = Arrays.asList(
new RequestScope.RequestScopeConfigurator(),
bootstrapConfigurators = Arrays.asList(new RequestScope.RequestScopeConfigurator(),
new ParamConverterConfigurator(), // 2010
new ParameterUpdaterConfigurator(), // 2011
new RuntimeConfigConfigurator(runtimeCfgState), // 2012
Expand All @@ -507,7 +518,7 @@ public int hashCode() {
new ExceptionMapperFactory.ExceptionMappersConfigurator(), // 2015
new JaxrsProviders.ProvidersConfigurator(), // 2016
new AutoDiscoverableConfigurator(RuntimeType.CLIENT),
new ClientComponentConfigurator(),
clientComponentConfigurator,
new FeatureConfigurator(RuntimeType.CLIENT));
bootstrapConfigurators.forEach(configurator -> configurator.init(injectionManager, bootstrapBag));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*
* Copyright (c) 2026 Contributors to the Eclipse Foundation
* Copyright (c) 2013, 2025 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2022 Payara Foundation and/or its affiliates. All rights reserved.
*
Expand Down Expand Up @@ -145,6 +146,10 @@ public Boolean apply(final Class<?> clazz) {

private boolean initialized = false;

// Shared by multiple clients, which can be initialized in parallel,
// therefore storing to a thread local and removing after initialization done in the done() method
private ThreadLocal<InjectionManager> effectiveInjectionManager = new ThreadLocal<>();

public CdiComponentProvider() {
customHk2TypesProvider = CdiUtil.lookupService(Hk2CustomBoundTypesProvider.class);
injectionManagerStore = CdiUtil.createHk2InjectionManagerStore();
Expand Down Expand Up @@ -259,6 +264,14 @@ private boolean bind(final Class<?> clazz, final Set<Class<?>> providerContracts

@Override
public void done() {

if (beanManager != null) {
final CdiComponentProvider extension = beanManager.getExtension(CdiComponentProvider.class);
if (extension != null) {
extension.effectiveInjectionManager.remove();
}
}

if (requestScopedComponents.size() > 0) {
InstanceBinding<ForeignRequestScopeBridge> descriptor = Bindings
.service((ForeignRequestScopeBridge) () -> requestScopedComponents)
Expand Down Expand Up @@ -658,7 +671,6 @@ private StringBuilder listElements(final StringBuilder logMsgBuilder, final Coll
/* package */ abstract class InjectionManagerInjectedCdiTarget implements InjectionManagerInjectedTarget {

private final InjectionTarget delegate;
private volatile InjectionManager effectiveInjectionManager;

public InjectionManagerInjectedCdiTarget(InjectionTarget delegate) {
this.delegate = delegate;
Expand All @@ -671,7 +683,7 @@ public InjectionManagerInjectedCdiTarget(InjectionTarget delegate) {
public void inject(final Object t, final CreationalContext cc) {
InjectionManager injectingManager = getEffectiveInjectionManager();
if (injectingManager == null || /* reload */ injectingManager.isShutdown()) {
injectingManager = effectiveInjectionManager;
injectingManager = effectiveInjectionManager.get();
threadInjectionManagers.set(injectingManager);
}

Expand Down Expand Up @@ -706,7 +718,16 @@ public void dispose(final Object t) {

@Override
public void setInjectionManager(final InjectionManager injectionManager) {
this.effectiveInjectionManager = injectionManager;
// The injectionManager is always the same within a single invocation.
// We set it only once, which is a bit faster than calling set with the same value
final InjectionManager manager = effectiveInjectionManager.get();
if (manager == null) {
effectiveInjectionManager.set(injectionManager);
} else if (!manager.equals(injectionManager)) {
LOGGER.log(Level.SEVERE, "Leaking injection manager found in the current thread."
+ " Very likely because it wasn't removed in a previous invocation and"
+ " leaked into this invocation.");
}
}
}

Expand Down
Loading