Next iteration towards supporting HK2 & Weld injection

Signed-off-by: jansupol <jan.supol@oracle.com>
diff --git a/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyBootstrapPreinitialization.java b/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyBootstrapPreinitialization.java
new file mode 100644
index 0000000..e521c8b
--- /dev/null
+++ b/containers/grizzly2-http/src/main/java/org/glassfish/jersey/grizzly2/httpserver/GrizzlyBootstrapPreinitialization.java
@@ -0,0 +1,29 @@
+/*
+ * 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.grizzly2.httpserver;
+
+import org.glassfish.jersey.innate.BootstrapPreinitialization;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+
+import jakarta.ws.rs.RuntimeType;
+
+public final class GrizzlyBootstrapPreinitialization implements BootstrapPreinitialization {
+    @Override
+    public void preregister(RuntimeType runtimeType, InjectionManager injectionManager) {
+        injectionManager.register(new GrizzlyHttpContainer.GrizzlyBinder());
+    }
+}
diff --git a/containers/grizzly2-http/src/main/resources/META-INF/services/org.glassfish.jersey.innate.BootstrapPreinitialization b/containers/grizzly2-http/src/main/resources/META-INF/services/org.glassfish.jersey.innate.BootstrapPreinitialization
new file mode 100644
index 0000000..a5be574
--- /dev/null
+++ b/containers/grizzly2-http/src/main/resources/META-INF/services/org.glassfish.jersey.innate.BootstrapPreinitialization
@@ -0,0 +1 @@
+org.glassfish.jersey.grizzly2.httpserver.GrizzlyBootstrapPreinitialization
\ No newline at end of file
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientBinder.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientBinder.java
index a48e353..92a4e8c 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/ClientBinder.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientBinder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -82,24 +82,26 @@
     @Override
     protected void configure() {
         install(new MessagingBinders.MessageBodyProviders(clientRuntimeProperties, RuntimeType.CLIENT),
-                new MessagingBinders.HeaderDelegateProviders());
+                new MessagingBinders.HeaderDelegateProviders(RuntimeType.CLIENT));
 
         bindFactory(ReferencingFactory.referenceFactory()).to(new GenericType<Ref<ClientConfig>>() {
-        }).in(RequestScoped.class);
+        }).in(RequestScoped.class).id(2101);
 
         bindFactory(RequestContextInjectionFactory.class)
                 .to(ClientRequest.class)
-                .in(RequestScoped.class);
+                .in(RequestScoped.class)
+                .id(2102);
 
         bindFactory(RequestContextInjectionFactory.class).to(HttpHeaders.class)
-                .proxy(true).proxyForSameScope(false).in(RequestScoped.class);
+                .proxy(true).proxyForSameScope(false).in(RequestScoped.class).id(2103);
 
         bindFactory(ReferencingFactory.referenceFactory()).to(new GenericType<Ref<ClientRequest>>() {
-        }).in(RequestScoped.class);
+        }).in(RequestScoped.class).id(2104);
 
-        bindFactory(PropertiesDelegateFactory.class, Singleton.class).to(PropertiesDelegate.class).in(RequestScoped.class);
+        bindFactory(PropertiesDelegateFactory.class, Singleton.class).to(PropertiesDelegate.class).in(RequestScoped.class)
+                .forClient(true).id(1001);
 
         // ChunkedInput entity support
-        bind(ChunkedInputReader.class).to(MessageBodyReader.class).in(Singleton.class);
+        bind(ChunkedInputReader.class).to(MessageBodyReader.class).in(Singleton.class).id(2105);
     }
 }
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientBootstrapPreinitialization.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientBootstrapPreinitialization.java
new file mode 100644
index 0000000..c73cf7f
--- /dev/null
+++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientBootstrapPreinitialization.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.client;
+
+import org.glassfish.jersey.innate.BootstrapPreinitialization;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+
+import jakarta.ws.rs.RuntimeType;
+
+public class ClientBootstrapPreinitialization implements BootstrapPreinitialization {
+    @Override
+    public void preregister(RuntimeType runtimeType, InjectionManager injectionManager) {
+        if (runtimeType == RuntimeType.CLIENT) {
+            new ClientConfig.PreInitialization(injectionManager);
+        }
+    }
+}
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientConfig.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientConfig.java
index b072c1d..6931a2d 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/ClientConfig.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientConfig.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.
  * Copyright (c) 2018 Payara Foundation and/or its affiliates.
  *
  * This program and the accompanying materials are made available under the
@@ -88,7 +88,7 @@
         @Override
         public void init(InjectionManager injectionManager, BootstrapBag bootstrapBag) {
             bootstrapBag.setConfiguration(runtimeConfig);
-            injectionManager.register(Bindings.service(runtimeConfig).to(Configuration.class));
+            injectionManager.register(Bindings.service(runtimeConfig).to(Configuration.class).forClient(true).id(1000));
         }
     }
 
@@ -417,69 +417,27 @@
             runtimeCfgState.markAsShared();
 
             final InjectionManager injectionManager = findInjectionManager();
-            injectionManager.register(new ClientBinder(runtimeCfgState.getProperties()));
-
-            final ClientBootstrapBag bootstrapBag = new ClientBootstrapBag();
-            bootstrapBag.setManagedObjectsFinalizer(new ManagedObjectsFinalizer(injectionManager));
-
-            final ClientMessageBodyFactory.MessageBodyWorkersConfigurator messageBodyWorkersConfigurator =
-                    new ClientMessageBodyFactory.MessageBodyWorkersConfigurator();
-
-            List<BootstrapConfigurator> bootstrapConfigurators = Arrays.asList(
-                    new RequestScope.RequestScopeConfigurator(),
-                    new ParamConverterConfigurator(),
-                    new ParameterUpdaterConfigurator(),
-                    new RuntimeConfigConfigurator(runtimeCfgState),
-                    new ContextResolverFactory.ContextResolversConfigurator(),
-                    messageBodyWorkersConfigurator,
-                    new ExceptionMapperFactory.ExceptionMappersConfigurator(),
-                    new JaxrsProviders.ProvidersConfigurator(),
-                    new AutoDiscoverableConfigurator(RuntimeType.CLIENT),
-                    new ClientComponentConfigurator(),
-                    new FeatureConfigurator(RuntimeType.CLIENT));
-            bootstrapConfigurators.forEach(configurator -> configurator.init(injectionManager, bootstrapBag));
-
-            // AutoDiscoverable.
-            if (!CommonProperties.getValue(runtimeCfgState.getProperties(), RuntimeType.CLIENT,
-                    CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE, Boolean.FALSE, Boolean.class)) {
-                runtimeCfgState.configureAutoDiscoverableProviders(injectionManager, bootstrapBag.getAutoDiscoverables());
-            } else {
-                runtimeCfgState.configureForcedAutoDiscoverableProviders(injectionManager);
-            }
-
-            // Configure binders and features.
-            runtimeCfgState.configureMetaProviders(injectionManager, bootstrapBag.getManagedObjectsFinalizer());
-
-            // Bind providers.
-            final Collection<ComponentProvider> componentProviders = bootstrapBag.getComponentProviders().get();
-            ProviderBinder.bindProviders(
-                    runtimeCfgState.getComponentBag(), RuntimeType.CLIENT, null, injectionManager, componentProviders
-            );
-
-            ClientExecutorProvidersConfigurator executorProvidersConfigurator =
-                    new ClientExecutorProvidersConfigurator(runtimeCfgState.getComponentBag(),
-                            runtimeCfgState.client,
-                            this.executorService,
-                            this.scheduledExecutorService);
-            executorProvidersConfigurator.init(injectionManager, bootstrapBag);
+            final PreInitialization preInit =
+                    new PreInitialization(runtimeCfgState, injectionManager, this.executorService, this.scheduledExecutorService);
+            List<BootstrapConfigurator> bootstrapConfigurators = preInit.bootstrapConfigurators;
 
             injectionManager.completeRegistration();
 
-            bootstrapConfigurators.forEach(configurator -> configurator.postInit(injectionManager, bootstrapBag));
+            bootstrapConfigurators.forEach(configurator -> 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, bootstrapBag);
+            final ClientRuntime crt = new ClientRuntime(configuration, connector, injectionManager, preInit.bootstrapBag);
 
             client.registerShutdownHook(crt);
-            messageBodyWorkersConfigurator.setClientRuntime(crt);
+            preInit.messageBodyWorkersConfigurator.setClientRuntime(crt);
 
             return crt;
         }
 
-        private final InjectionManager findInjectionManager() {
+        private InjectionManager findInjectionManager() {
             try {
-                return Injections.createInjectionManager(RuntimeType.CLIENT);
+                return Injections.createInjectionManager(commonConfig);
             } catch (IllegalStateException ise) {
                 return new NonInjectionManager(true);
             }
@@ -515,6 +473,68 @@
         }
     }
 
+    /* package */ static class PreInitialization {
+        private final ClientBootstrapBag bootstrapBag;
+        private final List<BootstrapConfigurator> bootstrapConfigurators;
+        private final ClientMessageBodyFactory.MessageBodyWorkersConfigurator messageBodyWorkersConfigurator;
+
+        /* package */ PreInitialization(InjectionManager injectionManager) {
+            this(new State(new JerseyClient()), injectionManager, null, null);
+        }
+
+
+        /* package */ PreInitialization(
+                State runtimeCfgState,
+                InjectionManager injectionManager,
+                ExecutorService executorService,
+                ScheduledExecutorService scheduledExecutorService) {
+            injectionManager.register(new ClientBinder(runtimeCfgState.getProperties()));
+
+            bootstrapBag = new ClientBootstrapBag();
+            bootstrapBag.setManagedObjectsFinalizer(new ManagedObjectsFinalizer(injectionManager));
+
+            messageBodyWorkersConfigurator = new ClientMessageBodyFactory.MessageBodyWorkersConfigurator(); // 2020
+
+            bootstrapConfigurators = Arrays.asList(
+                    new RequestScope.RequestScopeConfigurator(),
+                    new ParamConverterConfigurator(), // 2010
+                    new ParameterUpdaterConfigurator(), // 2011
+                    new RuntimeConfigConfigurator(runtimeCfgState), // 2012
+                    new ContextResolverFactory.ContextResolversConfigurator(), // 2014
+                    messageBodyWorkersConfigurator,
+                    new ExceptionMapperFactory.ExceptionMappersConfigurator(), // 2015
+                    new JaxrsProviders.ProvidersConfigurator(), // 2016
+                    new AutoDiscoverableConfigurator(RuntimeType.CLIENT),
+                    new ClientComponentConfigurator(),
+                    new FeatureConfigurator(RuntimeType.CLIENT));
+            bootstrapConfigurators.forEach(configurator -> configurator.init(injectionManager, bootstrapBag));
+
+            // AutoDiscoverable.
+            if (!CommonProperties.getValue(runtimeCfgState.getProperties(), RuntimeType.CLIENT,
+                    CommonProperties.FEATURE_AUTO_DISCOVERY_DISABLE, Boolean.FALSE, Boolean.class)) {
+                runtimeCfgState.configureAutoDiscoverableProviders(injectionManager, bootstrapBag.getAutoDiscoverables());
+            } else {
+                runtimeCfgState.configureForcedAutoDiscoverableProviders(injectionManager);
+            }
+
+            // Configure binders and features.
+            runtimeCfgState.configureMetaProviders(injectionManager, bootstrapBag.getManagedObjectsFinalizer());
+
+            // Bind providers.
+            final Collection<ComponentProvider> componentProviders = bootstrapBag.getComponentProviders().get();
+            ProviderBinder.bindProviders(
+                    runtimeCfgState.getComponentBag(), RuntimeType.CLIENT, null, injectionManager, componentProviders
+            );
+
+            ClientExecutorProvidersConfigurator executorProvidersConfigurator =
+                    new ClientExecutorProvidersConfigurator(runtimeCfgState.getComponentBag(),
+                            runtimeCfgState.client,
+                            executorService,
+                            scheduledExecutorService);
+            executorProvidersConfigurator.init(injectionManager, bootstrapBag);
+        }
+    }
+
     /**
      * Construct a new Jersey configuration instance with the default features
      * and property values.
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientExecutorProvidersConfigurator.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientExecutorProvidersConfigurator.java
index df26b22..b575a5c 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/ClientExecutorProvidersConfigurator.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientExecutorProvidersConfigurator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2021 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
@@ -37,6 +37,8 @@
 import org.glassfish.jersey.spi.ExecutorServiceProvider;
 import org.glassfish.jersey.spi.ScheduledExecutorServiceProvider;
 
+import jakarta.ws.rs.RuntimeType;
+
 /**
  * Configurator which initializes and register {@link ExecutorServiceProvider} and
  * {@link ScheduledExecutorServiceProvider}.
@@ -106,7 +108,9 @@
 
         InstanceBinding<ExecutorServiceProvider> executorBinding = Bindings
                 .service(defaultAsyncExecutorProvider)
-                .to(ExecutorServiceProvider.class);
+                .to(ExecutorServiceProvider.class)
+                .forClient(true)
+                .id(2020);
 
         injectionManager.register(executorBinding);
 
@@ -130,11 +134,13 @@
 
         InstanceBinding<ScheduledExecutorServiceProvider> schedulerBinding = Bindings
                 .service(defaultScheduledExecutorProvider)
-                .to(ScheduledExecutorServiceProvider.class);
+                .to(ScheduledExecutorServiceProvider.class)
+                .forClient(true)
+                .id(2021);
         injectionManager.register(schedulerBinding);
 
         registerExecutors(injectionManager, componentBag, defaultAsyncExecutorProvider,
-                defaultScheduledExecutorProvider, bootstrapBag.getManagedObjectsFinalizer());
+                defaultScheduledExecutorProvider, bootstrapBag.getManagedObjectsFinalizer(), RuntimeType.CLIENT);
     }
 
     private static ExecutorService lookupManagedExecutorService() {
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientMessageBodyFactory.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientMessageBodyFactory.java
index bbd0abc..f16cd34 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/ClientMessageBodyFactory.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientMessageBodyFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 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
@@ -65,8 +65,7 @@
         public void init(InjectionManager injectionManager, BootstrapBag bootstrapBag) {
             messageBodyFactory = new ClientMessageBodyFactory(bootstrapBag.getConfiguration(), () -> clientRuntime);
             InstanceBinding<ClientMessageBodyFactory> binding =
-                    Bindings.service(messageBodyFactory)
-                            .to(MessageBodyWorkers.class);
+                    Bindings.service(messageBodyFactory).to(MessageBodyWorkers.class).id(2020);
             injectionManager.register(binding);
         }
 
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/internal/inject/ParameterUpdaterConfigurator.java b/core-client/src/main/java/org/glassfish/jersey/client/internal/inject/ParameterUpdaterConfigurator.java
index f8627f8..4d58a8a 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/internal/inject/ParameterUpdaterConfigurator.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/internal/inject/ParameterUpdaterConfigurator.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.
  * Copyright (c) 2018 Payara Foundation and/or its affiliates.
  *
  * This program and the accompanying materials are made available under the
@@ -53,6 +53,6 @@
         ParameterUpdaterFactory parameterUpdaterFactory = new ParameterUpdaterFactory(lazyParamConverterFactory);
         clientBag.setParameterUpdaterProvider(parameterUpdaterFactory);
         injectionManager.register(Bindings.service(parameterUpdaterFactory)
-                        .to(ParameterUpdaterProvider.class));
+                        .to(ParameterUpdaterProvider.class).id(2011));
     }
 }
diff --git a/core-client/src/main/resources/META-INF/services/org.glassfish.jersey.innate.BootstrapPreinitialization b/core-client/src/main/resources/META-INF/services/org.glassfish.jersey.innate.BootstrapPreinitialization
new file mode 100644
index 0000000..c8f92f0
--- /dev/null
+++ b/core-client/src/main/resources/META-INF/services/org.glassfish.jersey.innate.BootstrapPreinitialization
@@ -0,0 +1 @@
+org.glassfish.jersey.client.ClientBootstrapPreinitialization
\ No newline at end of file
diff --git a/core-common/src/main/java/org/glassfish/jersey/innate/BootstrapPreinitialization.java b/core-common/src/main/java/org/glassfish/jersey/innate/BootstrapPreinitialization.java
new file mode 100644
index 0000000..29f7fe9
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/BootstrapPreinitialization.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.innate;
+
+import org.glassfish.jersey.Beta;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+
+import jakarta.ws.rs.RuntimeType;
+import jakarta.ws.rs.core.FeatureContext;
+
+/**
+ * <p>
+ *     The entry point for pre-initialize Jersey during bootstrap. Register the beans that are not recognized by the injection
+ *     framework to be injected in runtime. Register beans for the specific runtime type into the {@link InjectionManager}.
+ * </p>
+ */
+@Beta
+public interface BootstrapPreinitialization {
+    /**
+     * Manually register beans that are not automatically recognised by the injection framework.
+     * @param runtimeType
+     * @param injectionManager
+     */
+    void preregister(RuntimeType runtimeType, InjectionManager injectionManager);
+
+    static FeatureContext featureContextInstance() {
+        return new PreinitializationFeatureContext();
+    }
+}
diff --git a/core-common/src/main/java/org/glassfish/jersey/innate/PreinitializationFeatureContext.java b/core-common/src/main/java/org/glassfish/jersey/innate/PreinitializationFeatureContext.java
new file mode 100644
index 0000000..6882630
--- /dev/null
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/PreinitializationFeatureContext.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.innate;
+
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.Binding;
+import org.glassfish.jersey.internal.inject.ClassBinding;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.model.internal.CommonConfig;
+import org.glassfish.jersey.model.internal.ComponentBag;
+
+import jakarta.ws.rs.RuntimeType;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.FeatureContext;
+import java.util.Map;
+
+/**
+ * Feature Context to be used during the Bootstrap Preinitialization phase
+ */
+class PreinitializationFeatureContext implements FeatureContext {
+
+    private final AbstractBinder binder;
+
+    PreinitializationFeatureContext() {
+        this.binder = new AbstractBinder() {
+            @Override
+            protected void configure() {
+
+            }
+        };
+    }
+
+    @Override
+    public Configuration getConfiguration() {
+        return new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL);
+    }
+
+    @Override
+    public FeatureContext property(String name, Object value) {
+        return this;
+    }
+
+    @Override
+    public FeatureContext register(Class<?> componentClass) {
+        binder.bindAsContract(componentClass);
+        return this;
+    }
+
+    @Override
+    public FeatureContext register(Class<?> componentClass, int priority) {
+        binder.bindAsContract(componentClass).ranked(priority);
+        return this;
+    }
+
+    @Override
+    public FeatureContext register(Class<?> componentClass, Class<?>... contracts) {
+        final ClassBinding binding = binder.bind(componentClass);
+        if (contracts != null) {
+            for (Class<?> contract : contracts) {
+                binding.to(contract);
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public FeatureContext register(Class<?> componentClass, Map<Class<?>, Integer> contracts) {
+        for (Map.Entry<Class<?>, Integer> contract : contracts.entrySet()) {
+            final AbstractBinder abstractBinder = new AbstractBinder() {
+                @Override
+                protected void configure() {
+                }
+            };
+            final ClassBinding binding = abstractBinder.bind(componentClass);
+            binding.to(contract.getKey()).ranked(contract.getValue());
+            binder.install(abstractBinder);
+        }
+        return this;
+    }
+
+    @Override
+    public FeatureContext register(Object component) {
+        if (InjectionManager.class.isInstance(component)) {
+            ((InjectionManager) component).register(binder);
+        } else if (AbstractBinder.class.isInstance(component)) {
+            binder.install((AbstractBinder) component);
+        } else {
+            binder.bind(component).to(component.getClass());
+        }
+        return this;
+    }
+
+    @Override
+    public FeatureContext register(Object component, int priority) {
+        binder.bind(component).to(component.getClass()).ranked(priority);
+        return this;
+    }
+
+    @Override
+    public FeatureContext register(Object component, Class<?>... contracts) {
+        Binding binding = binder.bind(component);
+        if (contracts != null) {
+            for (Class<?> contract : contracts) {
+                binding.to(contract);
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public FeatureContext register(Object component, Map<Class<?>, Integer> contracts) {
+        for (Map.Entry<Class<?>, Integer> contract : contracts.entrySet()) {
+            final AbstractBinder abstractBinder = new AbstractBinder() {
+                @Override
+                protected void configure() {
+                }
+            };
+            final Binding binding = abstractBinder.bind(component);
+            binding.to(contract.getKey()).ranked(contract.getValue());
+            binder.install(abstractBinder);
+        }
+        return this;
+    }
+}
diff --git a/core-common/src/main/java/org/glassfish/jersey/innate/package-info.java b/core-common/src/main/java/org/glassfish/jersey/innate/package-info.java
index b0648e7..7d5ae69 100644
--- a/core-common/src/main/java/org/glassfish/jersey/innate/package-info.java
+++ b/core-common/src/main/java/org/glassfish/jersey/innate/package-info.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
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/ContextResolverFactory.java b/core-common/src/main/java/org/glassfish/jersey/internal/ContextResolverFactory.java
index 9c5bb7a..f5631a7 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/ContextResolverFactory.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/ContextResolverFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -24,6 +24,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 
 import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.RuntimeType;
 import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.ext.ContextResolver;
 
@@ -60,7 +61,9 @@
             contextResolverFactory = new ContextResolverFactory();
             InstanceBinding<ContextResolverFactory> binding =
                     Bindings.service(contextResolverFactory)
-                            .to(ContextResolvers.class);
+                            .to(ContextResolvers.class)
+                            .forClient(bootstrapBag.getConfiguration().getRuntimeType() == RuntimeType.CLIENT)
+                            .id(1014);
             injectionManager.register(binding);
         }
 
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/ExceptionMapperFactory.java b/core-common/src/main/java/org/glassfish/jersey/internal/ExceptionMapperFactory.java
index 55e5a68..cf0171a 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/ExceptionMapperFactory.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/ExceptionMapperFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -30,9 +30,9 @@
 
 import jakarta.ws.rs.Priorities;
 import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.RuntimeType;
 import jakarta.ws.rs.ext.ExceptionMapper;
 
-import org.glassfish.jersey.JerseyPriorities;
 import org.glassfish.jersey.internal.inject.Bindings;
 import org.glassfish.jersey.internal.inject.InjectionManager;
 import org.glassfish.jersey.internal.inject.InstanceBinding;
@@ -75,7 +75,9 @@
             exceptionMapperFactory = new ExceptionMapperFactory(injectionManager);
             InstanceBinding<ExceptionMapperFactory> binding =
                     Bindings.service(exceptionMapperFactory)
-                            .to(ExceptionMappers.class);
+                            .to(ExceptionMappers.class)
+                            .forClient(bootstrapBag.getConfiguration().getRuntimeType() == RuntimeType.CLIENT)
+                            .id(1015);
             injectionManager.register(binding);
         }
 
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/JaxrsProviders.java b/core-common/src/main/java/org/glassfish/jersey/internal/JaxrsProviders.java
index fa075fb..596860b 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/JaxrsProviders.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/JaxrsProviders.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
@@ -19,6 +19,7 @@
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 
+import jakarta.ws.rs.RuntimeType;
 import jakarta.ws.rs.core.Context;
 import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.ext.ContextResolver;
@@ -59,7 +60,8 @@
             injectionManager.register(
                     Bindings.service(JaxrsProviders.class)
                             .to(Providers.class)
-                            .in(PerLookup.class));
+                            .in(PerLookup.class)
+                            .id(injectionManager.getRuntimeType() == RuntimeType.CLIENT ? 2016 : 3016));
         }
     }
 
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/RuntimeDelegateImpl.java b/core-common/src/main/java/org/glassfish/jersey/internal/RuntimeDelegateImpl.java
index db16be8..ce3aa43 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/RuntimeDelegateImpl.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/RuntimeDelegateImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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,14 +16,13 @@
 
 package org.glassfish.jersey.internal;
 
+import jakarta.ws.rs.RuntimeType;
 import jakarta.ws.rs.SeBootstrap;
 import jakarta.ws.rs.core.Application;
 
-import jakarta.ws.rs.core.EntityPart;
 import jakarta.ws.rs.ext.RuntimeDelegate;
 import org.glassfish.jersey.message.internal.MessagingBinders;
 
-import java.util.Optional;
 import java.util.concurrent.CompletionStage;
 
 /**
@@ -40,7 +39,7 @@
 public class RuntimeDelegateImpl extends AbstractRuntimeDelegate {
 
     public RuntimeDelegateImpl() {
-        super(new MessagingBinders.HeaderDelegateProviders().getHeaderDelegateProviders());
+        super(new MessagingBinders.HeaderDelegateProviders(RuntimeType.CLIENT).getHeaderDelegateProviders());
     }
 
     @Override
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/inject/Binding.java b/core-common/src/main/java/org/glassfish/jersey/internal/inject/Binding.java
index 69a534a..f793792 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/inject/Binding.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/inject/Binding.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,10 +16,14 @@
 
 package org.glassfish.jersey.internal.inject;
 
+import org.glassfish.jersey.Beta;
+
 import java.lang.annotation.Annotation;
+import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.util.Collection;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Set;
 
 import jakarta.ws.rs.core.GenericType;
@@ -46,6 +50,8 @@
     private Boolean proxiable = null;
     private Boolean proxyForSameScope = null;
     private Integer ranked = null;
+    private boolean forClient = false;
+    private long id = 0;
 
     /**
      * Gets information whether the service is proxiable.
@@ -138,6 +144,15 @@
     }
 
     /**
+     * Get the hint of the bean that exists both on the client and the server
+     * @return the hint that this binding if for being injected on the client.
+     */
+    @Beta
+    public boolean isForClient() {
+        return forClient;
+    }
+
+    /**
      * Adds service's analyzer.
      *
      * @return current instance.
@@ -260,8 +275,9 @@
      *
      * @return current instance.
      */
-    public void ranked(int rank) {
+    public D ranked(int rank) {
         this.ranked = rank;
+        return (D) this;
     }
 
     /**
@@ -273,4 +289,58 @@
         this.implementationType = type;
         return (D) this;
     }
+
+    /**
+     * A hint whether the bean is for being injected using {@code @Inject} on the client side
+     * but there is also a bean with the same contract on the server, such as for {@code Configuration}.
+     *
+     * <p>Default is false.</p>
+     *
+     * @param forClient {@code true} when injectable for the same contract exists both on the client and server and
+     *                              this binding is for the client side.
+     * @return current instance.
+     */
+    @Beta
+    public D forClient(boolean forClient) {
+        this.forClient = forClient;
+        return (D) this;
+    }
+
+    /**
+     * The binding id used to match the binding in the pre-binding phase and in the binding phase.
+     * @param id the unique id.
+     * @return current instance.
+     */
+    @Beta
+    public D id(long id) {
+        // 1000 - 1999 Core-Common
+        // 2000 - 2999 Core-Client
+        // 3000 - 3999 Core-Server
+        this.id = id;
+        return (D) this;
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    @Override
+    public String toString() {
+        return contractsAsString() + " <- " + implementationType.getSimpleName();
+    }
+
+    protected String contractsAsString() {
+        StringBuilder sb = new StringBuilder();
+        Iterator<Type> it = contracts.iterator();
+        while (it.hasNext()) {
+            Type next = it.next();
+            if (Class.class.isInstance(next)) {
+                sb.append(((Class) next).getSimpleName());
+            } else if (ParameterizedType.class.isInstance(next)) {
+                sb.append(next);
+            }
+        }
+        return sb.toString();
+    }
+
 }
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/inject/InjectionManager.java b/core-common/src/main/java/org/glassfish/jersey/internal/inject/InjectionManager.java
index 4d5fd1c..3961d55 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/inject/InjectionManager.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/inject/InjectionManager.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
@@ -16,6 +16,9 @@
 
 package org.glassfish.jersey.internal.inject;
 
+import org.glassfish.jersey.Beta;
+
+import jakarta.ws.rs.RuntimeType;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import java.util.List;
@@ -257,4 +260,13 @@
      * @param preDestroyMe The object to preDestroy
      */
     void preDestroy(Object preDestroyMe);
+
+    /**
+     * Get RuntimeType of the InjectionManager.
+     * @return the runtimeType
+     */
+    @Beta
+    default RuntimeType getRuntimeType() {
+        return null;
+    }
 }
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/inject/InjectionManagerFactory.java b/core-common/src/main/java/org/glassfish/jersey/internal/inject/InjectionManagerFactory.java
index 2a74b37..41e3dca 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/inject/InjectionManagerFactory.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/inject/InjectionManagerFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018 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,6 +16,8 @@
 
 package org.glassfish.jersey.internal.inject;
 
+import jakarta.ws.rs.core.Configuration;
+
 /**
  * Factory which is able to create {@link InjectionManager}. Every DI provider must create its own {@link InjectionManagerFactory}
  * and register it in META-INF.services. Then the {@code InjectionManagerFactory} can be looked up and {@code InjectionManager}
@@ -39,4 +41,13 @@
      * @return initialized injection manager.
      */
     InjectionManager create(Object parent);
+
+    /**
+     * Load a new injection manager with parent object for a given RuntimeType.
+     *
+     * @param configuration the configuration including RuntimeType of the InjectionManager used.
+     * @param parent injection manager parent or concrete DI specific object which is compatible with DI provider.
+     * @return initialized injection manager.
+     */
+    InjectionManager create(Object parent, Configuration configuration);
 }
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/inject/InjectionResolverBinding.java b/core-common/src/main/java/org/glassfish/jersey/internal/inject/InjectionResolverBinding.java
index 44f8dee..590cb54 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/inject/InjectionResolverBinding.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/inject/InjectionResolverBinding.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018 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
@@ -42,4 +42,10 @@
     public T getResolver() {
         return resolver;
     }
+
+    @Override
+    public String toString() {
+        return resolver.getClass().getSimpleName() + " <- " + resolver.getClass().getSimpleName();
+
+    }
 }
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/inject/Injections.java b/core-common/src/main/java/org/glassfish/jersey/internal/inject/Injections.java
index 1750dd8..ac5f012 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/inject/Injections.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/inject/Injections.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,13 +16,20 @@
 
 package org.glassfish.jersey.internal.inject;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 
 import jakarta.ws.rs.ConstrainedTo;
 import jakarta.ws.rs.RuntimeType;
 import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.Feature;
+
 
 import org.glassfish.jersey.internal.LocalizationMessages;
 import org.glassfish.jersey.internal.ServiceFinder;
@@ -43,7 +50,7 @@
      * @return an injection manager with all the bindings.
      */
     public static InjectionManager createInjectionManager() {
-        return lookupInjectionManagerFactory(RuntimeType.SERVER).create();
+        return createInjectionManager(new EmptyConfiguration(RuntimeType.SERVER));
     }
 
     /**
@@ -53,7 +60,17 @@
      * @return an injection manager with all the bindings.
      */
     public static InjectionManager createInjectionManager(RuntimeType type) {
-        return lookupInjectionManagerFactory(type).create();
+        return createInjectionManager(new EmptyConfiguration(type));
+    }
+
+    /**
+     * Creates an {@link InjectionManager} without parent and initial binder.
+     * @param configuration {@link Configuration} including {@link RuntimeType} the {@link InjectionManagerFactory}
+     *                      must be {@link ConstrainedTo} if annotated.
+     * @return an injection manager with all the bindings.
+     */
+    public static InjectionManager createInjectionManager(Configuration configuration) {
+        return lookupInjectionManagerFactory(configuration.getRuntimeType()).create(null, configuration);
     }
 
     /**
@@ -63,8 +80,7 @@
      * @return an injection manager with all the bindings.
      */
     public static InjectionManager createInjectionManager(Binder binder) {
-        InjectionManagerFactory injectionManagerFactory = lookupInjectionManagerFactory(RuntimeType.SERVER);
-        InjectionManager injectionManager = injectionManagerFactory.create();
+        InjectionManager injectionManager = createInjectionManager(RuntimeType.SERVER);
         injectionManager.register(binder);
         return injectionManager;
     }
@@ -78,7 +94,21 @@
      * @return an injection manager with all the bindings.
      */
     public static InjectionManager createInjectionManager(Object parent) {
-        return lookupInjectionManagerFactory(RuntimeType.SERVER).create(parent);
+        return createInjectionManager(parent, new EmptyConfiguration(RuntimeType.SERVER));
+    }
+
+    /**
+     * Creates an unnamed, parented {@link InjectionManager}. In case the {@code parent} injection manager is not specified, the
+     * locator will not be parented.
+     *
+     * @param parent The parent of this injection manager. Services can be found in the parent (and all grand-parents). May be
+     *               {@code null}. An underlying DI provider checks whether the parent is in a proper type.
+     * @param configuration {@link Configuration} including {@link RuntimeType} the {@link InjectionManagerFactory}
+     *                      must be {@link ConstrainedTo} if annotated.
+     * @return an injection manager with all the bindings.
+     */
+    public static InjectionManager createInjectionManager(Object parent, Configuration configuration) {
+        return lookupInjectionManagerFactory(configuration.getRuntimeType()).create(parent, configuration);
     }
 
     private static InjectionManagerFactory lookupInjectionManagerFactory(RuntimeType type) {
@@ -136,4 +166,68 @@
             throw e;
         }
     }
+
+    private static final class EmptyConfiguration implements Configuration {
+
+        private final RuntimeType runtimeType;
+
+        private EmptyConfiguration(RuntimeType runtimeType) {
+            this.runtimeType = runtimeType;
+        }
+
+        @Override
+        public RuntimeType getRuntimeType() {
+            return runtimeType;
+        }
+
+        @Override
+        public Map<String, Object> getProperties() {
+            return Collections.emptyMap();
+        }
+
+        @Override
+        public Object getProperty(String name) {
+            return getProperties().get(name);
+        }
+
+        @Override
+        public Collection<String> getPropertyNames() {
+            return getProperties().keySet();
+        }
+
+        @Override
+        public boolean isEnabled(Feature feature) {
+            return false;
+        }
+
+        @Override
+        public boolean isEnabled(Class<? extends Feature> featureClass) {
+            return false;
+        }
+
+        @Override
+        public boolean isRegistered(Object component) {
+            return false;
+        }
+
+        @Override
+        public boolean isRegistered(Class<?> componentClass) {
+            return false;
+        }
+
+        @Override
+        public Map<Class<?>, Integer> getContracts(Class<?> componentClass) {
+            return Collections.emptyMap();
+        }
+
+        @Override
+        public Set<Class<?>> getClasses() {
+            return Collections.emptySet();
+        }
+
+        @Override
+        public Set<Object> getInstances() {
+            return Collections.emptySet();
+        }
+    }
 }
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/inject/InstanceBinding.java b/core-common/src/main/java/org/glassfish/jersey/internal/inject/InstanceBinding.java
index af51072..6f9f786 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/inject/InstanceBinding.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/inject/InstanceBinding.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018 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
@@ -59,4 +59,10 @@
     public T getService() {
         return service;
     }
+
+
+    @Override
+    public String toString() {
+        return contractsAsString() + " <- " + service.getClass().getSimpleName();
+    }
 }
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/inject/ParamConverterConfigurator.java b/core-common/src/main/java/org/glassfish/jersey/internal/inject/ParamConverterConfigurator.java
index f10976a..6fa7127 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/inject/ParamConverterConfigurator.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/inject/ParamConverterConfigurator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2018 Payara Foundation and/or its affiliates.
  *
  * This program and the accompanying materials are made available under the
@@ -17,6 +17,7 @@
 
 package org.glassfish.jersey.internal.inject;
 
+import jakarta.ws.rs.RuntimeType;
 import jakarta.ws.rs.ext.ParamConverterProvider;
 
 import org.glassfish.jersey.internal.BootstrapBag;
@@ -31,9 +32,10 @@
 
     @Override
     public void init(InjectionManager injectionManager, BootstrapBag bootstrapBag) {
+        long id = injectionManager.getRuntimeType() == RuntimeType.CLIENT ? 2010 : 3010;
         final ClassBinding<ParamConverters.AggregatedProvider> aggregatedConverters =
                 Bindings.service(ParamConverters.AggregatedProvider.class)
-                    .to(ParamConverterProvider.class);
+                    .to(ParamConverterProvider.class).id(id);
         injectionManager.register(aggregatedConverters);
     }
 }
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/inject/SupplierClassBinding.java b/core-common/src/main/java/org/glassfish/jersey/internal/inject/SupplierClassBinding.java
index f07b4ff..fd6f86e 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/inject/SupplierClassBinding.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/inject/SupplierClassBinding.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018 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
@@ -58,4 +58,9 @@
     public Class<? extends Annotation> getSupplierScope() {
         return supplierScope;
     }
+
+    @Override
+    public String toString() {
+        return contractsAsString() + " <- " + supplierClass.getSimpleName();
+    }
 }
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/inject/SupplierInstanceBinding.java b/core-common/src/main/java/org/glassfish/jersey/internal/inject/SupplierInstanceBinding.java
index e3f6643..1d826b5 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/inject/SupplierInstanceBinding.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/inject/SupplierInstanceBinding.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018 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
@@ -45,4 +45,9 @@
     public Supplier<T> getSupplier() {
         return supplier;
     }
+
+    @Override
+    public String toString() {
+        return contractsAsString() + " <- " + supplier.get().getClass().getSimpleName();
+    }
 }
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/MessageBodyFactory.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/MessageBodyFactory.java
index ab95eaf..43abe49 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/MessageBodyFactory.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/MessageBodyFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -105,7 +105,8 @@
             messageBodyFactory = new MessageBodyFactory(bootstrapBag.getConfiguration());
             InstanceBinding<MessageBodyFactory> binding =
                     Bindings.service(messageBodyFactory)
-                            .to(MessageBodyWorkers.class);
+                            .to(MessageBodyWorkers.class)
+                            .id(3182);
             injectionManager.register(binding);
         }
 
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/MessagingBinders.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/MessagingBinders.java
index fa1117a..85c56b0 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/MessagingBinders.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/MessagingBinders.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
@@ -20,10 +20,12 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
 import java.util.logging.Logger;
 
 import jakarta.ws.rs.RuntimeType;
@@ -89,17 +91,17 @@
         protected void configure() {
 
             // Message body providers (both readers & writers)
-            bindSingletonWorker(ByteArrayProvider.class);
+            bindSingletonWorker(ByteArrayProvider.class, runtimeType == RuntimeType.CLIENT ? 2030 : 3030);
             // bindSingletonWorker(DataSourceProvider.class);
-            bindSingletonWorker(FileProvider.class);
-            bindSingletonWorker(FormMultivaluedMapProvider.class);
-            bindSingletonWorker(FormProvider.class);
-            bindSingletonWorker(InputStreamProvider.class);
-            bindSingletonWorker(BasicTypesMessageProvider.class);
-            bindSingletonWorker(ReaderProvider.class);
+            bindSingletonWorker(FileProvider.class, runtimeType == RuntimeType.CLIENT ? 2031 : 3031);
+            bindSingletonWorker(FormMultivaluedMapProvider.class, runtimeType == RuntimeType.CLIENT ? 2032 : 3032);
+            bindSingletonWorker(FormProvider.class, runtimeType == RuntimeType.CLIENT ? 2033 : 3033);
+            bindSingletonWorker(InputStreamProvider.class, runtimeType == RuntimeType.CLIENT ? 2034 : 3034);
+            bindSingletonWorker(BasicTypesMessageProvider.class, runtimeType == RuntimeType.CLIENT ? 2035 : 3035);
+            bindSingletonWorker(ReaderProvider.class, runtimeType == RuntimeType.CLIENT ? 2036 : 3036);
             // bindSingletonWorker(RenderedImageProvider.class); - enabledProvidersBinder
-            bindSingletonWorker(StringMessageProvider.class);
-            bindSingletonWorker(EnumMessageProvider.class);
+            bindSingletonWorker(StringMessageProvider.class, runtimeType == RuntimeType.CLIENT ? 2037 : 3037);
+            bindSingletonWorker(EnumMessageProvider.class, runtimeType == RuntimeType.CLIENT ? 2038 : 3038);
 
             // Message body readers -- enabledProvidersBinder
             // bind(SourceProvider.StreamSourceReader.class).to(MessageBodyReader.class).in(Singleton.class);
@@ -110,7 +112,8 @@
              */
 
             // Message body writers
-            bind(StreamingOutputProvider.class).to(MessageBodyWriter.class).in(Singleton.class);
+            bind(StreamingOutputProvider.class).to(MessageBodyWriter.class).in(Singleton.class)
+                    .id(runtimeType == RuntimeType.CLIENT ? 2039 : 3039);
             // bind(SourceProvider.SourceWriter.class).to(MessageBodyWriter.class).in(Singleton.class); - enabledProvidersBinder
 
             final EnabledProvidersBinder enabledProvidersBinder = new EnabledProvidersBinder();
@@ -119,14 +122,14 @@
                         String.valueOf(applicationProperties.get(CommonProperties.PROVIDER_DEFAULT_DISABLE))
                 );
             }
-            enabledProvidersBinder.bindToBinder(this);
+            enabledProvidersBinder.bindToBinder(this, runtimeType);
 
             // Header Delegate Providers registered in META-INF.services
             install(new ServiceFinderBinder<>(HeaderDelegateProvider.class, applicationProperties, runtimeType));
         }
 
-        private <T extends MessageBodyReader & MessageBodyWriter> void bindSingletonWorker(final Class<T> worker) {
-            bind(worker).to(MessageBodyReader.class).to(MessageBodyWriter.class).in(Singleton.class);
+        private <T extends MessageBodyReader & MessageBodyWriter> void bindSingletonWorker(final Class<T> worker, long id) {
+            bind(worker).to(MessageBodyReader.class).to(MessageBodyWriter.class).in(Singleton.class).id(id);
         }
     }
 
@@ -136,9 +139,11 @@
     public static class HeaderDelegateProviders extends AbstractBinder {
 
         private final Set<HeaderDelegateProvider> providers;
+        private final RuntimeType runtimeType;
 
-        public HeaderDelegateProviders() {
-            Set<HeaderDelegateProvider> providers = new HashSet<>();
+        public HeaderDelegateProviders(RuntimeType runtimeType) {
+            this.runtimeType = runtimeType;
+            Set<HeaderDelegateProvider> providers = new LinkedHashSet<>();
             providers.add(new CacheControlProvider());
             providers.add(new CookieProvider());
             providers.add(new DateProvider());
@@ -154,7 +159,9 @@
 
         @Override
         protected void configure() {
-            providers.forEach(provider -> bind(provider).to(HeaderDelegateProvider.class));
+            AtomicLong id = new AtomicLong(40);
+            providers.forEach(provider -> bind(provider).to(HeaderDelegateProvider.class)
+                    .id((runtimeType == RuntimeType.CLIENT ? 2000 : 3000) + id.getAndIncrement()));
         }
 
         /**
@@ -207,7 +214,7 @@
             }
         }
 
-        private void bindToBinder(AbstractBinder binder) {
+        private void bindToBinder(AbstractBinder binder, RuntimeType runtimeType) {
             ProviderBinder providerBinder = null;
             for (Provider provider : enabledProviders) {
                 if (isClass(provider.className)) {
@@ -231,7 +238,7 @@
                             providerBinder = new StreamSourceBinder();
                             break;
                     }
-                    providerBinder.bind(binder, provider);
+                    providerBinder.bind(binder, provider, runtimeType);
                 } else {
                     if (warningMap.get(provider).compareAndSet(false, true)) {
                         switch (provider) {
@@ -260,50 +267,56 @@
         }
 
         private interface ProviderBinder {
-            void bind(AbstractBinder binder, Provider provider);
+            void bind(AbstractBinder binder, Provider provider, RuntimeType runtimeType);
         }
 
         private static class DataSourceBinder implements ProviderBinder {
             @Override
-            public void bind(AbstractBinder binder, Provider provider) {
+            public void bind(AbstractBinder binder, Provider provider, RuntimeType runtimeType) {
                 binder.bind(DataSourceProvider.class)
-                        .to(MessageBodyReader.class).to(MessageBodyWriter.class).in(Singleton.class);
+                        .to(MessageBodyReader.class).to(MessageBodyWriter.class).in(Singleton.class)
+                        .id(runtimeType == RuntimeType.CLIENT ? 2070 : 3070);
             }
         }
 
         private static class DomSourceBinder implements ProviderBinder {
             @Override
-            public void bind(AbstractBinder binder, Provider provider) {
-                binder.bind(SourceProvider.DomSourceReader.class).to(MessageBodyReader.class).in(Singleton.class);
+            public void bind(AbstractBinder binder, Provider provider, RuntimeType runtimeType) {
+                binder.bind(SourceProvider.DomSourceReader.class).to(MessageBodyReader.class).in(Singleton.class)
+                        .id(runtimeType == RuntimeType.CLIENT ? 2071 : 3071);
             }
         }
 
         private static class RenderedImageBinder implements ProviderBinder {
             @Override
-            public void bind(AbstractBinder binder, Provider provider) {
+            public void bind(AbstractBinder binder, Provider provider, RuntimeType runtimeType) {
                 binder.bind(RenderedImageProvider.class)
-                        .to(MessageBodyReader.class).to(MessageBodyWriter.class).in(Singleton.class);
+                        .to(MessageBodyReader.class).to(MessageBodyWriter.class).in(Singleton.class)
+                        .id(runtimeType == RuntimeType.CLIENT ? 2072 : 3072);
             }
         }
 
         private static class SaxSourceBinder implements ProviderBinder {
             @Override
-            public void bind(AbstractBinder binder, Provider provider) {
-                binder.bind(SourceProvider.SaxSourceReader.class).to(MessageBodyReader.class).in(Singleton.class);
+            public void bind(AbstractBinder binder, Provider provider, RuntimeType runtimeType) {
+                binder.bind(SourceProvider.SaxSourceReader.class).to(MessageBodyReader.class).in(Singleton.class)
+                        .id(runtimeType == RuntimeType.CLIENT ? 2073 : 3073);
             }
         }
 
         private static class SourceBinder implements ProviderBinder {
             @Override
-            public void bind(AbstractBinder binder, Provider provider) {
-                binder.bind(SourceProvider.SourceWriter.class).to(MessageBodyWriter.class).in(Singleton.class);
+            public void bind(AbstractBinder binder, Provider provider, RuntimeType runtimeType) {
+                binder.bind(SourceProvider.SourceWriter.class).to(MessageBodyWriter.class).in(Singleton.class)
+                        .id(runtimeType == RuntimeType.CLIENT ? 2074 : 3074);
             }
         }
 
         private static class StreamSourceBinder implements ProviderBinder {
             @Override
-            public void bind(AbstractBinder binder, Provider provider) {
-                binder.bind(SourceProvider.StreamSourceReader.class).to(MessageBodyReader.class).in(Singleton.class);
+            public void bind(AbstractBinder binder, Provider provider, RuntimeType runtimeType) {
+                binder.bind(SourceProvider.StreamSourceReader.class).to(MessageBodyReader.class).in(Singleton.class)
+                        .id(runtimeType == RuntimeType.CLIENT ? 2075 : 3075);
             }
         }
     }
diff --git a/core-common/src/main/java/org/glassfish/jersey/process/internal/AbstractExecutorProvidersConfigurator.java b/core-common/src/main/java/org/glassfish/jersey/process/internal/AbstractExecutorProvidersConfigurator.java
index 2a9c8b4..7ee23d8 100644
--- a/core-common/src/main/java/org/glassfish/jersey/process/internal/AbstractExecutorProvidersConfigurator.java
+++ b/core-common/src/main/java/org/glassfish/jersey/process/internal/AbstractExecutorProvidersConfigurator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2021 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
@@ -28,6 +28,8 @@
 import org.glassfish.jersey.spi.ExecutorServiceProvider;
 import org.glassfish.jersey.spi.ScheduledExecutorServiceProvider;
 
+import jakarta.ws.rs.RuntimeType;
+
 /**
  * Abstract Configurator which initializes and register {@link ExecutorServiceProvider} and
  * {@link ScheduledExecutorServiceProvider}.
@@ -57,7 +59,8 @@
             ComponentBag componentBag,
             ExecutorServiceProvider defaultAsyncExecutorProvider,
             ScheduledExecutorServiceProvider defaultScheduledExecutorProvider,
-            ManagedObjectsFinalizer finalizer) {
+            ManagedObjectsFinalizer finalizer,
+            RuntimeType runtimeType) {
 
         List<ExecutorServiceProvider> customExecutors =
                 Stream.concat(
@@ -79,6 +82,6 @@
         customScheduledExecutors.add(defaultScheduledExecutorProvider);
         customScheduledExecutors.stream().forEach(e -> finalizer.registerForPreDestroyCall(e));
 
-        ExecutorProviders.registerExecutorBindings(injectionManager, customExecutors, customScheduledExecutors);
+        ExecutorProviders.registerExecutorBindings(injectionManager, customExecutors, customScheduledExecutors, runtimeType);
     }
 }
diff --git a/core-common/src/main/java/org/glassfish/jersey/process/internal/ExecutorProviders.java b/core-common/src/main/java/org/glassfish/jersey/process/internal/ExecutorProviders.java
index 2a71beb..f7da69e 100644
--- a/core-common/src/main/java/org/glassfish/jersey/process/internal/ExecutorProviders.java
+++ b/core-common/src/main/java/org/glassfish/jersey/process/internal/ExecutorProviders.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -31,6 +31,7 @@
 import jakarta.inject.Named;
 import jakarta.inject.Qualifier;
 import jakarta.inject.Singleton;
+import jakarta.ws.rs.RuntimeType;
 
 import org.glassfish.jersey.internal.LocalizationMessages;
 import org.glassfish.jersey.internal.inject.Bindings;
@@ -68,13 +69,13 @@
      *
      * @param injectionManager application's injection manager.
      */
-    public static void registerExecutorBindings(InjectionManager injectionManager) {
+    public static void registerExecutorBindings(InjectionManager injectionManager, RuntimeType runtimeType) {
         List<ExecutorServiceProvider> executorProviders =
                 getExecutorProviders(injectionManager, ExecutorServiceProvider.class);
         List<ScheduledExecutorServiceProvider> scheduledProviders =
                 getExecutorProviders(injectionManager, ScheduledExecutorServiceProvider.class);
 
-        registerExecutorBindings(injectionManager, executorProviders, scheduledProviders);
+        registerExecutorBindings(injectionManager, executorProviders, scheduledProviders, runtimeType);
     }
 
     private static <T> List<T> getExecutorProviders(InjectionManager injectionManager, Class<T> providerClass) {
@@ -103,7 +104,8 @@
     public static void registerExecutorBindings(
             InjectionManager injectionManager,
             List<ExecutorServiceProvider> executorProviders,
-            List<ScheduledExecutorServiceProvider> scheduledProviders) {
+            List<ScheduledExecutorServiceProvider> scheduledProviders,
+            RuntimeType runtimeType) {
 
         Map<Class<? extends Annotation>, List<ExecutorServiceProvider>> executorProviderMap =
                 getQualifierToProviderMap(executorProviders);
@@ -122,7 +124,9 @@
             SupplierInstanceBinding<ExecutorService> descriptor =
                     Bindings.supplier(new ExecutorServiceSupplier(executorProvider))
                             .in(Singleton.class)
-                            .to(ExecutorService.class);
+                            .to(ExecutorService.class)
+//                            .forClient(runtimeType == RuntimeType.CLIENT)
+                            .id(runtimeType == RuntimeType.CLIENT ? 1011 : 1111);
 
             Annotation qualifier = executorProvider.getClass().getAnnotation(qualifierAnnotationClass);
             if (qualifier instanceof Named) {
@@ -151,7 +155,9 @@
             SupplierInstanceBinding<ScheduledExecutorService> descriptor =
                     Bindings.supplier(new ScheduledExecutorServiceSupplier(executorProvider))
                             .in(Singleton.class)
-                            .to(ScheduledExecutorService.class);
+                            .to(ScheduledExecutorService.class)
+//                            .forClient(runtimeType == RuntimeType.CLIENT)
+                            .id(runtimeType == RuntimeType.CLIENT ? 1013 : 1113);
 
             if (!executorProviderMap.containsKey(qualifierAnnotationClass)) {
                 // it is safe to register binding for ExecutorService too...
diff --git a/core-common/src/test/java/org/glassfish/jersey/internal/TestRuntimeDelegate.java b/core-common/src/test/java/org/glassfish/jersey/internal/TestRuntimeDelegate.java
index b7d0472..790d92f 100644
--- a/core-common/src/test/java/org/glassfish/jersey/internal/TestRuntimeDelegate.java
+++ b/core-common/src/test/java/org/glassfish/jersey/internal/TestRuntimeDelegate.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,7 @@
 
 package org.glassfish.jersey.internal;
 
+import jakarta.ws.rs.RuntimeType;
 import jakarta.ws.rs.SeBootstrap;
 import jakarta.ws.rs.WebApplicationException;
 import jakarta.ws.rs.core.Application;
@@ -41,7 +42,7 @@
 public class TestRuntimeDelegate extends AbstractRuntimeDelegate {
 
     public TestRuntimeDelegate() {
-        super(new MessagingBinders.HeaderDelegateProviders().getHeaderDelegateProviders());
+        super(new MessagingBinders.HeaderDelegateProviders(RuntimeType.CLIENT).getHeaderDelegateProviders());
     }
 
     @Override
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ApplicationConfigurator.java b/core-server/src/main/java/org/glassfish/jersey/server/ApplicationConfigurator.java
index 08e1460..8531a25 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ApplicationConfigurator.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ApplicationConfigurator.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
@@ -81,7 +81,7 @@
         }
 
         serverBag.setApplication(resultApplication);
-        injectionManager.register(Bindings.service(resultApplication).to(Application.class));
+        injectionManager.register(Bindings.service(resultApplication).to(Application.class).id(3199));
     }
 
     private static Application createApplication(
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ApplicationHandler.java b/core-server/src/main/java/org/glassfish/jersey/server/ApplicationHandler.java
index 7d75df1..6fcbe67 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ApplicationHandler.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ApplicationHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2024 Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2018 Payara Foundation and/or its affiliates.
  *
  * This program and the accompanying materials are made available under the
@@ -186,12 +186,14 @@
             // TODO: Do we really need these three bindings in DI provider? What JAX-RS specification says?
             InstanceBinding<ApplicationHandler> handlerBinding =
                     Bindings.service(ApplicationHandler.this)
-                            .to(ApplicationHandler.class);
+                            .to(ApplicationHandler.class)
+                            .id(3180);
 
             InstanceBinding<ResourceConfig> configBinding =
                     Bindings.service(serverBag.getRuntimeConfig())
                             .to(Configuration.class)
-                            .to(ServerConfig.class);
+                            .to(ServerConfig.class)
+                            .id(1000);
 
             injectionManager.register(handlerBinding);
             injectionManager.register(configBinding);
@@ -274,6 +276,10 @@
         initialize(new ApplicationConfigurator(application), Injections.createInjectionManager(parentManager), customBinder);
     }
 
+    /* package */ ApplicationHandler(InjectionManager injectionManager) {
+        initialize(new ApplicationConfigurator(new Application()), injectionManager, null);
+    }
+
     private void initialize(ApplicationConfigurator applicationConfigurator, InjectionManager injectionManager,
             Binder customBinder) {
         LOGGER.config(LocalizationMessages.INIT_MSG(Version.getBuildId()));
@@ -284,19 +290,19 @@
         ServerBootstrapBag bootstrapBag = new ServerBootstrapBag();
         bootstrapBag.setManagedObjectsFinalizer(managedObjectsFinalizer);
         List<BootstrapConfigurator> bootstrapConfigurators = Arrays.asList(
-                new RequestProcessingConfigurator(),
+                new RequestProcessingConfigurator(), // 3100-3110
                 new RequestScope.RequestScopeConfigurator(),
-                new ParamConverterConfigurator(),
-                new ParamExtractorConfigurator(),
-                new ValueParamProviderConfigurator(),
-                new JerseyResourceContextConfigurator(),
+                new ParamConverterConfigurator(), // 3010
+                new ParamExtractorConfigurator(), // 3111
+                new ValueParamProviderConfigurator(), // 3120-3150
+                new JerseyResourceContextConfigurator(), // 3112
                 new ComponentProviderConfigurator(),
-                new JaxrsProviders.ProvidersConfigurator(),
-                applicationConfigurator,
-                new RuntimeConfigConfigurator(),
-                new ContextResolverFactory.ContextResolversConfigurator(),
-                new MessageBodyFactory.MessageBodyWorkersConfigurator(),
-                new ExceptionMapperFactory.ExceptionMappersConfigurator(),
+                new JaxrsProviders.ProvidersConfigurator(), // 3016
+                applicationConfigurator, // 3190 - 3199
+                new RuntimeConfigConfigurator(), // 3180 - 3181
+                new ContextResolverFactory.ContextResolversConfigurator(), // 3014
+                new MessageBodyFactory.MessageBodyWorkersConfigurator(), // 3182
+                new ExceptionMapperFactory.ExceptionMappersConfigurator(), // 3015
                 new ResourceMethodInvokerConfigurator(),
                 new ProcessingProvidersConfigurator(),
                 new ContainerProviderConfigurator(RuntimeType.SERVER),
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/JerseyResourceContextConfigurator.java b/core-server/src/main/java/org/glassfish/jersey/server/JerseyResourceContextConfigurator.java
index 942237b..1e17d97 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/JerseyResourceContextConfigurator.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/JerseyResourceContextConfigurator.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
@@ -50,7 +50,8 @@
         InstanceBinding<JerseyResourceContext> resourceContextBinding =
                 Bindings.service(resourceContext)
                         .to(ResourceContext.class)
-                        .to(ExtendedResourceContext.class);
+                        .to(ExtendedResourceContext.class)
+                        .id(3112);
         injectionManager.register(resourceContextBinding);
         serverBag.setResourceContext(resourceContext);
     }
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ServerBootstrapPreinitialization.java b/core-server/src/main/java/org/glassfish/jersey/server/ServerBootstrapPreinitialization.java
new file mode 100644
index 0000000..a7e8963
--- /dev/null
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ServerBootstrapPreinitialization.java
@@ -0,0 +1,41 @@
+/*
+ * 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.server;
+
+import org.glassfish.jersey.innate.BootstrapPreinitialization;
+import org.glassfish.jersey.internal.inject.Bindings;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.process.internal.RequestScoped;
+import org.glassfish.jersey.server.wadl.WadlFeature;
+import org.glassfish.jersey.server.wadl.processor.WadlModelProcessor;
+
+import jakarta.ws.rs.RuntimeType;
+
+public class ServerBootstrapPreinitialization implements BootstrapPreinitialization {
+
+    @Override
+    public void preregister(RuntimeType runtimeType, InjectionManager injectionManager) {
+        if (runtimeType == RuntimeType.SERVER) {
+            new ApplicationHandler(injectionManager);
+            if (new WadlFeature().configure(BootstrapPreinitialization.featureContextInstance())) {
+                injectionManager.register(
+                        Bindings.serviceAsContract(WadlModelProcessor.OptionsHandler.class).in(RequestScoped.class)
+                );
+            }
+        }
+    }
+}
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ServerExecutorProvidersConfigurator.java b/core-server/src/main/java/org/glassfish/jersey/server/ServerExecutorProvidersConfigurator.java
index 77974f1..1a8b91b 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/ServerExecutorProvidersConfigurator.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/ServerExecutorProvidersConfigurator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2021 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
@@ -28,6 +28,8 @@
 import org.glassfish.jersey.spi.ScheduledThreadPoolExecutorProvider;
 import org.glassfish.jersey.spi.ThreadPoolExecutorProvider;
 
+import jakarta.ws.rs.RuntimeType;
+
 /**
  * Configurator which initializes and register {@link org.glassfish.jersey.spi.ExecutorServiceProvider} and
  * {@link org.glassfish.jersey.spi.ScheduledExecutorServiceProvider}.
@@ -57,7 +59,7 @@
         injectionManager.register(executorBinding);
 
         registerExecutors(injectionManager, componentBag, defaultAsyncExecutorProvider,
-                defaultScheduledExecutorProvider, serverBag.getManagedObjectsFinalizer());
+                defaultScheduledExecutorProvider, serverBag.getManagedObjectsFinalizer(), RuntimeType.SERVER);
     }
 
     /**
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/RuntimeDelegateImpl.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/RuntimeDelegateImpl.java
index bfaad0e..0b7abc2 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/RuntimeDelegateImpl.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/RuntimeDelegateImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -19,6 +19,7 @@
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CompletionStage;
 
+import jakarta.ws.rs.RuntimeType;
 import jakarta.ws.rs.SeBootstrap;
 import jakarta.ws.rs.core.Application;
 
@@ -45,7 +46,7 @@
 public class RuntimeDelegateImpl extends AbstractRuntimeDelegate {
 
     public RuntimeDelegateImpl() {
-        super(new MessagingBinders.HeaderDelegateProviders().getHeaderDelegateProviders());
+        super(new MessagingBinders.HeaderDelegateProviders(RuntimeType.SERVER).getHeaderDelegateProviders());
     }
 
     @Override
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/inject/ParamExtractorConfigurator.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/inject/ParamExtractorConfigurator.java
index ef540e2..ec6f7dd 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/inject/ParamExtractorConfigurator.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/inject/ParamExtractorConfigurator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2021 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2024 Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2018 Payara Foundation and/or its affiliates.
  *
  * This program and the accompanying materials are made available under the
@@ -52,6 +52,7 @@
         serverBag.setMultivaluedParameterExtractorProvider(multiExtractor);
         injectionManager.register(
                 Bindings.service(multiExtractor)
-                        .to(MultivaluedParameterExtractorProvider.class));
+                        .to(MultivaluedParameterExtractorProvider.class)
+                        .id(3111));
     }
 }
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/inject/ValueParamProviderConfigurator.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/inject/ValueParamProviderConfigurator.java
index 07337eb..f4e1376 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/inject/ValueParamProviderConfigurator.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/inject/ValueParamProviderConfigurator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2021 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,17 +116,17 @@
         serverBag.setValueParamProviders(Collections.unmodifiableCollection(suppliers));
 
         // Needs to be in InjectionManager because of CdiComponentProvider
-        injectionManager.register(Bindings.service(asyncProvider).to(ValueParamProvider.class));
-        injectionManager.register(Bindings.service(cookieProvider).to(ValueParamProvider.class));
-        injectionManager.register(Bindings.service(formProvider).to(ValueParamProvider.class));
-        injectionManager.register(Bindings.service(headerProvider).to(ValueParamProvider.class));
-        injectionManager.register(Bindings.service(matrixProvider).to(ValueParamProvider.class));
-        injectionManager.register(Bindings.service(pathProvider).to(ValueParamProvider.class));
-        injectionManager.register(Bindings.service(queryProvider).to(ValueParamProvider.class));
-        injectionManager.register(Bindings.service(webTargetProvider).to(ValueParamProvider.class));
-        injectionManager.register(Bindings.service(beanProvider).to(ValueParamProvider.class));
-        injectionManager.register(Bindings.service(entityProvider).to(ValueParamProvider.class));
-        injectionManager.register(Bindings.service(contextProvider).to(ValueParamProvider.class));
+        injectionManager.register(Bindings.service(asyncProvider).to(ValueParamProvider.class).id(3120));
+        injectionManager.register(Bindings.service(cookieProvider).to(ValueParamProvider.class).id(3121));
+        injectionManager.register(Bindings.service(formProvider).to(ValueParamProvider.class).id(3122));
+        injectionManager.register(Bindings.service(headerProvider).to(ValueParamProvider.class).id(3123));
+        injectionManager.register(Bindings.service(matrixProvider).to(ValueParamProvider.class).id(3124));
+        injectionManager.register(Bindings.service(pathProvider).to(ValueParamProvider.class).id(3125));
+        injectionManager.register(Bindings.service(queryProvider).to(ValueParamProvider.class).id(3126));
+        injectionManager.register(Bindings.service(webTargetProvider).to(ValueParamProvider.class).id(3127));
+        injectionManager.register(Bindings.service(beanProvider).to(ValueParamProvider.class).id(3128));
+        injectionManager.register(Bindings.service(entityProvider).to(ValueParamProvider.class).id(3129));
+        injectionManager.register(Bindings.service(contextProvider).to(ValueParamProvider.class).id(3130));
 
         // Provide request scoped ContainerRequest without the proxy.
         Provider<ContainerRequest> request = () -> {
@@ -134,20 +134,20 @@
             return reference.get().request();
         };
 
-        registerResolver(injectionManager, asyncProvider, Suspended.class, request);
-        registerResolver(injectionManager, cookieProvider, CookieParam.class, request);
-        registerResolver(injectionManager, formProvider, FormParam.class, request);
-        registerResolver(injectionManager, headerProvider, HeaderParam.class, request);
-        registerResolver(injectionManager, matrixProvider, MatrixParam.class, request);
-        registerResolver(injectionManager, pathProvider, PathParam.class, request);
-        registerResolver(injectionManager, queryProvider, QueryParam.class, request);
-        registerResolver(injectionManager, webTargetProvider, Uri.class, request);
-        registerResolver(injectionManager, beanProvider, BeanParam.class, request);
+        registerResolver(injectionManager, asyncProvider, Suspended.class, request, 3140);
+        registerResolver(injectionManager, cookieProvider, CookieParam.class, request, 3141);
+        registerResolver(injectionManager, formProvider, FormParam.class, request, 3142);
+        registerResolver(injectionManager, headerProvider, HeaderParam.class, request, 3143);
+        registerResolver(injectionManager, matrixProvider, MatrixParam.class, request, 3144);
+        registerResolver(injectionManager, pathProvider, PathParam.class, request, 3145);
+        registerResolver(injectionManager, queryProvider, QueryParam.class, request, 3146);
+        registerResolver(injectionManager, webTargetProvider, Uri.class, request, 31457);
+        registerResolver(injectionManager, beanProvider, BeanParam.class, request, 3148);
     }
 
     private void registerResolver(InjectionManager im, ValueParamProvider vfp, Class<? extends Annotation> annotation,
-            Provider<ContainerRequest> request) {
-        im.register(Bindings.injectionResolver(new ParamInjectionResolver<>(vfp, annotation, request)));
+            Provider<ContainerRequest> request, long id) {
+        im.register(Bindings.injectionResolver(new ParamInjectionResolver<>(vfp, annotation, request)).id(id));
     }
 
     @Override
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/internal/process/RequestProcessingConfigurator.java b/core-server/src/main/java/org/glassfish/jersey/server/internal/process/RequestProcessingConfigurator.java
index 9194c47..c90ebeb 100644
--- a/core-server/src/main/java/org/glassfish/jersey/server/internal/process/RequestProcessingConfigurator.java
+++ b/core-server/src/main/java/org/glassfish/jersey/server/internal/process/RequestProcessingConfigurator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2021 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
@@ -123,25 +123,28 @@
         @Override
         protected void configure() {
             bindAsContract(RequestProcessingContextReference.class)
-                    .in(RequestScoped.class);
+                    .in(RequestScoped.class).id(3101);
 
             // Bind non-proxiable ContainerRequest injection injection points
             bindFactory(ContainerRequestFactory.class)
                     .to(ContainerRequest.class).to(ContainerRequestContext.class)
                     .proxy(false)
-                    .in(RequestScoped.class);
+                    .in(RequestScoped.class)
+                    .id(3102);
 
             // Bind proxiable HttpHeaders, Request and ContainerRequestContext injection injection points
             bindFactory(ContainerRequestFactory.class)
                     .to(HttpHeaders.class).to(Request.class).to(PropertiesDelegate.class)
                     .proxy(true).proxyForSameScope(false)
-                    .in(RequestScoped.class);
+                    .in(RequestScoped.class)
+                    .id(3103);
 
             // Bind proxiable UriInfo, ExtendedUriInfo and ResourceInfo injection points
             bindFactory(UriRoutingContextFactory.class)
                     .to(UriInfo.class).to(ExtendedUriInfo.class).to(ResourceInfo.class)
                     .proxy(true).proxyForSameScope(false)
-                    .in(RequestScoped.class);
+                    .in(RequestScoped.class)
+                    .id(3104);
 
             // Bind proxiable SecurityContext injection point.
             // NOTE:
@@ -152,20 +155,23 @@
             bind(SecurityContextInjectee.class)
                     .to(SecurityContext.class)
                     .proxy(true).proxyForSameScope(false)
-                    .in(RequestScoped.class);
+                    .in(RequestScoped.class)
+                    .id(3105);
 
             // Bind proxiable CloseableService injection point.
             bindFactory(CloseableServiceFactory.class)
                     .to(CloseableService.class)
                     .proxy(true).proxyForSameScope(false)
-                    .in(RequestScoped.class);
+                    .in(RequestScoped.class)
+                    .id(3106);
 
             // Bind proxiable AsyncContext and AsyncResponse injection points.
             // TODO maybe we can get rid of these completely? Or at least for AsyncContext?
             bindFactory(AsyncContextFactory.class)
                     .to(AsyncContext.class)
                     .to(AsyncResponse.class)
-                    .in(RequestScoped.class);
+                    .in(RequestScoped.class)
+                    .id(3107);
         }
     }
 }
diff --git a/core-server/src/main/resources/META-INF/services/org.glassfish.jersey.innate.BootstrapPreinitialization b/core-server/src/main/resources/META-INF/services/org.glassfish.jersey.innate.BootstrapPreinitialization
new file mode 100644
index 0000000..66f8ea4
--- /dev/null
+++ b/core-server/src/main/resources/META-INF/services/org.glassfish.jersey.innate.BootstrapPreinitialization
@@ -0,0 +1 @@
+org.glassfish.jersey.server.ServerBootstrapPreinitialization
\ No newline at end of file
diff --git a/incubator/cdi-inject-weld/pom.xml b/incubator/cdi-inject-weld/pom.xml
index f13b275..d077afb 100644
--- a/incubator/cdi-inject-weld/pom.xml
+++ b/incubator/cdi-inject-weld/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2017, 2023 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
@@ -94,6 +94,11 @@
             <artifactId>jakarta.el-api</artifactId>
             <scope>test</scope>
         </dependency>
+
+        <dependency>
+            <groupId>com.sun.xml.bind</groupId>
+            <artifactId>jaxb-osgi</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/ClassBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/ClassBean.java
index d7bfc8c..68a787e 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/ClassBean.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/ClassBean.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
@@ -28,6 +28,8 @@
 import jakarta.enterprise.inject.spi.InjectionTarget;
 import jakarta.ws.rs.RuntimeType;
 
+import org.glassfish.jersey.inject.weld.internal.inject.InitializableInstanceBinding;
+import org.glassfish.jersey.inject.weld.internal.injector.JerseyClientCreationalContext;
 import org.glassfish.jersey.inject.weld.internal.injector.JerseyInjectionTarget;
 import org.glassfish.jersey.internal.inject.ClassBinding;
 
@@ -60,7 +62,7 @@
  *
  * @author Petr Bouda
  */
-class ClassBean<T> extends JerseyBean<T> {
+public class ClassBean<T> extends JerseyBean<T> {
 
     private final ClassBinding<T> binding;
     private InjectionTarget<T> injectionTarget;
@@ -90,6 +92,12 @@
     @Override
     @SuppressWarnings("unchecked")
     public T create(CreationalContext<T> context) {
+//        ClassBinding<T> realBinding = (ClassBinding<T>) getBinding();
+//        if (JerseyClientCreationalContext.class.isInstance(context)) {
+//            realBinding = ((JerseyClientCreationalContext) context)
+//                  .getInjectionManager().getInjectionManagerBinding(realBinding);
+//        }
+//        T service = realBinding.getService();
         T instance = injectionTarget.produce(context);
         injectionTarget.inject(instance, context);
         injectionTarget.postConstruct(instance);
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableInstanceBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableInstanceBean.java
index cf0dd3d..5e1f7d5 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableInstanceBean.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableInstanceBean.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
@@ -22,8 +22,12 @@
 
 import org.glassfish.jersey.inject.weld.internal.inject.InitializableInstanceBinding;
 import org.glassfish.jersey.inject.weld.internal.injector.JerseyClientCreationalContext;
+import org.glassfish.jersey.inject.weld.internal.managed.CdiClientInjectionManager;
+import org.glassfish.jersey.inject.weld.internal.managed.ContextSafe;
+import org.glassfish.jersey.internal.inject.InjectionManager;
 
 import java.lang.annotation.Annotation;
+import java.util.Objects;
 
 /**
  * Instance bean to be created in the pre-initialization phase and initialized after Jersey is bootstrap.
@@ -52,6 +56,11 @@
         InitializableInstanceBinding<T> realBinding = (InitializableInstanceBinding<T>) getBinding();
         if (JerseyClientCreationalContext.class.isInstance(context)) {
             realBinding = ((JerseyClientCreationalContext) context).getInjectionManager().getInjectionManagerBinding(realBinding);
+        } else {
+            CdiClientInjectionManager locked = ContextSafe.get();
+            if (locked != null) {
+                realBinding = locked.getInjectionManagerBinding(realBinding);
+            }
         }
         T service = realBinding.getService();
         this.injectionTarget.inject(service, context);
@@ -75,6 +84,6 @@
 
     @Override
     public String toString() {
-        return "InitializableInstanceBean{" + getBeanClass() + "}";
+        return getBinding().toString();
     }
 }
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierInstanceBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierInstanceBean.java
index d42ca44..98fb63d 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierInstanceBean.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierInstanceBean.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
@@ -23,6 +23,8 @@
 import org.glassfish.jersey.inject.weld.internal.inject.InitializableSupplierInstanceBinding;
 import org.glassfish.jersey.inject.weld.internal.injector.JerseyClientCreationalContext;
 import org.glassfish.jersey.inject.weld.internal.injector.JerseyInjectionTarget;
+import org.glassfish.jersey.inject.weld.internal.managed.CdiClientInjectionManager;
+import org.glassfish.jersey.inject.weld.internal.managed.ContextSafe;
 import org.glassfish.jersey.inject.weld.internal.type.ParameterizedTypeImpl;
 import org.glassfish.jersey.internal.inject.DisposableSupplier;
 import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
@@ -101,6 +103,12 @@
             final JerseyClientCreationalContext jerseyContext = (JerseyClientCreationalContext) context;
             return jerseyContext.getInjectionManager().getInjectionManagerBinding(binding).getSupplier();
         } else {
+            CdiClientInjectionManager locked = ContextSafe.get();
+            if (locked != null) {
+                return locked
+                        .getInjectionManagerBinding((InitializableSupplierInstanceBinding<T>) getBinding())
+                        .getSupplier();
+            }
             return supplier;
         }
     }
@@ -115,4 +123,9 @@
     public Class<? extends Annotation> getScope() {
         return getBinding().getScope() == null ? Dependent.class : transformScope(getBinding().getScope());
     }
+
+    @Override
+    public String toString() {
+        return getBinding().toString();
+    }
 }
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierInstanceBeanBridge.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierInstanceBeanBridge.java
index 8f16719..773e779 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierInstanceBeanBridge.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/InitializableSupplierInstanceBeanBridge.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
@@ -21,7 +21,10 @@
 import jakarta.ws.rs.RuntimeType;
 
 import org.glassfish.jersey.inject.weld.internal.inject.InitializableSupplierInstanceBinding;
+import org.glassfish.jersey.inject.weld.internal.injector.JerseyClientCreationalContext;
 import org.glassfish.jersey.inject.weld.internal.injector.JerseyInjectionTarget;
+import org.glassfish.jersey.inject.weld.internal.managed.CdiClientInjectionManager;
+import org.glassfish.jersey.inject.weld.internal.managed.ContextSafe;
 import org.glassfish.jersey.internal.inject.DisposableSupplier;
 import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
 
@@ -83,7 +86,19 @@
 
     @Override
     public Object create(CreationalContext creationalContext) {
-        return supplier.get();
+        if (JerseyClientCreationalContext.class.isInstance(creationalContext)) {
+            final InitializableSupplierInstanceBinding binding = (InitializableSupplierInstanceBinding) getBinding();
+            final JerseyClientCreationalContext jerseyContext = (JerseyClientCreationalContext) creationalContext;
+            return jerseyContext.getInjectionManager().getInjectionManagerBinding(binding).getSupplier().get();
+        } else {
+            CdiClientInjectionManager locked = ContextSafe.get();
+            if (locked != null) {
+                return locked
+                        .getInjectionManagerBinding((InitializableSupplierInstanceBinding) getBinding())
+                        .getSupplier().get();
+            }
+            return supplier.get();
+        }
     }
 
     @Override
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/JerseyBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/JerseyBean.java
index 66594f9..fa19e81 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/JerseyBean.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/JerseyBean.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2021, 2023 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
@@ -21,6 +21,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.Objects;
 import java.util.Set;
 
 import jakarta.enterprise.context.Dependent;
@@ -161,7 +162,7 @@
             return binding.getRank();
         }
 
-        int defaultValue = 1;
+        int defaultValue = 0;
         Class<T> type = binding.getImplementationType();
         if (type != null) {
             return JerseyPriorities.getPriorityValue(type, defaultValue);
@@ -189,4 +190,17 @@
     public String getContractsAsString() {
         return Arrays.toString(binding.getContracts().toArray());
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        JerseyBean<?> that = (JerseyBean<?>) o;
+        return Objects.equals(binding, that.binding) && runtimeType == that.runtimeType;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(binding, runtimeType);
+    }
 }
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/SupplierClassBean.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/SupplierClassBean.java
index ef4d154..0f71404 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/SupplierClassBean.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/bean/SupplierClassBean.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
@@ -63,7 +63,7 @@
  *
  * @author Petr Bouda
  */
-class SupplierClassBean<T> extends JerseyBean<Supplier<T>> {
+public class SupplierClassBean<T> extends JerseyBean<Supplier<T>> {
 
     private final Set<Type> contracts = new HashSet<>();
     private final Class<? extends Supplier<T>> supplierClass;
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/data/BindingBeanPair.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/data/BindingBeanPair.java
index 1d0b2c9..c8d66b7 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/data/BindingBeanPair.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/data/BindingBeanPair.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
@@ -18,7 +18,7 @@
 import org.glassfish.jersey.inject.weld.internal.bean.JerseyBean;
 import org.glassfish.jersey.internal.inject.Binding;
 
-import java.util.LinkedList;
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -26,7 +26,7 @@
  */
 public class BindingBeanPair {
     private final Binding binding;
-    private final List<JerseyBean> beans = new LinkedList<JerseyBean>();
+    private final List<JerseyBean> beans = new ArrayList<JerseyBean>();
 
     public BindingBeanPair(Binding binding, JerseyBean... beans) {
         this.binding = binding;
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/ClassListBinding.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/ClassListBinding.java
new file mode 100644
index 0000000..e9faa98
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/ClassListBinding.java
@@ -0,0 +1,65 @@
+/*
+ * 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.inject;
+
+import org.glassfish.jersey.internal.inject.ClassBinding;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.ServiceHolder;
+import org.glassfish.jersey.internal.inject.ServiceHolderImpl;
+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 java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class ClassListBinding<T> {
+    private final Class<T> serviceType;
+    private final List<ClassBinding<T>> services = new ArrayList<>();
+    private final InjectionManager injectionManager;
+    private final LazyValue<List<ServiceHolder<T>>> instances;
+
+    public ClassListBinding(Class<T> serviceType, InjectionManager injectionManager) {
+        this.serviceType = serviceType;
+        this.injectionManager = injectionManager;
+        instances = Values.lazy((Value<List<ServiceHolder<T>>>) () -> services.stream()
+                .map(binding -> new ServiceHolderImpl(
+                        create(binding),
+                        binding.getService().getClass(),
+                        binding.getContracts(),
+                        binding.getRank() == null ? 0 : binding.getRank()))
+                .map(sh -> (ServiceHolder<T>) sh).collect(Collectors.toList()));
+    }
+
+    private T create(ClassBinding<T> binding) {
+        T t = injectionManager.create(binding.getService());
+        injectionManager.inject(t);
+        return t;
+    }
+
+    public void init(ClassBinding<?> service) {
+        services.add((ClassBinding<T>) service);
+    }
+
+    public List<T> getServices() {
+        return instances.get().stream().map(sh -> ((ServiceHolder<T>) sh).getInstance()).collect(Collectors.toList());
+    }
+
+    public List<ServiceHolder<T>> getServiceHolders() {
+        return instances.get();
+    }}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InitializableBinding.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InitializableBinding.java
new file mode 100644
index 0000000..d464483
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InitializableBinding.java
@@ -0,0 +1,26 @@
+/*
+ * 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.inject;
+
+import jakarta.ws.rs.RuntimeType;
+
+public abstract class InitializableBinding<T, U extends MatchableBinding> extends MatchableBinding<T, U> {
+
+    public abstract boolean isInit();
+
+    public abstract RuntimeType getRuntimeType();
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InitializableInstanceBinding.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InitializableInstanceBinding.java
index 61b4a2c..0e41170 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InitializableInstanceBinding.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InitializableInstanceBinding.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
@@ -18,13 +18,13 @@
 
 import org.glassfish.jersey.internal.inject.AliasBinding;
 import org.glassfish.jersey.internal.inject.Binding;
-import org.glassfish.jersey.internal.inject.Bindings;
 import org.glassfish.jersey.internal.inject.InstanceBinding;
 
+import jakarta.ws.rs.RuntimeType;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import java.util.Arrays;
-import java.util.Collections;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -34,19 +34,21 @@
  *
  * @param <T> Type of the service described by this injection binding.
  */
-public class InitializableInstanceBinding<T> extends MatchableBinding<T, InitializableInstanceBinding<T>> implements Cloneable {
+public class InitializableInstanceBinding<T> extends InitializableBinding<T, InitializableInstanceBinding<T>>
+        implements Cloneable {
 
     protected T service;
-    private AtomicBoolean isInit = new AtomicBoolean(false);
+    private final AtomicBoolean isInit = new AtomicBoolean(false);
     private Class<T> implementationType;
+    private final RuntimeType runtimeType;
 
     /**
      * Creates a service as an instance.
      *
      * @param service service's instance.
      */
-    protected InitializableInstanceBinding(T service) {
-        this(service, null);
+    protected InitializableInstanceBinding(T service, RuntimeType runtimeType) {
+        this(service, null, runtimeType);
     }
 
     /**
@@ -55,12 +57,13 @@
      * @param service      service's instance.
      * @param contractType service's contractType.
      */
-    private InitializableInstanceBinding(T service, Type contractType) {
+    private InitializableInstanceBinding(T service, Type contractType, RuntimeType runtimeType) {
         this.service = service;
         this.implementationType = service == null ? null : (Class<T>) service.getClass();
         if (contractType != null) {
             this.to(contractType);
         }
+        this.runtimeType = runtimeType;
     }
 
     /**
@@ -81,6 +84,7 @@
      *
      * @return service's type.
      */
+    @Override
     public Class<T> getImplementationType() {
         return implementationType;
     }
@@ -98,6 +102,12 @@
         return isInit.get();
     }
 
+    @Override
+    public RuntimeType getRuntimeType() {
+        return runtimeType;
+    }
+
+    @Override
     public Matching<InitializableInstanceBinding<T>> matches(Binding other) {
         return super.matches(other);
     }
@@ -107,8 +117,8 @@
         throw new RuntimeException(new CloneNotSupportedException());
     }
 
-    public static <T> InitializableInstanceBinding<T> from(InstanceBinding<T> instanceBinding) {
-        return new InitializableWrappingInstanceBinding(instanceBinding);
+    public static <T> InitializableInstanceBinding<T> from(InstanceBinding<T> instanceBinding, RuntimeType runtimeType) {
+        return new InitializableWrappingInstanceBinding(instanceBinding, runtimeType);
     }
 
     @Override
@@ -116,42 +126,79 @@
         return MatchLevel.IMPLEMENTATION;
     }
 
+    @Override
+    public Matching<MatchableBinding> matching(Binding other) {
+        return visitor.matches((InitializableInstanceBinding) this, other);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(service, implementationType);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        InitializableInstanceBinding<?> that = (InitializableInstanceBinding<?>) o;
+        return Objects.equals(service, that.service)
+                && Objects.equals(implementationType, that.implementationType);
+    }
+
     private static class InitializableWrappingInstanceBinding<T> extends InitializableInstanceBinding<T> {
         private final InstanceBinding<T> wrapped;
-        public InitializableWrappingInstanceBinding(InstanceBinding<T> binding) {
-            super(binding.getService());
+        public InitializableWrappingInstanceBinding(InstanceBinding<T> binding, RuntimeType runtimeType) {
+            super(binding.getService(), runtimeType);
             wrapped = binding;
+            postCreate();
         }
 
-        private InitializableWrappingInstanceBinding(InitializableWrappingInstanceBinding<T> binding) {
-            super(binding.service);
+        private InitializableWrappingInstanceBinding(InitializableWrappingInstanceBinding<T> binding, RuntimeType runtimeType) {
+            super(binding.service, runtimeType);
             wrapped = binding.wrapped;
+            postCreate();
         }
 
-        @Override
-        public Class<T> getImplementationType() {
-            return super.getImplementationType();
+        private void postCreate() {
+            wrapped.getContracts().forEach(c -> this.to(c));
+            if (wrapped.getRank() != null) {
+                this.ranked(wrapped.getRank());
+            }
+            this.named(wrapped.getName());
+            this.id(wrapped.getId());
+            this.in(wrapped.getScope());
+            this.forClient(wrapped.isForClient());
         }
 
-        @Override
-        public T getService() {
-            return super.getService();
-        }
+//        @Override
+//        public Class<T> getImplementationType() {
+//            return super.getImplementationType();
+//        }
+//
+//        @Override
+//        public T getService() {
+//            return super.getService();
+//        }
+//
+//        @Override
+//        public RuntimeType getRuntime() {
+//            return super.getRuntime();
+//        }
 
-        @Override
-        public Class<? extends Annotation> getScope() {
-            return wrapped.getScope();
-        }
-
-        @Override
-        public Set<Type> getContracts() {
-            return wrapped.getContracts();
-        }
-
-        @Override
-        public Integer getRank() {
-            return wrapped.getRank();
-        }
+//        @Override
+//        public Class<? extends Annotation> getScope() {
+//            return wrapped.getScope();
+//        }
+//
+//        @Override
+//        public Set<Type> getContracts() {
+//            return wrapped.getContracts();
+//        }
+//
+//        @Override
+//        public Integer getRank() {
+//            return wrapped.getRank();
+//        }
 
         @Override
         public Set<AliasBinding> getAliases() {
@@ -175,12 +222,22 @@
 
         @Override
         public String toString() {
-            return "InitializableWrappingInstanceBinding(" + wrapped.getService().getClass() + ")";
+            return wrapped.toString();
         }
 
+//        @Override
+//        public boolean isForClient() {
+//            return wrapped.isForClient();
+//        }
+//
+//        @Override
+//        public long getId() {
+//            return wrapped.getId();
+//        }
+
         @Override
         public InitializableWrappingInstanceBinding clone() {
-            return new InitializableWrappingInstanceBinding(this);
+            return new InitializableWrappingInstanceBinding(this, this.getRuntimeType());
         }
     }
 }
\ No newline at end of file
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InitializableSupplierInstanceBinding.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InitializableSupplierInstanceBinding.java
index d99bf59..c4421f7 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InitializableSupplierInstanceBinding.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InitializableSupplierInstanceBinding.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
@@ -21,10 +21,12 @@
 import org.glassfish.jersey.internal.inject.DisposableSupplier;
 import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
 
+import jakarta.ws.rs.RuntimeType;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
 import java.util.function.Supplier;
 
 /**
@@ -32,20 +34,23 @@
  * @param <T> Type of the supplied service described by this injection binding.
  */
 public class InitializableSupplierInstanceBinding<T>
-        extends MatchableBinding<Supplier<T>, InitializableSupplierInstanceBinding<T>>
+        extends InitializableBinding<Supplier<T>, InitializableSupplierInstanceBinding<T>>
         implements Cloneable {
 
     private final InitializableSupplier<T> supplier;
+    private final RuntimeType runtimeType;
 
     /**
      * Creates a supplier as an instance.
      *
-     * @param supplier service's instance.
+     * @param supplier    service's instance.
+     * @param runtimeType
      */
-    public InitializableSupplierInstanceBinding(Supplier<T> supplier) {
+    public InitializableSupplierInstanceBinding(Supplier<T> supplier, RuntimeType runtimeType) {
         this.supplier = DisposableSupplier.class.isInstance(supplier)
                 ? new InitializableDisposableSupplier<T>((DisposableSupplier<T>) supplier)
                 : new InitializableSupplier<T>(supplier);
+        this.runtimeType = runtimeType;
         if ("EmptyReferenceFactory".equals(supplier.getClass().getSimpleName())) {
             this.supplier.init(supplier);
             this.supplier.isReferencingFactory = true;
@@ -65,6 +70,11 @@
         return supplier.init.get();
     }
 
+    @Override
+    public RuntimeType getRuntimeType() {
+        return runtimeType;
+    }
+
     /**
      * Gets supplier's instance.
      *
@@ -81,8 +91,8 @@
         return supplier.originalSupplier;
     }
 
-    public static <T> InitializableSupplierInstanceBinding<T> from(SupplierInstanceBinding<T> binding) {
-        return new InitializableSupplierWrappingInstanceBinding(binding);
+    public static <T> InitializableSupplierInstanceBinding<T> from(SupplierInstanceBinding<T> binding, RuntimeType runtimeType) {
+        return new InitializableSupplierWrappingInstanceBinding(binding, runtimeType);
     }
 
     @Override
@@ -100,6 +110,9 @@
 
     private Matching<InitializableSupplierInstanceBinding<T>> matches(
             Class<?> originalSupplierClass, Class<?> otherSupplierClass, Binding other) {
+        if (getId() != 0) {
+            return matchesById(other);
+        }
         final boolean matchesService = originalSupplierClass.equals(otherSupplierClass);
         final Matching matching = matchesContracts(other);
         if (matching.matchLevel == MatchLevel.FULL_CONTRACT && matchesService) {
@@ -113,6 +126,11 @@
         return MatchLevel.SUPPLIER;
     }
 
+    @Override
+    public Matching<MatchableBinding> matching(Binding other) {
+        return visitor.matches((InitializableSupplierInstanceBinding) this, other);
+    }
+
     private static class InitializableDisposableSupplier<T> extends InitializableSupplier<T> implements DisposableSupplier<T> {
         private InitializableDisposableSupplier(DisposableSupplier<T> originalSupplier) {
             super(originalSupplier);
@@ -120,7 +138,9 @@
 
         @Override
         public void dispose(T instance) {
-            ((DisposableSupplier) supplier).dispose(instance);
+            if (isInit()) {
+                ((DisposableSupplier) supplier).dispose(instance);
+            }
         }
     }
 
@@ -158,40 +178,59 @@
 
     private static class InitializableSupplierWrappingInstanceBinding<T> extends InitializableSupplierInstanceBinding<T> {
         private final SupplierInstanceBinding wrapped;
-        public InitializableSupplierWrappingInstanceBinding(SupplierInstanceBinding binding) {
-            super(binding.getSupplier());
+        InitializableSupplierWrappingInstanceBinding(SupplierInstanceBinding binding, RuntimeType runtimeType) {
+            super(binding.getSupplier(), runtimeType);
             wrapped = binding;
+            postCreate();
         }
 
-        private InitializableSupplierWrappingInstanceBinding(InitializableSupplierWrappingInstanceBinding binding) {
-            super(binding.getOriginalSupplier());
+        private InitializableSupplierWrappingInstanceBinding(InitializableSupplierWrappingInstanceBinding binding,
+                                                             RuntimeType runtimeType) {
+            super(binding.getOriginalSupplier(), runtimeType);
             wrapped = binding.wrapped;
+            postCreate();
         }
 
-        @Override
-        public Class getImplementationType() {
-            return super.getImplementationType();
+        private void postCreate() {
+            wrapped.getContracts().forEach(c -> this.to((Type) c));
+            if (wrapped.getRank() != null) {
+                this.ranked(wrapped.getRank());
+            }
+            this.named(wrapped.getName());
+            this.id(wrapped.getId());
+            this.in(wrapped.getScope());
+            this.forClient(wrapped.isForClient());
         }
 
-        @Override
-        public Supplier getSupplier() {
-            return super.getSupplier();
-        }
+//        @Override
+//        public Class getImplementationType() {
+//            return super.getImplementationType();
+//        }
+//
+//        @Override
+//        public Supplier getSupplier() {
+//            return super.getSupplier();
+//        }
+//
+//        @Override
+//        public RuntimeType getRuntime() {
+//            return super.getRuntime();
+//        }
 
-        @Override
-        public Class<? extends Annotation> getScope() {
-            return wrapped.getScope();
-        }
-
-        @Override
-        public Set<Type> getContracts() {
-            return wrapped.getContracts();
-        }
-
-        @Override
-        public Integer getRank() {
-            return wrapped.getRank();
-        }
+//        @Override
+//        public Class<? extends Annotation> getScope() {
+//            return wrapped.getScope();
+//        }
+//
+//        @Override
+//        public Set<Type> getContracts() {
+//            return wrapped.getContracts();
+//        }
+//
+//        @Override
+//        public Integer getRank() {
+//            return wrapped.getRank();
+//        }
 
         @Override
         public Set<AliasBinding> getAliases() {
@@ -209,19 +248,35 @@
         }
 
         @Override
-        public String getName() {
-            return wrapped.getName();
+        public String toString() {
+            return wrapped.toString();
         }
 
+
+//        @Override
+//        public String getName() {
+//            return wrapped.getName();
+//        }
+
+//        @Override
+//        public long getId() {
+//            return wrapped.getId();
+//        }
+//
+//        @Override
+//        public boolean isForClient() {
+//            return wrapped.isForClient();
+//        }
+
         @Override
         public InitializableSupplierWrappingInstanceBinding clone() {
-            return new InitializableSupplierWrappingInstanceBinding(this);
+            return new InitializableSupplierWrappingInstanceBinding(this, getRuntimeType());
         }
 
-        @Override
-        public String toString() {
-            return "InitializableSupplierWrappingInstanceBinding(" +  wrapped.getSupplier() + ")";
-        }
+//        @Override
+//        public String toString() {
+//            return "InitializableSupplierWrappingInstanceBinding(" +  wrapped.getSupplier() + ")";
+//        }
     }
 
 }
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InstanceListBinding.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InstanceListBinding.java
new file mode 100644
index 0000000..201d71a
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/InstanceListBinding.java
@@ -0,0 +1,67 @@
+/*
+ * 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.inject;
+
+import org.glassfish.jersey.internal.inject.Binding;
+import org.glassfish.jersey.internal.inject.InstanceBinding;
+import org.glassfish.jersey.internal.inject.ServiceHolder;
+import org.glassfish.jersey.internal.inject.ServiceHolderImpl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class InstanceListBinding<T> extends MatchableBinding<List<T>, InitializableInstanceBinding<List<T>>>
+        implements Cloneable {
+
+    private final Class<T> serviceType;
+    private final List<InstanceBinding<T>> services = new ArrayList<>();
+
+    /**
+     * Creates a service as an instance.
+     *
+     * @param serviceType service's type.
+     */
+    public InstanceListBinding(Class<T> serviceType) {
+        this.serviceType = serviceType;
+    }
+
+    @Override
+    protected MatchLevel bestMatchLevel() {
+        return MatchLevel.NEVER;
+    }
+
+    @Override
+    public Matching<MatchableBinding> matching(Binding other) {
+        return Matching.noneMatching();
+    }
+
+    public void init(InstanceBinding<?> service) {
+        services.add((InstanceBinding<T>) service);
+    }
+
+    public List<T> getServices() {
+        return services.stream().map(binding -> binding.getService()).collect(Collectors.toList());
+    }
+
+    public List<ServiceHolder<T>> getServiceHolders() {
+        return services.stream().map(binding ->
+                new ServiceHolderImpl<T>(binding.getService(), serviceType, binding.getContracts(),
+                        binding.getRank() == null ? 0 : binding.getRank()))
+                .collect(Collectors.toList());
+    }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/MatchableBinding.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/MatchableBinding.java
index e6cd0bd..2fc71d3 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/MatchableBinding.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/inject/MatchableBinding.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
@@ -17,6 +17,8 @@
 package org.glassfish.jersey.inject.weld.internal.inject;
 
 import org.glassfish.jersey.internal.inject.Binding;
+import org.glassfish.jersey.internal.inject.InstanceBinding;
+import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
 
 import java.lang.reflect.Type;
 import java.util.Set;
@@ -29,9 +31,20 @@
  */
 public abstract class MatchableBinding<T, D extends MatchableBinding> extends Binding<T, D> {
 
+    protected static MatchingVisitor visitor = new MatchingVisitor();
     protected abstract MatchLevel bestMatchLevel();
 
+    /**
+     * Visitor version of matches
+     * @param other
+     * @return
+     */
+    public abstract Matching<MatchableBinding> matching(Binding other);
+
     protected Matching<D> matches(Binding<?, ?> other) {
+        if (getId() != 0) {
+            return matchesById(other);
+        }
         final Matching<D> matching = matchesContracts(other);
         if (matching.matchLevel == MatchLevel.FULL_CONTRACT) {
             if (getImplementationType().equals(other.getImplementationType())) {
@@ -41,6 +54,14 @@
         return matching;
     }
 
+    protected Matching matchesById(Binding<?, ?> other) {
+        if (getId() == other.getId()) {
+            return new Matching<>((D) this, MatchLevel.FULL_CONTRACT);
+        } else {
+            return Matching.noneMatching();
+        }
+    }
+
     /**
      * Return a Matching object that represents comparison between contracts of this binding and a given binding.
      * The result contains a reference to this binding.
@@ -113,6 +134,10 @@
         public D getBinding() {
             return binding;
         }
+
+        public Matching<D> clone() {
+            return new Matching<>(binding, matchLevel);
+        }
     }
 
     /**
@@ -123,7 +148,8 @@
         PARTIAL_CONTRACT(1),
         FULL_CONTRACT(2),
         IMPLEMENTATION(3),
-        SUPPLIER(4);
+        SUPPLIER(4),
+        NEVER(5);
 
         private final int level;
 
@@ -131,5 +157,21 @@
             this.level = level;
         }
     }
+
+    protected static class MatchingVisitor<D extends MatchableBinding<?, D>> {
+        public MatchableBinding.Matching<InitializableInstanceBinding<D>> matches(
+                InitializableInstanceBinding<D> binding, Binding other) {
+            return binding.matches((InstanceBinding) other);
+        }
+
+        public MatchableBinding.Matching<InitializableSupplierInstanceBinding<D>> matches(
+                InitializableSupplierInstanceBinding<D> binding, Binding other) {
+            return binding.matches((SupplierInstanceBinding<D>) other);
+        }
+
+        public Matching<MatchableBinding<?, D>> matches(MatchableBinding<?, D> binding, Binding other) {
+            throw new IllegalStateException("Unexpected");
+        }
+    }
 }
 
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyInjectionTarget.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyInjectionTarget.java
index b64513b..35e2d42 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyInjectionTarget.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyInjectionTarget.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
@@ -62,7 +62,7 @@
  * instances. {@code Delegate} is a original {@code InjectionTarget} which is able to inject other fields/parameters which
  * are managed by CDI.
  * <p>
- * Implementation is also able create with custom {@code jerseyConstructor} if it is provided. This functionality allows override
+ * Implementation is also able to create with custom {@code jerseyConstructor} if it is provided. This functionality allows override
  * default instantiator and use the Jersey-specific one.
  */
 public class JerseyInjectionTarget<T> extends BasicInjectionTarget<T> {
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyTwofoldInstantiator.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyTwofoldInstantiator.java
index 01e96c0..ee09f29 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyTwofoldInstantiator.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/injector/JerseyTwofoldInstantiator.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
@@ -17,6 +17,7 @@
 package org.glassfish.jersey.inject.weld.internal.injector;
 
 import jakarta.enterprise.context.spi.CreationalContext;
+
 import org.jboss.weld.injection.ConstructorInjectionPoint;
 import org.jboss.weld.injection.producer.AbstractInstantiator;
 import org.jboss.weld.manager.BeanManagerImpl;
@@ -59,10 +60,10 @@
     @Override
     public T newInstance(CreationalContext<T> ctx, BeanManagerImpl manager) {
         final ConstructorInjectionPoint<T> cip =
-                optionalConstructorInjectionPoint == null || !JerseyClientCreationalContext.class.isInstance(ctx)
+                !hasOptionalConstructorInjectionPoint() || !JerseyClientCreationalContext.class.isInstance(ctx)
                 ? primaryInstantiator.getConstructorInjectionPoint()
                 : optionalConstructorInjectionPoint;
-        return cip.newInstance(manager, ctx);
+            return cip.newInstance(manager, ctx);
     }
 
     /**
@@ -72,4 +73,8 @@
     public void setOptionalConstructorInjectionPoint(ConstructorInjectionPoint<T> optionalConstructorInjectionPoint) {
         this.optionalConstructorInjectionPoint = optionalConstructorInjectionPoint;
     }
+
+    public boolean hasOptionalConstructorInjectionPoint() {
+        return optionalConstructorInjectionPoint != null;
+    }
 }
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..7a3b0af 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
@@ -20,6 +20,7 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Type;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -29,6 +30,8 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
@@ -104,24 +107,35 @@
  */
 class BinderRegisterExtension implements Extension {
 
-    private AtomicBoolean registrationDone = new AtomicBoolean(false);
+    private final AtomicBoolean registrationDone = new AtomicBoolean(false);
     private Supplier<BeanManager> beanManagerSupplier;
-    private Ref<InjectionManager> serverInjectionManager = Refs.emptyRef();
+    private final Ref<InjectionManager> serverInjectionManager = Refs.emptyRef();
 
-    private BootstrapInjectionManager clientBootstrapInjectionManager = new BootstrapInjectionManager(RuntimeType.CLIENT);
-    private WrappingInjectionManager serverBootstrapInjectionManager = new WrappingInjectionManager()
+    private final BootstrapInjectionManager clientBootstrapInjectionManager = new BootstrapInjectionManager(RuntimeType.CLIENT);
+    private final WrappingInjectionManager serverBootstrapInjectionManager = new WrappingInjectionManager()
             .setInjectionManager(new BootstrapInjectionManager(RuntimeType.SERVER));
-    private BootstrapBag bootstrapBag = new BootstrapBag();
+    private final BootstrapBag bootstrapBag = new BootstrapBag();
 
-    private final CachingBinder clientBindings = new CachingBinder(serverInjectionManager);
-    private final CachingBinder serverBindings = new CachingBinder(serverInjectionManager) {
+    private final List<InitializableInstanceBinding> skippedClientInstanceBindings = new ArrayList<>();
+    private final List<InitializableSupplierInstanceBinding> skippedClientSupplierInstanceBindings = new ArrayList<>();
+
+    private final CachingBinder clientBindings = new CachingBinder(serverInjectionManager, RuntimeType.CLIENT) {
+//        @Override
+//        protected void configure() {
+//            bind(InitializableInstanceBinding.from(
+//            Bindings.service(clientBootstrapInjectionManager).to(InjectionManager.class)));
+//        }
+    };
+    private final CachingBinder serverBindings = new CachingBinder(serverInjectionManager, RuntimeType.SERVER) {
         @Override
         protected void configure() {
             install(new ContextInjectionResolverImpl.Binder(beanManagerSupplier));
-            bind(InitializableInstanceBinding.from(Bindings.service(serverInjectionManager.get()).to(InjectionManager.class)));
+            bind(InitializableInstanceBinding.from(
+                    Bindings.service(serverInjectionManager.get()).to(InjectionManager.class),
+                    RuntimeType.SERVER));
         }
     };
-    private final CachingBinder annotatedBeansBinder = new CachingBinder(serverInjectionManager);
+    private final CachingBinder annotatedBeansBinder = new CachingBinder(serverInjectionManager, null);
     private final MergedBindings mergedBindings = new MergedBindings(serverBindings, clientBindings);
 
     private final List<InitializableInstanceBinding> initializableInstanceBindings = new LinkedList<>();
@@ -274,15 +288,15 @@
      *
      * @param abd         {@code AfterBeanDiscovery} event.
      * @param beanManager current {@code BeanManager}.
-     * @link ProcessAnnotatedType} bootstrap phase.
+     * @see ProcessAnnotatedType bootstrap phase.
      */
     void registerBeans(@Observes AfterBeanDiscovery abd, BeanManager beanManager) {
-        serverInjectionManager.set(new CdiInjectionManager(beanManager, mergedBindings));
+        serverInjectionManager.set(new CdiInjectionManager(beanManager, mergedBindings, RuntimeType.SERVER));
 
         beanManagerSupplier = () -> beanManager; // set bean manager supplier to be called by bindings#configure
         CdiInjectionManagerFactoryBase.setBeanManager(beanManager);
 
-        registerApplicationHandler(beanManager);
+//        registerApplicationHandler(beanManager);
 
         registrationDone.set(true); //
 
@@ -316,16 +330,32 @@
         final Collection<Binding> bindings = binder.getBindings();
         binder.setReadOnly();
 
+        //check unique id;
+        TreeMap<Long, Binding> treeMap = new TreeMap<>();
+        for (Binding binding : bindings) {
+            if (binding.getId() != 0 && !binding.isForClient()) {
+                if (treeMap.containsKey(binding.getId())) {
+                    throw new IllegalStateException("Id " + binding.getId() + " already exists:" + treeMap.get(binding.getId()));
+                }
+                treeMap.put(binding.getId(), binding);
+            }
+        }
+
         allBindingsLabel:
         for (Binding binding : bindings) {
             if (ClassBinding.class.isAssignableFrom(binding.getClass())) {
                 if (RuntimeType.CLIENT == runtimeType) {
                     for (Type contract : ((ClassBinding<?>) binding).getContracts()) {
-                        final List<BindingBeanPair> preregistered = classBindings.get(contract);
-                        if (preregistered != null && preregistered.size() == 1) {
-                            BeanHelper.updateBean(
-                                    (ClassBinding<?>) binding, preregistered.get(0), injectionResolvers, beanManager);
-                            continue allBindingsLabel;
+                        List<BindingBeanPair> preregistered = classBindings.get(contract);
+                        if (preregistered != null) {
+                            preregistered = preregistered.stream()
+                                    .filter(pair -> pair.getBeans().get(0).getRutimeType() == RuntimeType.SERVER)
+                                    .collect(Collectors.toList());
+                            if (preregistered.size() == 1 || binding.isForClient()) {
+                                BeanHelper.updateBean(
+                                        (ClassBinding<?>) binding, preregistered.get(0), injectionResolvers, beanManager);
+                                continue allBindingsLabel;
+                            }
                         }
                     }
                 }
@@ -337,11 +367,16 @@
             } else if (SupplierClassBinding.class.isAssignableFrom(binding.getClass())) {
                 if (RuntimeType.CLIENT == runtimeType) {
                     for (Type contract : ((SupplierClassBinding<?>) binding).getContracts()) {
-                        final List<BindingBeanPair> preregistered = supplierClassBindings.get(contract);
-                        if (preregistered != null && preregistered.size() == 1) {
-                            BeanHelper.updateSupplierBean(
-                                    (SupplierClassBinding<?>) binding, preregistered.get(0), injectionResolvers, beanManager);
-                            continue allBindingsLabel;
+                        List<BindingBeanPair> preregistered = supplierClassBindings.get(contract);
+                        if (preregistered != null) {
+                            preregistered = preregistered.stream()
+                                    .filter(pair -> pair.getBeans().get(0).getRutimeType() == RuntimeType.SERVER)
+                                    .collect(Collectors.toList());
+                            if (preregistered.size() == 1 || binding.isForClient()) {
+                                BeanHelper.updateSupplierBean(
+                                        (SupplierClassBinding<?>) binding, preregistered.get(0), injectionResolvers, beanManager);
+                                continue allBindingsLabel;
+                            }
                         }
                     }
                 }
@@ -351,17 +386,29 @@
                     supplierClassBindings.add(contract, pair);
                 }
             } else if (InitializableInstanceBinding.class.isAssignableFrom(binding.getClass())) {
-                if (RuntimeType.SERVER == runtimeType
+/*
+ * We do want to register beans such as Configuration just once. There are two of them, one for client and for a server.
+ * But having two of them would fail Weld Validation -> Weld would not know which one to @Inject
+ * The solution is to have JerseyTwoFoldInstantiator that creates a client bean for a client and a server bean for the server.
+ *
+ * But also we do not want to skip registering beans on client that are not in server
+ * or there are multiple of them of the same contract.
+ */
+                if (RuntimeType.SERVER == runtimeType || !binding.isForClient()
                         || !matchInitializableInstanceBinding((InitializableInstanceBinding<?>) binding)) {
                     initializableInstanceBindings.add((InitializableInstanceBinding<?>) binding);
                     BeanHelper.registerBean(
                             runtimeType, (InitializableInstanceBinding<?>) binding, abd, injectionResolvers, beanManager);
+                } else {
+                    skippedClientInstanceBindings.add((InitializableInstanceBinding) binding);
                 }
             } else if (InitializableSupplierInstanceBinding.class.isInstance(binding)) {
-                if (RuntimeType.SERVER == runtimeType
+                if (RuntimeType.SERVER == runtimeType || !binding.isForClient()
                         || !matchInitializableSupplierInstanceBinding((InitializableSupplierInstanceBinding) binding)) {
                     initializableSupplierInstanceBindings.add((InitializableSupplierInstanceBinding) binding);
                     BeanHelper.registerSupplier(runtimeType, (InitializableSupplierInstanceBinding<?>) binding, abd, beanManager);
+                } else {
+                    skippedClientSupplierInstanceBindings.add((InitializableSupplierInstanceBinding) binding);
                 }
             }
         }
@@ -525,21 +572,21 @@
 
 
     /** To be used by the tests only */
-    public void register(BeforeBeanDiscovery beforeBeanDiscovery, Binding binding) {
+    void register(BeforeBeanDiscovery beforeBeanDiscovery, Binding binding) {
         register(RuntimeType.SERVER, binding);
     }
 
     /** To be used by the tests only */
-    public void register(BeforeBeanDiscovery beforeBeanDiscovery, Iterable<Binding> bindings) {
+    void register(BeforeBeanDiscovery beforeBeanDiscovery, Iterable<Binding> bindings) {
         register(RuntimeType.SERVER, bindings);
     }
 
     private void register(RuntimeType runtimeType, Binding binding) {
         final AbstractBinder bindings = runtimeType == RuntimeType.CLIENT ? clientBindings : serverBindings;
         if (InstanceBinding.class.isInstance(binding)) {
-            bindings.bind(InitializableInstanceBinding.from((InstanceBinding) binding));
+            bindings.bind(InitializableInstanceBinding.from((InstanceBinding) binding, runtimeType));
         } else if (SupplierInstanceBinding.class.isInstance(binding)) {
-            bindings.bind(InitializableSupplierInstanceBinding.from((SupplierInstanceBinding) binding));
+            bindings.bind(InitializableSupplierInstanceBinding.from((SupplierInstanceBinding) binding, runtimeType));
         } else {
             bindings.bind(binding);
         }
@@ -556,10 +603,28 @@
         for (BootstrapPreinitialization registrar : ServiceFinder.find(BootstrapPreinitialization.class)) {
             registrars.add(registrar);
         }
+
+        final List<org.glassfish.jersey.innate.BootstrapPreinitialization> preregistrars = new LinkedList<>();
+        for (org.glassfish.jersey.innate.BootstrapPreinitialization registrar
+                : ServiceFinder.find(org.glassfish.jersey.innate.BootstrapPreinitialization.class)) {
+            preregistrars.add(registrar);
+        }
+
+        for (org.glassfish.jersey.innate.BootstrapPreinitialization registrar
+                : ServiceFinder.find(org.glassfish.jersey.innate.BootstrapPreinitialization.class)) {
+            //registrars.add(registrar);
+            registrar.preregister(RuntimeType.SERVER, serverBootstrapInjectionManager);
+        }
+
         for (BootstrapPreinitialization registrar : registrars) {
             registrar.register(RuntimeType.SERVER, serverBindings);
         }
 
+        for (org.glassfish.jersey.innate.BootstrapPreinitialization registrar
+                : ServiceFinder.find(org.glassfish.jersey.innate.BootstrapPreinitialization.class)) {
+            registrar.preregister(RuntimeType.CLIENT, clientBootstrapInjectionManager);
+        }
+
         for (BootstrapPreinitialization registrar : registrars) {
             registrar.register(RuntimeType.CLIENT, clientBindings);
         }
@@ -631,9 +696,6 @@
 
         @Override
         public <T> T createAndInitialize(Class<T> createMe) {
-            if (RequestScope.class == createMe) {
-                return (T) new CdiRequestScope();
-            }
             if (isNotJerseyInternal(createMe)) {
                 return null;
             }
@@ -667,7 +729,10 @@
 
         @Override
         public <T> T getInstance(Class<T> contractOrImpl) {
-            return createAndInitialize(contractOrImpl);
+            if (RequestScope.class == contractOrImpl) {
+                return (T) new CdiRequestScope();
+            }
+            return null; //createAndInitialize(contractOrImpl);
         }
 
         @Override
@@ -705,6 +770,11 @@
         public void preDestroy(Object preDestroyMe) {
             //noop
         }
+
+        @Override
+        public RuntimeType getRuntimeType() {
+            return runtimeType;
+        }
     }
 
     /**
@@ -716,9 +786,11 @@
         private final Ref<InjectionManager> injectionManager;
         private AbstractBinder temporaryBinder = new TemporaryBinder();
         private final Collection<Binding> bindings = new LinkedList<>();
+        private final RuntimeType runtimeType;
 
-        private CachingBinder(Ref<InjectionManager> injectionManager) {
+        private CachingBinder(Ref<InjectionManager> injectionManager, RuntimeType runtimeType) {
             this.injectionManager = injectionManager;
+            this.runtimeType = runtimeType;
         }
 
         @Override
@@ -786,9 +858,9 @@
                 final Collection<Binding> newBindings = temporaryBinder.getBindings();
                 for (Binding binding : newBindings) {
                     if (InstanceBinding.class.isAssignableFrom(binding.getClass())) {
-                        binding = InitializableInstanceBinding.from((InstanceBinding) binding);
+                        binding = InitializableInstanceBinding.from((InstanceBinding) binding, runtimeType);
                     } else if (SupplierInstanceBinding.class.isAssignableFrom(binding.getClass())) {
-                        binding = InitializableSupplierInstanceBinding.from((SupplierInstanceBinding) binding);
+                        binding = InitializableSupplierInstanceBinding.from((SupplierInstanceBinding) binding, runtimeType);
                     }
                     bindings.add(binding);
                 }
@@ -812,16 +884,55 @@
         }
     }
 
-    private static class MergedBindings implements Binder {
+    /* package */ static class MergedBindings implements Binder {
         private final AbstractBinder first;
         private final AbstractBinder second;
-
+        private final Collection<ClassBinding> classBindings = new ArrayList<>();
+        private final Collection<InitializableInstanceBinding> instanceBindings = new ArrayList<>();
+        private final Collection<SupplierClassBinding> supplierClassBindings = new ArrayList<>();
+        private final Collection<InitializableSupplierInstanceBinding> supplierInstanceBindings = new ArrayList<>();
 
         private MergedBindings(AbstractBinder first, AbstractBinder second) {
             this.first = first;
             this.second = second;
         }
 
+//        private void initBindings(Collection<Binding> bindings) {
+//            for (Binding binding : bindings) {
+//                if (InstanceBinding.class.isInstance(binding)) {
+//                    instanceBindings.add((InitializableInstanceBinding) binding);
+//                } else if (ClassBinding.class.isInstance(binding)) {
+//                    classBindings.add((ClassBinding) binding);
+//                } else if (SupplierInstanceBinding.class.isInstance(binding)) {
+//                    supplierInstanceBindings.add((InitializableSupplierInstanceBinding) binding);
+//                } else if (SupplierClassBinding.class.isInstance(binding)) {
+//                    supplierClassBindings.add((SupplierClassBinding) binding);
+//                }
+//            }
+//        }
+//
+//        public <T extends Binding<T,?>> Collection<T> getBindings(Class<T> clazz) {
+//            if (InstanceBinding.class.equals(clazz)) {
+//                return (Collection<T>) (Collection<? extends Binding>) instanceBindings;
+//            } else if (ClassBinding.class.equals(clazz)) {
+//                return (Collection<T>) (Collection<? extends Binding>) classBindings;
+//            } else if (SupplierInstanceBinding.class.isInstance(clazz)) {
+//                return (Collection<T>) (Collection<? extends Binding>) supplierInstanceBindings;
+//            } else if (SupplierClassBinding.class.equals(clazz)) {
+//                return (Collection<T>) (Collection<? extends Binding>) supplierClassBindings;
+//            }
+//            return Collections.emptyList();
+//        }
+
+        public Collection<Binding> getServerBindings() {
+            return first.getBindings();
+        }
+
+        public Collection<Binding> getClientBindings() {
+            return second.getBindings();
+        }
+
+        @Override
         public Collection<Binding> getBindings() {
             final Collection<Binding> firstBindings = first.getBindings();
             final Collection<Binding> secondBindings = second.getBindings();
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/CdiClientInjectionManager.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/CdiClientInjectionManager.java
index a1c500f..2c6d247 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/CdiClientInjectionManager.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/CdiClientInjectionManager.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
@@ -19,71 +19,88 @@
 import jakarta.enterprise.context.spi.CreationalContext;
 import jakarta.enterprise.inject.spi.Bean;
 import jakarta.enterprise.inject.spi.BeanManager;
+import jakarta.enterprise.inject.spi.InjectionTarget;
 import jakarta.ws.rs.RuntimeType;
 
+import org.glassfish.jersey.inject.weld.internal.bean.ClassBean;
 import org.glassfish.jersey.inject.weld.internal.bean.JerseyBean;
+import org.glassfish.jersey.inject.weld.internal.bean.SupplierClassBean;
+import org.glassfish.jersey.inject.weld.internal.inject.InitializableBinding;
 import org.glassfish.jersey.inject.weld.internal.inject.InitializableInstanceBinding;
 import org.glassfish.jersey.inject.weld.internal.inject.InitializableSupplierInstanceBinding;
 import org.glassfish.jersey.inject.weld.internal.inject.MatchableBinding;
 import org.glassfish.jersey.inject.weld.internal.injector.JerseyClientCreationalContext;
-import org.glassfish.jersey.internal.inject.Binder;
+import org.glassfish.jersey.inject.weld.internal.injector.JerseyInjectionTarget;
 import org.glassfish.jersey.internal.inject.Binding;
 import org.glassfish.jersey.internal.inject.Bindings;
+import org.glassfish.jersey.internal.inject.ClassBinding;
 import org.glassfish.jersey.internal.inject.InjectionManager;
 import org.glassfish.jersey.internal.inject.InstanceBinding;
 import org.glassfish.jersey.internal.inject.SupplierClassBinding;
 import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
 import org.jboss.weld.contexts.CreationalContextImpl;
 
-import java.util.Collection;
 import java.util.IdentityHashMap;
 import java.util.Map;
 
 /**
  * Each Client Runtime has a unique CdiClientInjectionManager, which passes proper {@link Binding} to the Weld.
  */
-public class CdiClientInjectionManager extends CdiInjectionManager {
+public final class CdiClientInjectionManager extends CdiInjectionManager {
 
     private Map<InitializableInstanceBinding, InitializableInstanceBinding> clientInstanceBindings = new IdentityHashMap<>();
     private Map<InitializableSupplierInstanceBinding, InitializableSupplierInstanceBinding> clientSupplierInstanceBindings
             = new IdentityHashMap<>();
     private Map<SupplierClassBinding, SupplierClassBinding> clientSupplierClassBinding = new IdentityHashMap<>();
+    private Map<ClassBinding, ClassBinding> clientClassBinding = new IdentityHashMap<>();
 
-    public CdiClientInjectionManager(BeanManager beanManager, Binder bindings) {
-        super(beanManager, bindings);
+    CdiClientInjectionManager(BeanManager beanManager, BinderRegisterExtension.MergedBindings bindings) {
+        super(beanManager, bindings, RuntimeType.CLIENT);
     }
 
     @Override
     public void register(Binding binding) {
         if (InstanceBinding.class.isInstance(binding)) {
-            final Collection<Binding> preBindings = getBindings().getBindings();
-            MatchableBinding.Matching<InitializableInstanceBinding> matching = MatchableBinding.Matching.noneMatching();
-            for (Binding preBinding : preBindings) {
-                if (InitializableInstanceBinding.class.isInstance(preBinding)) {
-                    matching = matching.better(((InitializableInstanceBinding) preBinding).matches((InstanceBinding) binding));
-                    if (matching.isBest()) {
-                        break;
-                    }
-                }
-            }
+//            final Collection<Binding> preBindings = getBindings().getBindings();
+//            MatchableBinding.Matching<InitializableInstanceBinding> matching = MatchableBinding.Matching.noneMatching();
+//            for (Binding preBinding : preBindings) {
+//                if (InitializableInstanceBinding.class.isInstance(preBinding)) {
+//                    matching = matching.better(((InitializableInstanceBinding) preBinding).matches((InstanceBinding) binding));
+//                    if (matching.isBest()) {
+//                        break;
+//                    }
+//                }
+//            }
+            MatchableBinding.Matching<InitializableInstanceBinding> matching;
+//            MatchableBinding.Matching<InitializableInstanceBinding> matching =
+//                    findPrebinding(InitializableInstanceBinding.class, binding /*, RuntimeType.CLIENT*/);
+//            if (matching.matches()) {
+//                matching.getBinding().init(((InstanceBinding) binding).getService());
+//                return;
+//            }
+            matching = findPrebinding(InitializableInstanceBinding.class, binding/*, RuntimeType.SERVER*/);
             if (matching.matches()) {
                 final InitializableInstanceBinding clone = matching.getBinding().clone();
                 clone.init(((InstanceBinding) binding).getService());
                 clientInstanceBindings.put(matching.getBinding(), clone);
             } else {
-                throw new IllegalStateException("Not initialized " + ((InstanceBinding<?>) binding).getService());
-            }
-        } else if (SupplierInstanceBinding.class.isInstance(binding)) {
-            final Collection<Binding> preBindings = getBindings().getBindings();
-            MatchableBinding.Matching<InitializableSupplierInstanceBinding> matching = MatchableBinding.Matching.noneMatching();
-            for (Binding preBinding : preBindings) {
-                if (InitializableSupplierInstanceBinding.class.isInstance(preBinding)) {
-                    matching = matching.better(((InitializableSupplierInstanceBinding) preBinding).matchesContracts(binding));
-                    if (matching.isBest()) {
-                        break;
-                    }
+                if (!userBindings.init((InstanceBinding<?>) binding)) {
+                    throw new IllegalStateException("Not initialized " + ((InstanceBinding<?>) binding).getService());
                 }
             }
+        } else if (SupplierInstanceBinding.class.isInstance(binding)) {
+//            final Collection<Binding> preBindings = getBindings().getBindings();
+//            MatchableBinding.Matching<InitializableSupplierInstanceBinding> matching = MatchableBinding.Matching.noneMatching();
+//            for (Binding preBinding : preBindings) {
+//                if (InitializableSupplierInstanceBinding.class.isInstance(preBinding)) {
+//                    matching = matching.better(((InitializableSupplierInstanceBinding) preBinding).matchesContracts(binding));
+//                    if (matching.isBest()) {
+//                        break;
+//                    }
+//                }
+//            }
+            MatchableBinding.Matching<InitializableSupplierInstanceBinding> matching =
+                    findPrebinding(InitializableSupplierInstanceBinding.class, binding);
             if (matching.matches()) {
                 final InitializableSupplierInstanceBinding clone = matching.getBinding().clone();
                 clone.init(((SupplierInstanceBinding) binding).getSupplier());
@@ -108,6 +125,15 @@
 //            } else {
 //                throw new IllegalStateException("Not initialized " + ((SupplierInstanceBinding<?>) binding).getSupplier());
 //            }
+        } else if (ClassBinding.class.isInstance(binding)) {
+            ClassBinding prebinding = findClassBinding(binding.getImplementationType());
+            if (prebinding == null) {
+                //User registered provider
+                if (!userBindings.init((ClassBinding<?>) binding)) {
+                    throw new IllegalStateException("Unexpected");
+                }
+                clientClassBinding.put(prebinding, (ClassBinding) binding);
+            }
         }
     }
 
@@ -123,7 +149,22 @@
 
     public SupplierClassBinding getInjectionManagerBinding(SupplierClassBinding binding) {
         SupplierClassBinding clientBinding = clientSupplierClassBinding.get(binding);
-        return clientBinding;
+        return clientBinding != null ? clientBinding : binding;
+    }
+
+    public ClassBinding getInjectionManagerBinding(ClassBinding binding) {
+        ClassBinding clientBinding = clientClassBinding.get(binding);
+        return clientBinding != null ? clientBinding : binding;
+    }
+
+    @Override
+    protected void lockContext() {
+        ContextSafe.lockContext(this);
+    }
+
+    @Override
+    protected void unlockContext() {
+        ContextSafe.unlock(this);
     }
 
     @Override
@@ -145,7 +186,40 @@
 
     @Override
     protected boolean isRuntimeTypeBean(Bean<?> bean) {
-        return !JerseyBean.class.isInstance(bean) || ((JerseyBean) bean).getRutimeType() == RuntimeType.CLIENT;
+        return !JerseyBean.class.isInstance(bean)
+                || ((JerseyBean) bean).getRutimeType() == RuntimeType.CLIENT
+                || clientInstanceBindings.containsKey(((JerseyBean<?>) bean).getBinding())
+                || clientSupplierInstanceBindings.containsKey(((JerseyBean<?>) bean).getBinding())
+                || isTwoFoldInstantiator((JerseyBean) bean);
     }
 
+    private static boolean isTwoFoldInstantiator(JerseyBean bean) {
+        InjectionTarget injectionTarget = null;
+        if (ClassBean.class.isInstance(bean)) {
+            injectionTarget = ((ClassBean) bean).getInjectionTarget();
+        } else if (SupplierClassBean.class.isInstance(bean)) {
+            injectionTarget = ((SupplierClassBean) bean).getInjectionTarget();
+        }
+
+        if (injectionTarget != null) {
+            if (JerseyInjectionTarget.class.isInstance(injectionTarget)) {
+                JerseyInjectionTarget jerseyInjectionTarget = (JerseyInjectionTarget) injectionTarget;
+                return jerseyInjectionTarget.getTwofoldInstantiator().hasOptionalConstructorInjectionPoint();
+            }
+        }
+        return false;
+    }
+
+    private boolean isInit(JerseyBean bean) {
+        if (InitializableBinding.class.isInstance(bean.getBinding())) {
+            return ((InitializableBinding) bean.getBinding()).isInit();
+        } else {
+            return true;
+        }
+    }
+
+    @Override
+    public RuntimeType getRuntimeType() {
+        return RuntimeType.CLIENT;
+    }
 }
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/CdiInjectionManager.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/CdiInjectionManager.java
index e5759ea..91c0d1e 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/CdiInjectionManager.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/CdiInjectionManager.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
@@ -47,24 +47,27 @@
 import org.glassfish.jersey.internal.inject.InstanceBinding;
 import org.glassfish.jersey.internal.inject.ServiceHolder;
 import org.glassfish.jersey.internal.inject.ServiceHolderImpl;
+import org.glassfish.jersey.internal.inject.SupplierClassBinding;
 import org.glassfish.jersey.internal.inject.SupplierInstanceBinding;
 
 /**
  * Implementation of {@link InjectionManager} used on the server side.
  */
 @Singleton
-public class CdiInjectionManager implements InjectionManager {
+class CdiInjectionManager implements InjectionManager {
 
     private final BeanManager beanManager;
-    private final Binder bindings;
+    private final BinderRegisterExtension.MergedBindings bindings;
     private boolean isCompleted = false;
     Set<Class<?>> managedBeans;
+    protected final ProviderBindings userBindings;
 
     // Keeps all binders and bindings added to the InjectionManager during the bootstrap.
 
-    public CdiInjectionManager(BeanManager beanManager, Binder bindings) {
+    CdiInjectionManager(BeanManager beanManager, BinderRegisterExtension.MergedBindings bindings, RuntimeType runtimeType) {
         this.beanManager = beanManager;
         this.bindings = bindings;
+        userBindings = new ProviderBindings(runtimeType, this);
     }
 
     @Override
@@ -73,33 +76,37 @@
             return;
         }
         if (InstanceBinding.class.isInstance(binding)) {
-            final Collection<Binding> preBindings = bindings.getBindings();
-            MatchableBinding.Matching<InitializableInstanceBinding> matching = MatchableBinding.Matching.noneMatching();
-            for (Binding preBinding : preBindings) {
-                if (InitializableInstanceBinding.class.isInstance(preBinding)) {
-                    matching = matching.better(((InitializableInstanceBinding) preBinding).matches((InstanceBinding) binding));
-                    if (matching.isBest()) {
-                        break;
-                    }
-                }
-            }
+//            final Collection<Binding> preBindings = bindings.getBindings();
+//            MatchableBinding.Matching<InitializableInstanceBinding> matching = MatchableBinding.Matching.noneMatching();
+//            for (Binding preBinding : preBindings) {
+//                if (InitializableInstanceBinding.class.isInstance(preBinding)) {
+//                    matching = matching.better(((InitializableInstanceBinding) preBinding).matches((InstanceBinding) binding));
+//                    if (matching.isBest()) {
+//                        break;
+//                    }
+//                }
+//            }
+            MatchableBinding.Matching<InitializableInstanceBinding> matching
+                    = findPrebinding(InitializableInstanceBinding.class, binding);
             if (matching.matches()) {
                matching.getBinding().init(((InstanceBinding) binding).getService());
-            } else if (findClassBinding(binding.getImplementationType()) == null) {
-                throw new IllegalStateException("Not initialized " + ((InstanceBinding<?>) binding).getService());
+            } else /*if (findClassBinding(binding.getImplementationType()) == null) */{
+                throw new IllegalStateException("Could not initialize " + ((InstanceBinding<?>) binding).getService());
             }
         } else if (SupplierInstanceBinding.class.isInstance(binding)) {
-            final Collection<Binding> preBindings = bindings.getBindings();
-            MatchableBinding.Matching<InitializableSupplierInstanceBinding> matching = MatchableBinding.Matching.noneMatching();
-            for (Binding preBinding : preBindings) {
-                if (InitializableSupplierInstanceBinding.class.isInstance(preBinding)) {
-                    matching = matching.better(
-                            ((InitializableSupplierInstanceBinding) preBinding).matches((SupplierInstanceBinding) binding));
-                    if (matching.isBest()) {
-                        break;
-                    }
-                }
-            }
+//            final Collection<Binding> preBindings = bindings.getBindings();
+//            MatchableBinding.Matching<InitializableSupplierInstanceBinding> matching = MatchableBinding.Matching.noneMatching();
+//            for (Binding preBinding : preBindings) {
+//                if (InitializableSupplierInstanceBinding.class.isInstance(preBinding)) {
+//                    matching = matching.better(
+//                            ((InitializableSupplierInstanceBinding) preBinding).matches((SupplierInstanceBinding) binding));
+//                    if (matching.isBest()) {
+//                        break;
+//                    }
+//                }
+//            }
+            MatchableBinding.Matching<InitializableSupplierInstanceBinding> matching =
+                    findPrebinding(InitializableSupplierInstanceBinding.class, binding);
             if (matching.matches()) {
                 matching.getBinding().init(((SupplierInstanceBinding) binding).getSupplier());
             } else {
@@ -123,9 +130,31 @@
         }
     }
 
-    private <T> ClassBinding<T> findClassBinding(Class<T> implementationType) {
+    protected <MB extends MatchableBinding> MatchableBinding.Matching<MB>
+    findPrebinding(Class<MB> matchebleBindingClass, Binding binderBinding) {
+        final Collection<Binding> preBindings;
+//        if (runtimeType == RuntimeType.SERVER) {
+//            preBindings = bindings.getServerBindings();
+//        } else if (runtimeType == RuntimeType.CLIENT) {
+//            preBindings = bindings.getClientBindings();
+//        } else {
+            preBindings = bindings.getBindings();
+//        }
+        MatchableBinding.Matching<MB> matching = MatchableBinding.Matching.noneMatching();
+        for (Binding preBinding : preBindings) {
+            if (matchebleBindingClass.isInstance(preBinding)) {
+                matching = matching.better(((MB) preBinding).matching(binderBinding));
+                if (matching.isBest()
+                        || (matching.matches() && binderBinding.isForClient())) {
+                    break;
+                }
+            }
+        }
+        return matching;
+    }
+
+    protected <T> ClassBinding<T> findClassBinding(Class<T> implementationType) {
         final Collection<Binding> preBindings = bindings.getBindings();
-        boolean found = false;
         for (Binding preBinding : preBindings) {
             if (ClassBinding.class.isInstance(preBinding)
                     && ((ClassBinding) preBinding).getImplementationType().equals(implementationType)) {
@@ -135,6 +164,17 @@
         return null;
     }
 
+    protected <T> SupplierClassBinding<T> findSupplierClassBinding(Class<T> implementationType) {
+        final Collection<Binding> preBindings = bindings.getBindings();
+        for (Binding preBinding : preBindings) {
+            if (SupplierClassBinding.class.isInstance(preBinding)
+                    && ((SupplierClassBinding) preBinding).getImplementationType().equals(implementationType)) {
+                return (SupplierClassBinding<T>) preBinding;
+            }
+        }
+        return null;
+    }
+
     private boolean isManagedClass(Binding binding) {
         return managedBeans != null
                 && binding.getImplementationType() != null
@@ -168,13 +208,13 @@
 
     @Override
     public <T> T create(Class<T> createMe) {
-        Unmanaged.UnmanagedInstance<T> unmanaged = new Unmanaged<>(createMe).newInstance();
+        Unmanaged.UnmanagedInstance<T> unmanaged = new Unmanaged<>(beanManager, createMe).newInstance();
         return unmanaged.produce().get();
     }
 
     @Override
     public <T> T createAndInitialize(Class<T> createMe) {
-        Unmanaged.UnmanagedInstance<T> unmanaged = new Unmanaged<>(createMe).newInstance();
+        Unmanaged.UnmanagedInstance<T> unmanaged = new Unmanaged<>(beanManager, createMe).newInstance();
         return unmanaged.produce()
                 .inject()
                 .postConstruct()
@@ -192,15 +232,18 @@
             }
 
             CreationalContext<?> ctx = createCreationalContext(bean);
+            lockContext();
             T reference = (T) beanManager.getReference(bean, contractOrImpl, ctx);
+            unlockContext();
 
-            int rank = 1;
+            int rank = 0;
             if (bean instanceof JerseyBean) {
                 rank = ((JerseyBean) bean).getRank();
             }
 
             result.add(new ServiceHolderImpl<>(reference, (Class<T>) bean.getBeanClass(), bean.getTypes(), rank));
         }
+        result.addAll(userBindings.getServiceHolders(contractOrImpl));
         return result;
     }
 
@@ -220,7 +263,7 @@
     }
 
     @SuppressWarnings("unchecked")
-    protected <T> T getInstanceInternal(Type contractOrImpl, Annotation... qualifiers) {
+    protected <T> T  getInstanceInternal(Type contractOrImpl, Annotation... qualifiers) {
 //        if (contractOrImpl.getTypeName().contains("HelloResource")) {
 //            T t = (T) CDI.current().select((Class) contractOrImpl, qualifiers).get();
 //            try {
@@ -242,11 +285,22 @@
 
         final Iterator<?> beansIterator = beans.iterator();
         Bean<?> bean = (Bean<?>) beansIterator.next();
-        while (beansIterator.hasNext() && !JerseyBean.class.isInstance(bean) && !isRuntimeTypeBean(bean)) {
-            bean = (Bean<?>) beansIterator.next(); // prefer Jersey binding
+        boolean isRuntimeType = false;
+        while (!(isRuntimeType = isRuntimeTypeBean(bean))) {
+            if (beansIterator.hasNext()) {
+                bean = (Bean<?>) beansIterator.next(); // prefer Jersey binding
+            } else {
+                break;
+            }
+        }
+        if (!isRuntimeType) {
+            throw new IllegalStateException("Bean for type " + contractOrImpl + " not found");
         }
         CreationalContext<T> ctx = createCreationalContext((Bean<T>) bean);
-        return (T) beanManager.getReference(bean, contractOrImpl, ctx);
+        lockContext();
+        T t = (T) beanManager.getReference(bean, contractOrImpl, ctx);
+        unlockContext();
+        return t;
     }
 
     @Override
@@ -286,10 +340,16 @@
     public <T> List<T> getAllInstances(Type contractOrImpl) {
         List<T> result = new ArrayList<>();
         for (Bean<?> bean : beanManager.getBeans(contractOrImpl)) {
+            if (!isRuntimeTypeBean(bean)) {
+                continue;
+            }
             CreationalContext<?> ctx = createCreationalContext(bean);
+            lockContext();
             Object reference = beanManager.getReference(bean, contractOrImpl, ctx);
+            unlockContext();
             result.add((T) reference);
         }
+        result.addAll(userBindings.getServices(contractOrImpl));
         return result;
     }
 
@@ -304,6 +364,12 @@
         injectionTarget.inject(instance, creationalContext);
     }
 
+    protected void lockContext() {
+    }
+
+    protected void unlockContext() {
+    }
+
     @Override
     public void preDestroy(Object preDestroyMe) {
     }
@@ -338,7 +404,7 @@
         return false;
     }
 
-    protected Binder getBindings() {
+    protected BinderRegisterExtension.MergedBindings getBindings() {
         return bindings;
     }
 
@@ -361,7 +427,8 @@
      * @return true iff the given bean is not a Jersey Bean or the Jersey Bean is of the proper {@code RuntimeType}.
      */
     protected boolean isRuntimeTypeBean(Bean<?> bean) {
-        return !JerseyBean.class.isInstance(bean) || ((JerseyBean) bean).getRutimeType() == RuntimeType.SERVER;
+        return !JerseyBean.class.isInstance(bean)
+                || ((JerseyBean) bean).getRutimeType() == RuntimeType.SERVER;
     }
 
     @Override
@@ -375,4 +442,9 @@
         // TODO: Used only in legacy CDI integration.
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public RuntimeType getRuntimeType() {
+        return RuntimeType.SERVER;
+    }
 }
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ClientBootstrapPreinitialization.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ClientBootstrapPreinitialization.java
index c748f6c..215e836 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ClientBootstrapPreinitialization.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ClientBootstrapPreinitialization.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
@@ -16,19 +16,9 @@
 
 package org.glassfish.jersey.inject.weld.internal.managed;
 
-import jakarta.inject.Inject;
-import jakarta.inject.Provider;
 import jakarta.ws.rs.RuntimeType;
-import jakarta.ws.rs.client.ClientBuilder;
-
-import org.glassfish.jersey.client.ClientConfig;
-import org.glassfish.jersey.client.ClientRequest;
-import org.glassfish.jersey.client.JerseyClient;
 import org.glassfish.jersey.inject.weld.spi.BootstrapPreinitialization;
-import org.glassfish.jersey.internal.PropertiesDelegate;
 import org.glassfish.jersey.internal.inject.AbstractBinder;
-import org.glassfish.jersey.internal.inject.ReferencingFactory;
-import org.glassfish.jersey.internal.util.collection.Ref;
 
 import java.util.function.Supplier;
 
@@ -44,8 +34,8 @@
             return;
         }
 
-        ClientConfig config = new ClientConfig();
-        JerseyClient client = (JerseyClient) ClientBuilder.newClient(config);
-        client.getConfiguration().getClientExecutor();
+//        ClientConfig config = new ClientConfig();
+//        JerseyClient client = (JerseyClient) ClientBuilder.newClient(config);
+//        client.getConfiguration().getClientExecutor();
     }
 }
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ContextSafe.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ContextSafe.java
new file mode 100644
index 0000000..1350b0f
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ContextSafe.java
@@ -0,0 +1,38 @@
+/*
+ * 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.managed;
+
+public final class ContextSafe {
+
+    private static final ThreadLocal<CdiClientInjectionManager> CURRENT_CONTEXT = new ThreadLocal<>();
+
+    public static void lockContext(CdiClientInjectionManager current) {
+        CURRENT_CONTEXT.set(current);
+    }
+
+    public static CdiClientInjectionManager get() {
+        return CURRENT_CONTEXT.get();
+    }
+
+    public static void unlock(CdiClientInjectionManager locked) {
+        CdiClientInjectionManager ctx = CURRENT_CONTEXT.get();
+        if (ctx != locked) {
+            throw new IllegalStateException("The CreationalContext safe has been compromised");
+        }
+        CURRENT_CONTEXT.remove();
+    }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ProviderBindings.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ProviderBindings.java
new file mode 100644
index 0000000..16b39d0
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ProviderBindings.java
@@ -0,0 +1,130 @@
+/*
+ * 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.managed;
+
+import org.glassfish.jersey.inject.weld.internal.inject.ClassListBinding;
+import org.glassfish.jersey.inject.weld.internal.inject.InstanceListBinding;
+import org.glassfish.jersey.internal.inject.ClassBinding;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.InstanceBinding;
+import org.glassfish.jersey.internal.inject.ServiceHolder;
+
+import jakarta.ws.rs.RuntimeType;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.client.ClientResponseFilter;
+import jakarta.ws.rs.client.RxInvokerProvider;
+import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.container.ContainerResponseFilter;
+import jakarta.ws.rs.container.DynamicFeature;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.MessageBodyWriter;
+import jakarta.ws.rs.ext.ParamConverterProvider;
+import jakarta.ws.rs.ext.ReaderInterceptor;
+import jakarta.ws.rs.ext.WriterInterceptor;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+class ProviderBindings {
+    private final Map<Type, InstanceListBinding<?>> userInstanceBindings = new HashMap<>();
+    private final Map<Type, ClassListBinding<?>> userClassBindings = new HashMap<>();
+    private final InjectionManager injectionManager;
+
+    ProviderBindings(RuntimeType runtimeType, InjectionManager injectionManager) {
+        this.injectionManager = injectionManager;
+
+        if (runtimeType == RuntimeType.CLIENT) {
+            init(ClientRequestFilter.class);
+            init(ClientResponseFilter.class);
+            init(RxInvokerProvider.class);
+        } else if (runtimeType == RuntimeType.SERVER) {
+            init(ContainerResponseFilter.class);
+            init(ContainerRequestFilter.class);
+            init(DynamicFeature.class);
+        }
+        init(ParamConverterProvider.class);
+        init(WriterInterceptor.class);
+        init(ReaderInterceptor.class);
+        init(MessageBodyReader.class);
+        init(MessageBodyWriter.class);
+    }
+
+    private <T> void init(Class<T> contract) {
+        userInstanceBindings.put(contract, new InstanceListBinding<T>(contract));
+        userClassBindings.put(contract, new ClassListBinding<T>(contract, injectionManager));
+    }
+
+    boolean init(InstanceBinding<?> userBinding) {
+        boolean init = false;
+        for (Type contract : userBinding.getContracts()) {
+            InstanceListBinding<?> binding = userInstanceBindings.get(contract);
+            if (binding != null) {
+                init = true;
+                binding.init(userBinding);
+                break;
+            }
+        }
+        return init;
+    }
+
+    boolean init(ClassBinding<?> userBinding) {
+        boolean init = false;
+        for (Type contract : userBinding.getContracts()) {
+            ClassListBinding<?> binding = userClassBindings.get(contract);
+            if (binding != null) {
+                init = true;
+                binding.init(userBinding);
+                break;
+            }
+        }
+        return init;
+    }
+
+    <T> List<ServiceHolder<T>> getServiceHolders(Type contract) {
+        List<ServiceHolder<T>> list = new ArrayList<>();
+
+        InstanceListBinding<T> instanceBinding = (InstanceListBinding<T>) userInstanceBindings.get(contract);
+        if (instanceBinding != null) {
+            list.addAll(instanceBinding.getServiceHolders());
+        }
+
+        ClassListBinding<T> classBinding = (ClassListBinding<T>) userClassBindings.get(contract);
+        if (classBinding != null) {
+            list.addAll(classBinding.getServiceHolders());
+        }
+
+        return list;
+    }
+
+    <T> List<T> getServices(Type contract) {
+        List<T> list = new ArrayList<>();
+
+        InstanceListBinding<T> instanceBinding = (InstanceListBinding<T>) userInstanceBindings.get(contract);
+        if (instanceBinding != null) {
+            list.addAll(instanceBinding.getServices());
+        }
+
+        ClassListBinding<T> classBinding = (ClassListBinding<T>) userClassBindings.get(contract);
+        if (classBinding != null) {
+            list.addAll(classBinding.getServices());
+        }
+
+        return list;
+    }
+}
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ServerBootstrapPreinitialization.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ServerBootstrapPreinitialization.java
index 826c52f..4cc7b98 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ServerBootstrapPreinitialization.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/internal/managed/ServerBootstrapPreinitialization.java
@@ -1,6 +1,6 @@
 /*
+ * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2022 Contributors to the Eclipse Foundation
- * Copyright (c) 2021 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
@@ -51,9 +51,6 @@
 import org.glassfish.jersey.model.internal.CommonConfig;
 import org.glassfish.jersey.model.internal.ComponentBag;
 import org.glassfish.jersey.process.internal.RequestScoped;
-import org.glassfish.jersey.server.wadl.WadlFeature;
-import org.glassfish.jersey.server.wadl.processor.OptionsMethodProcessor;
-import org.glassfish.jersey.server.wadl.processor.WadlModelProcessor;
 import org.glassfish.jersey.servlet.WebConfig;
 import org.glassfish.jersey.servlet.spi.AsyncContextDelegateProvider;
 import org.glassfish.jersey.servlet.spi.FilterUrlMappingsProvider;
@@ -558,7 +555,7 @@
 //        binder.bind(ChunkedResponseWriter.class).to(MessageBodyWriter.class).in(Singleton.class);
 //        binder.bind(JsonWithPaddingInterceptor.class).to(WriterInterceptor.class).in(Singleton.class);
 
-        if (runtimeType == RuntimeType.SERVER) {
+        if (runtimeType == null /*RuntimeType.SERVER*/) {
             // new ApplicationHandler(new ResourceConfig());
 
             //grizzly
@@ -597,29 +594,29 @@
             final ServletConfig servletConfig = webConfig.getServletConfig();
             binder.bindFactory(() -> servletConfig).to(ServletConfig.class).in(Singleton.class);
 
-            // WADL TODO put to a proper module
-            try {
-                new WadlFeature().configure(new PreinitializationFeatureContext(binder) {
-                    @Override
-                    public FeatureContext register(Class<?> componentClass) {
-                        if (WadlModelProcessor.class.isAssignableFrom(componentClass)) {
-                            super.register(WadlModelProcessor.OptionsHandler.class);
-                        }
-                        super.register(componentClass);
-                        return this;
-                    }
-                });
-            } catch (Exception e) {
-
-            }
-            try {
-                Class[] classes = OptionsMethodProcessor.class.getDeclaredClasses();
-                for (Class clz : classes) {
-                    binder.bindAsContract(clz);
-                }
-            } catch (Exception e) {
-
-            }
+//            // WADL TODO put to a proper module
+//            try {
+//                new WadlFeature().configure(new PreinitializationFeatureContext(binder) {
+//                    @Override
+//                    public FeatureContext register(Class<?> componentClass) {
+//                        if (WadlModelProcessor.class.isAssignableFrom(componentClass)) {
+//                            super.register(WadlModelProcessor.OptionsHandler.class);
+//                        }
+//                        super.register(componentClass);
+//                        return this;
+//                    }
+//                });
+//            } catch (Exception e) {
+//
+//            }
+//            try {
+//                Class[] classes = OptionsMethodProcessor.class.getDeclaredClasses();
+//                for (Class clz : classes) {
+//                    binder.bindAsContract(clz);
+//                }
+//            } catch (Exception e) {
+//
+//            }
         }
 
 //
diff --git a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/managed/CdiInjectionManagerFactory.java b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/managed/CdiInjectionManagerFactory.java
index ad7ac01..12d20bc 100644
--- a/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/managed/CdiInjectionManagerFactory.java
+++ b/incubator/cdi-inject-weld/src/main/java/org/glassfish/jersey/inject/weld/managed/CdiInjectionManagerFactory.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
@@ -19,6 +19,7 @@
 import jakarta.annotation.Priority;
 import jakarta.enterprise.context.spi.CreationalContext;
 import jakarta.ws.rs.RuntimeType;
+import jakarta.ws.rs.core.Configuration;
 
 import org.glassfish.jersey.client.ClientConfig;
 import org.glassfish.jersey.inject.weld.internal.injector.JerseyClientCreationalContext;
@@ -34,11 +35,16 @@
 public class CdiInjectionManagerFactory extends CdiInjectionManagerFactoryBase implements InjectionManagerFactory {
 
     @Override
-    // TODO deprecate this in favor of #create(Object parent, RuntimeType runtimeType)
+    @Deprecated
     public InjectionManager create(Object parent) {
         return create(parent, getRuntimeType());
     }
 
+    @Override
+    public InjectionManager create(Object parent, Configuration configuration) {
+        return create(parent, configuration.getRuntimeType());
+    }
+
     /**
      * Create injectionManager for {@link RuntimeType#CLIENT or get the existing injection manager for the server}
      * @param parent Parent injection manager. Not used in this InjectionManagerFactory.
@@ -62,7 +68,7 @@
         }
     }
 
-    // TODO refactor to call InjectionManagerFactory#create(Object, RuntimeType);
+    @Deprecated
     private static RuntimeType getRuntimeType() {
         Exception e = new RuntimeException();
         for (StackTraceElement element : e.getStackTrace()) {
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/ClientTestParent.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/ClientTestParent.java
new file mode 100644
index 0000000..beb75bd
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/ClientTestParent.java
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+import org.glassfish.jersey.internal.inject.Injections;
+import org.junit.jupiter.api.BeforeEach;
+
+import jakarta.ws.rs.RuntimeType;
+
+public class ClientTestParent extends TestParent {
+    @BeforeEach
+    public void init() {
+        injectionManager = Injections.createInjectionManager(RuntimeType.CLIENT);
+    }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/TestParent.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/TestParent.java
new file mode 100644
index 0000000..b89a179
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/TestParent.java
@@ -0,0 +1,82 @@
+/*
+ * 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;
+
+import jakarta.enterprise.inject.se.SeContainer;
+import jakarta.enterprise.inject.se.SeContainerInitializer;
+
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Injections;
+import org.glassfish.jersey.internal.inject.ServiceHolder;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.BeforeAll;
+
+import java.util.List;
+
+public class TestParent {
+    protected static SeContainer container;
+    protected InjectionManager injectionManager;
+
+    @BeforeAll
+    public static void setup() {
+        SeContainerInitializer containerInitializer = SeContainerInitializer.newInstance();
+        container = containerInitializer.initialize();
+    }
+
+    @BeforeEach
+    public void init() {
+        injectionManager = Injections.createInjectionManager();
+    }
+
+    @AfterAll
+    public static void tearDown() throws Exception {
+        container.close();
+    }
+
+    protected <T> void assertOneInstance(Class<T> type, String implementationName) {
+        Assertions.assertEquals(1, injectionManager.getAllInstances(type).size());
+        Assertions.assertEquals(1, injectionManager.getAllServiceHolders(type).size());
+        T provider = injectionManager.getInstance(type);
+        Assertions.assertNotNull(provider);
+        Assertions.assertTrue(provider.getClass().getName().contains(implementationName),
+                "The provider name was " + provider.getClass().getName() + " but expected was " + implementationName);
+    }
+
+    protected <T> void assertMultiple(Class<T> type, int minCount, String... implementationNames) {
+        assertMultiple(injectionManager, type, minCount, implementationNames);
+    }
+
+    public static <T> void assertMultiple(
+            InjectionManager injectionManager, Class<T> type, int minCount, String... implementationNames) {
+        List<T> instances = injectionManager.getAllInstances(type);
+        Assertions.assertTrue(instances.size() >= minCount, type.getSimpleName() + " instances " + instances.size());
+        for (String implName : implementationNames) {
+            Assertions.assertTrue(instances.stream().anyMatch(i -> i.getClass().getSimpleName().equals(implName)),
+                    implName + " was not found among the instances");
+        }
+
+        List<ServiceHolder<T>> holders = injectionManager.getAllServiceHolders(type);
+        Assertions.assertTrue(holders.size() >= minCount, type.getSimpleName() + " service holders " + instances.size());
+        for (String implName : implementationNames) {
+            Assertions.assertTrue(holders.stream().anyMatch(h -> h.getInstance().getClass().getSimpleName().equals(implName)),
+                    implName + " was not found among the service holders");
+        }
+    }
+
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/client/ClientBindingsTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/client/ClientBindingsTest.java
new file mode 100644
index 0000000..4b618d8
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/client/ClientBindingsTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.binder.client;
+
+import org.glassfish.jersey.client.ClientBootstrapBag;
+import org.glassfish.jersey.client.ClientBootstrapPreinitialization;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.inject.ParameterUpdaterProvider;
+import org.glassfish.jersey.client.internal.inject.ParameterUpdaterConfigurator;
+import org.glassfish.jersey.inject.weld.ClientTestParent;
+import org.glassfish.jersey.internal.BootstrapBag;
+import org.glassfish.jersey.internal.ContextResolverFactory;
+import org.glassfish.jersey.internal.ExceptionMapperFactory;
+import org.glassfish.jersey.internal.JaxrsProviders;
+import org.glassfish.jersey.internal.inject.ServiceHolder;
+import org.glassfish.jersey.internal.spi.AutoDiscoverable;
+import org.glassfish.jersey.message.MessageBodyWorkers;
+import org.glassfish.jersey.message.internal.MessageBodyFactory;
+import org.glassfish.jersey.spi.ContextResolvers;
+import org.glassfish.jersey.spi.ExceptionMappers;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.RuntimeType;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.ext.ParamConverterProvider;
+import jakarta.ws.rs.ext.Providers;
+import java.util.List;
+
+public class ClientBindingsTest extends ClientTestParent {
+    @Test
+    void testConfigurationInjection() {
+        injectionManager.completeRegistration();
+        new ClientBootstrapPreinitialization().preregister(RuntimeType.CLIENT, injectionManager);
+        assertOneInstance(Configuration.class, "ClientConfig$State");
+    }
+
+    @Test
+    void testParamConverterProvider() {
+        injectionManager.completeRegistration();
+        // new ParamConverterConfigurator().init(injectionManager, (BootstrapBag) null); requires Configuration
+        new ClientBootstrapPreinitialization().preregister(RuntimeType.CLIENT, injectionManager);
+        assertOneInstance(ParamConverterProvider.class, "AggregatedProvider");
+    }
+
+    @Test
+    void testParameterUpdaterProvider() {
+        injectionManager.completeRegistration();
+        new ParameterUpdaterConfigurator().init(injectionManager, new ClientBootstrapBag());
+        assertOneInstance(ParameterUpdaterProvider.class, "ParameterUpdaterFactory");
+    }
+
+    @Test
+    void testContextResolvers() {
+        injectionManager.completeRegistration();
+
+        ClientBootstrapBag cbb = new ClientBootstrapBag();
+        cbb.setConfiguration(new ClientConfig());
+        new ContextResolverFactory.ContextResolversConfigurator().init(injectionManager, cbb);
+        assertOneInstance(ContextResolvers.class, "ContextResolverFactory");
+    }
+
+    @Test
+    void testExceptionMappers() {
+        injectionManager.completeRegistration();
+
+        ClientBootstrapBag cbb = new ClientBootstrapBag();
+        cbb.setConfiguration(new ClientConfig());
+        new ExceptionMapperFactory.ExceptionMappersConfigurator().init(injectionManager, cbb);
+        assertOneInstance(ExceptionMappers.class, "ExceptionMapperFactory");
+    }
+
+    @Test
+    void testProviders() {
+        injectionManager.completeRegistration();
+        new JaxrsProviders.ProvidersConfigurator().init(injectionManager, (BootstrapBag) null);
+        assertOneInstance(Providers.class, "JaxrsProviders");
+    }
+
+    @Test
+    void testAutoDiscoverable() {
+        injectionManager.completeRegistration();
+        // new AutoDiscoverableConfigurator(RuntimeType.CLIENT).init(injectionManager, new ClientBootstrapBag()); config
+        new ClientBootstrapPreinitialization().preregister(RuntimeType.CLIENT, injectionManager);
+        assertMultiple(AutoDiscoverable.class, 2, "LoggingFeatureAutoDiscoverable");
+    }
+
+    @Test
+    void testMessageBodyWorkers() {
+        injectionManager.completeRegistration();
+        new ClientBootstrapPreinitialization().preregister(RuntimeType.CLIENT, injectionManager);
+        assertOneInstance(MessageBodyWorkers.class, "MessageBodyFactory");
+    }
+
+    @Test
+    void clientOnlyInstancesTest() {
+        injectionManager.completeRegistration();
+        List<ClientOnlyPreinitialization.ClientOnlyInterface> instances =
+                injectionManager.getAllInstances(ClientOnlyPreinitialization.ClientOnlyInterface.class);
+        Assertions.assertEquals(2, instances.size());
+        Assertions.assertTrue(instances.stream()
+                .anyMatch(p -> p.getClass().equals(ClientOnlyPreinitialization.ClientOnlyClassA.class)));
+        Assertions.assertTrue(instances.stream()
+                .anyMatch(p -> p.getClass().equals(ClientOnlyPreinitialization.ClientOnlyClassB.class)));
+    }
+
+    @Test
+    void clientOnlyServiceHoldersTest() {
+        injectionManager.completeRegistration();
+        List<ServiceHolder<ClientOnlyPreinitialization.ClientOnlyInterface>> instances =
+                injectionManager.getAllServiceHolders(ClientOnlyPreinitialization.ClientOnlyInterface.class);
+        Assertions.assertEquals(2, instances.size());
+        Assertions.assertTrue(instances.stream()
+                .anyMatch(p -> p.getInstance().getClass().equals(ClientOnlyPreinitialization.ClientOnlyClassA.class)));
+        Assertions.assertTrue(instances.stream()
+                .anyMatch(p -> p.getInstance().getClass().equals(ClientOnlyPreinitialization.ClientOnlyClassB.class)));
+    }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/client/ClientOnlyPreinitialization.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/client/ClientOnlyPreinitialization.java
new file mode 100644
index 0000000..0660a4c
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/client/ClientOnlyPreinitialization.java
@@ -0,0 +1,45 @@
+/*
+ * 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.binder.client;
+
+import org.glassfish.jersey.innate.BootstrapPreinitialization;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+
+import jakarta.ws.rs.RuntimeType;
+
+public class ClientOnlyPreinitialization implements BootstrapPreinitialization {
+    public static interface ClientOnlyInterface {
+
+    }
+    public static class ClientOnlyClassA implements ClientOnlyInterface {
+
+    }
+    public static class ClientOnlyClassB implements ClientOnlyInterface {
+
+    }
+    @Override
+    public void preregister(RuntimeType runtimeType, InjectionManager injectionManager) {
+        injectionManager.register(new AbstractBinder() {
+            @Override
+            protected void configure() {
+                bind(ClientOnlyClassA.class).to(ClientOnlyInterface.class);
+                bind(ClientOnlyClassB.class).to(ClientOnlyInterface.class);
+            }
+        });
+    }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/client/CustomProviderTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/client/CustomProviderTest.java
new file mode 100644
index 0000000..4d63204
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/client/CustomProviderTest.java
@@ -0,0 +1,160 @@
+/*
+ * 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.binder.client;
+
+import org.glassfish.jersey.inject.weld.ClientTestParent;
+import org.glassfish.jersey.inject.weld.TestParent;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.InjectionManagerSupplier;
+import org.glassfish.jersey.message.internal.ReaderWriter;
+import org.glassfish.jersey.process.internal.RequestScoped;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Configuration;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.MessageBodyWriter;
+import jakarta.ws.rs.ext.Provider;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.nio.charset.StandardCharsets;
+
+public class CustomProviderTest extends ClientTestParent {
+
+    private static final String URI = "http://somewhere.nevermind:60000";
+
+    public static class POJO {
+        private final String value;
+
+        public POJO(String value) {
+            this.value = value;
+        }
+
+        @Override
+        public String toString() {
+            return value;
+        }
+    }
+
+    public static class POJOProvider implements MessageBodyReader<POJO>, MessageBodyWriter<POJO> {
+
+        @Override
+        public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+            return type == POJO.class;
+        }
+
+        @Override
+        public POJO readFrom(Class<POJO> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+                             MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
+                throws IOException, WebApplicationException {
+            return new POJO(ReaderWriter.readFromAsString(entityStream, mediaType));
+        }
+
+        @Override
+        public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+            return type == POJO.class;
+        }
+
+        @Override
+        public void writeTo(POJO pojo, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+                            MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
+                throws IOException, WebApplicationException {
+            entityStream.write(pojo.toString().getBytes(StandardCharsets.UTF_8));
+        }
+    }
+
+    @Test
+    void testCustomRequestFilter() {
+        Response r = ClientBuilder.newClient()
+                .register(new ClientRequestFilter() {
+                    @Override
+                    public void filter(ClientRequestContext requestContext) throws IOException {
+                        InjectionManager im = ((InjectionManagerSupplier) requestContext).getInjectionManager();
+                        assertMultiple(im, ClientRequestFilter.class, 1, this.getClass().getSimpleName());
+                        requestContext.abortWith(Response.ok().build());
+                    }})
+                .target(URI).request()
+                .get();
+        r.close();
+    }
+
+    @Test
+    void testCustomMessageBodyReader() {
+        Response r = ClientBuilder.newClient()
+                .register(new POJOProvider())
+                .register(new ClientRequestFilter() {
+                    @Override
+                    public void filter(ClientRequestContext requestContext) throws IOException {
+                        InjectionManager im = ((InjectionManagerSupplier) requestContext).getInjectionManager();
+                        assertMultiple(im, MessageBodyReader.class, 1, POJOProvider.class.getSimpleName());
+                        requestContext.abortWith(Response.ok().build());
+                    }})
+                .target(URI).request()
+                .get();
+        r.close();
+    }
+
+    @Test
+    void testCustomMessageBodyReaderClass() {
+        Response r = ClientBuilder.newClient()
+                .register(POJOProvider.class)
+                .register(new ClientRequestFilter() {
+                    @Override
+                    public void filter(ClientRequestContext requestContext) throws IOException {
+                        InjectionManager im = ((InjectionManagerSupplier) requestContext).getInjectionManager();
+                        assertMultiple(im, MessageBodyReader.class, 1, POJOProvider.class.getSimpleName());
+                        requestContext.abortWith(Response.ok().build());
+                    }})
+                .target(URI).request()
+                .get();
+        r.close();
+        //post(Entity.entity(new POJO("hello"),MediaType.TEXT_PLAIN_TYPE));
+    }
+
+    static class InjectingClientRequestFilter implements ClientRequestFilter {
+        @Inject
+        Configuration configuration;
+
+        @Override
+        public void filter(ClientRequestContext requestContext) throws IOException {
+            Assertions.assertNotNull(configuration);
+            Assertions.assertTrue(configuration.getClass().getName().contains("ClientConfig$State"));
+            requestContext.abortWith(Response.ok().build());
+        }
+    }
+
+    @Test
+    void testCustomFilterProviderIsInjectable() {
+        try (Response r = ClientBuilder.newClient().register(InjectingClientRequestFilter.class)
+                .target(URI).request().get()) {
+            Assertions.assertEquals(200, r.getStatus());
+        }
+    }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/client/TestClientRequestFilter.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/client/TestClientRequestFilter.java
new file mode 100644
index 0000000..f6b4000
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/client/TestClientRequestFilter.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * 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.binder.client;
+
+import org.glassfish.jersey.inject.weld.TestParent;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.InjectionManagerSupplier;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.Provider;
+import java.io.IOException;
+
+@Provider
+//@ApplicationScoped
+public class TestClientRequestFilter implements ClientRequestFilter {
+    @Override
+    public void filter(ClientRequestContext requestContext) throws IOException {
+        InjectionManager im = ((InjectionManagerSupplier) requestContext).getInjectionManager();
+        TestParent.assertMultiple(im, ClientRequestFilter.class, 1, CustomProviderTest.POJOProvider.class.getName());
+        requestContext.abortWith(Response.ok().build());
+    }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/common/CoreCommonBindingsTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/common/CoreCommonBindingsTest.java
new file mode 100644
index 0000000..66a4b18
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/common/CoreCommonBindingsTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * 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.binder.common;
+
+import org.glassfish.jersey.inject.weld.ClientTestParent;
+import org.glassfish.jersey.internal.BootstrapBag;
+import org.glassfish.jersey.message.MessageBodyWorkers;
+import org.glassfish.jersey.message.internal.MessageBodyFactory;
+import org.glassfish.jersey.message.internal.MessagingBinders;
+import org.glassfish.jersey.spi.HeaderDelegateProvider;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import jakarta.ws.rs.RuntimeType;
+import jakarta.ws.rs.ext.MessageBodyReader;
+import jakarta.ws.rs.ext.MessageBodyWriter;
+import java.util.Collections;
+import java.util.List;
+
+public class CoreCommonBindingsTest extends ClientTestParent {
+
+    @Test
+    public void testProviders() {
+        injectionManager.completeRegistration();
+        injectionManager.register(new MessagingBinders.HeaderDelegateProviders(RuntimeType.CLIENT));
+        assertMultiple(HeaderDelegateProvider.class, 10, "DateProvider");
+    }
+
+    @Test
+    public void testMessageBodyProviders() {
+        injectionManager.completeRegistration();
+        injectionManager.register(new MessagingBinders.MessageBodyProviders(Collections.emptyMap(), RuntimeType.CLIENT));
+        assertMultiple(MessageBodyReader.class, 10, "StringMessageProvider");
+        assertMultiple(MessageBodyWriter.class, 10, "StringMessageProvider");
+    }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/server/ModelProcessorBindingsTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/server/ModelProcessorBindingsTest.java
new file mode 100644
index 0000000..126148b
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/server/ModelProcessorBindingsTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.binder.server;
+
+import org.glassfish.jersey.inject.weld.TestParent;
+import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.Bindings;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.server.ServerConfig;
+import org.glassfish.jersey.server.internal.JerseyResourceContext;
+import org.glassfish.jersey.server.model.ModelProcessor;
+import org.glassfish.jersey.server.wadl.WadlApplicationContext;
+import org.glassfish.jersey.server.wadl.internal.WadlApplicationContextImpl;
+import org.glassfish.jersey.server.wadl.processor.OptionsMethodProcessor;
+import org.glassfish.jersey.server.wadl.processor.WadlModelProcessor;
+import org.junit.jupiter.api.Test;
+
+import jakarta.inject.Singleton;
+import javax.security.auth.login.Configuration;
+import jakarta.ws.rs.container.ResourceContext;
+
+public class ModelProcessorBindingsTest extends TestParent {
+
+    @Test
+    public void testWadlProcessor() {
+        injectionManager.completeRegistration();
+        injectionManager.register(Bindings.service(new OptionsMethodProcessor()).to(ModelProcessor.class));
+//        injectionManager.register(new AbstractBinder() {
+//            @Override
+//            protected void configure() {
+//                bind(new WadlModelProcessor()).to(ModelProcessor.class);
+//            }
+//        });
+        assertMultiple(ModelProcessor.class, 2, WadlModelProcessor.class.getSimpleName(),
+                OptionsMethodProcessor.class.getSimpleName());
+    }
+
+    @Test
+    public void testWadlContext() {
+        injectionManager.register(new AbstractBinder() {
+            @Override
+            protected void configure() {
+                bind(new ResourceConfig()).to(ServerConfig.class).to(Configuration.class).id(1000);
+                bind(new JerseyResourceContext(null, null, null)).to(ResourceContext.class).id(3112);
+                bind(WadlApplicationContextImpl.class).to(WadlApplicationContext.class).in(Singleton.class);
+            }
+        });
+        injectionManager.completeRegistration();
+        assertOneInstance(WadlApplicationContext.class, WadlApplicationContextImpl.class.getSimpleName());
+    }
+}
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/server/ServerBindingsTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/server/ServerBindingsTest.java
new file mode 100644
index 0000000..a6a6849
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/binder/server/ServerBindingsTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * 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.binder.server;
+
+import org.glassfish.jersey.inject.weld.TestParent;
+import org.glassfish.jersey.inject.weld.binder.client.ClientOnlyPreinitialization;
+import org.glassfish.jersey.internal.inject.ServiceHolder;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+public class ServerBindingsTest extends TestParent {
+    @Test
+    void clientOnlyInstancesTest() {
+        injectionManager.completeRegistration();
+        List<ClientOnlyPreinitialization.ClientOnlyInterface> instances =
+                injectionManager.getAllInstances(ClientOnlyPreinitialization.ClientOnlyInterface.class);
+        Assertions.assertEquals(2, instances.size());
+        Assertions.assertTrue(instances.stream()
+                .anyMatch(p -> p.getClass().equals(ClientOnlyPreinitialization.ClientOnlyClassA.class)));
+        Assertions.assertTrue(instances.stream()
+                .anyMatch(p -> p.getClass().equals(ClientOnlyPreinitialization.ClientOnlyClassB.class)));
+    }
+
+    @Test
+    void clientOnlyServiceHoldersTest() {
+        injectionManager.completeRegistration();
+        List<ServiceHolder<ClientOnlyPreinitialization.ClientOnlyInterface>> instances =
+                injectionManager.getAllServiceHolders(ClientOnlyPreinitialization.ClientOnlyInterface.class);
+        Assertions.assertEquals(2, instances.size());
+        Assertions.assertTrue(instances.stream()
+                .anyMatch(p -> p.getInstance().getClass().equals(ClientOnlyPreinitialization.ClientOnlyClassA.class)));
+        Assertions.assertTrue(instances.stream()
+                .anyMatch(p -> p.getInstance().getClass().equals(ClientOnlyPreinitialization.ClientOnlyClassB.class)));
+    }
+}
\ No newline at end of file
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/CachedConstructorAnalyzerTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/CachedConstructorAnalyzerTest.java
index 85bfe56..1b0f4f7 100644
--- a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/CachedConstructorAnalyzerTest.java
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/injector/CachedConstructorAnalyzerTest.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
@@ -23,7 +23,6 @@
 
 import jakarta.enterprise.inject.InjectionException;
 import jakarta.ws.rs.MatrixParam;
-import jakarta.ws.rs.NotFoundException;
 import jakarta.ws.rs.PathParam;
 import jakarta.ws.rs.core.Context;
 
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ClientInstanceInjectionTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ClientInstanceInjectionTest.java
index afb04b8..d7dbfbc 100644
--- a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ClientInstanceInjectionTest.java
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ClientInstanceInjectionTest.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
@@ -21,6 +21,7 @@
 import jakarta.inject.Inject;
 import jakarta.ws.rs.RuntimeType;
 
+import org.glassfish.jersey.inject.weld.TestParent;
 import org.glassfish.jersey.inject.weld.managed.CdiInjectionManagerFactory;
 import org.glassfish.jersey.internal.inject.InjectionManager;
 import org.junit.jupiter.api.Assertions;
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/DisposableSupplierTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/DisposableSupplierTest.java
index ee96847..7efa92e 100644
--- a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/DisposableSupplierTest.java
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/DisposableSupplierTest.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
@@ -27,6 +27,7 @@
 import jakarta.inject.Inject;
 import jakarta.ws.rs.core.GenericType;
 
+import org.glassfish.jersey.inject.weld.TestParent;
 import org.glassfish.jersey.inject.weld.internal.bean.BeanHelper;
 import org.glassfish.jersey.internal.inject.DisposableSupplier;
 import org.glassfish.jersey.process.internal.RequestScope;
@@ -346,7 +347,7 @@
 
     /**
      * PerLookup fields are not disposed therefore they should never be used as a DisposedSupplier because the field stay in
-     * {@link org.glassfish.jersey.inject.weld.bean.SupplierClassBean} forever.
+     * {@link org.glassfish.jersey.inject.weld.internal.bean.SupplierClassBean} forever.
      */
     @Test
     public void testDisposeComposedObjectWithPerLookupFields() {
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/InjectionManagerTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/InjectionManagerTest.java
index 7be66d9..f3f6dda 100644
--- a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/InjectionManagerTest.java
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/InjectionManagerTest.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
@@ -20,6 +20,7 @@
 import jakarta.inject.Inject;
 import jakarta.ws.rs.RuntimeType;
 
+import org.glassfish.jersey.inject.weld.TestParent;
 import org.glassfish.jersey.inject.weld.managed.CdiInjectionManagerFactory;
 import org.glassfish.jersey.internal.inject.InjectionManager;
 import org.junit.jupiter.api.Assertions;
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ProviderInjectionTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ProviderInjectionTest.java
index 42aadeb..d43f11c 100644
--- a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ProviderInjectionTest.java
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/ProviderInjectionTest.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
@@ -26,6 +26,7 @@
 import jakarta.inject.Provider;
 import jakarta.ws.rs.core.Context;
 
+import org.glassfish.jersey.inject.weld.TestParent;
 import org.glassfish.jersey.internal.inject.AbstractBinder;
 
 import org.hamcrest.core.StringStartsWith;
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierClassBindingTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierClassBindingTest.java
index 7db2804..e8e9cab 100644
--- a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierClassBindingTest.java
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierClassBindingTest.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
@@ -27,6 +27,7 @@
 import jakarta.inject.Inject;
 import jakarta.inject.Singleton;
 
+import org.glassfish.jersey.inject.weld.TestParent;
 import org.glassfish.jersey.internal.inject.AbstractBinder;
 
 import org.hamcrest.core.StringStartsWith;
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierInstanceBindingTest.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierInstanceBindingTest.java
index 9c247a9..fe758f8 100644
--- a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierInstanceBindingTest.java
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/SupplierInstanceBindingTest.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
@@ -28,6 +28,7 @@
 import jakarta.inject.Inject;
 import jakarta.ws.rs.core.GenericType;
 
+import org.glassfish.jersey.inject.weld.TestParent;
 import org.glassfish.jersey.internal.inject.AbstractBinder;
 
 import org.hamcrest.core.StringStartsWith;
diff --git a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestParent.java b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestParent.java
index e3013fe..e69de29 100644
--- a/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestParent.java
+++ b/incubator/cdi-inject-weld/src/test/java/org/glassfish/jersey/inject/weld/internal/managed/TestParent.java
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2021, 2022 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.managed;
-
-import jakarta.enterprise.inject.se.SeContainer;
-import jakarta.enterprise.inject.se.SeContainerInitializer;
-import org.glassfish.jersey.internal.inject.InjectionManager;
-import org.glassfish.jersey.internal.inject.Injections;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.BeforeAll;
-
-public class TestParent {
-    protected static SeContainer container;
-    protected InjectionManager injectionManager;
-
-
-    @BeforeAll
-    public static void setup() {
-        SeContainerInitializer containerInitializer = SeContainerInitializer.newInstance();
-        container = containerInitializer.initialize();
-    }
-
-    @BeforeEach
-    public void init() {
-        injectionManager = Injections.createInjectionManager();
-    }
-
-    @AfterAll
-    public static void tearDown() throws Exception {
-        container.close();
-    }
-
-}
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..6978e2f 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
@@ -22,10 +22,11 @@
 
 import org.glassfish.jersey.inject.weld.spi.BootstrapPreinitialization;
 import org.glassfish.jersey.internal.inject.AbstractBinder;
+import org.glassfish.jersey.internal.inject.InjectionManager;
 import org.glassfish.jersey.internal.inject.PerThread;
 import org.glassfish.jersey.process.internal.RequestScoped;
 
-public class TestPreinitialization implements BootstrapPreinitialization {
+public class TestPreinitialization implements BootstrapPreinitialization, org.glassfish.jersey.innate.BootstrapPreinitialization {
     @Override
     public void register(RuntimeType runtimeType, AbstractBinder binder) {
         if (RuntimeType.CLIENT == runtimeType) {
@@ -33,6 +34,7 @@
             {
                 binder.bindFactory(ClientInstanceInjectionTest.InjectableClientServerSupplierClient.class)
                         .to(ClientInstanceInjectionTest.InjectableClientServer.class);
+                binder.bindAsContract(ClientInstanceInjectionTest.InjectedBean.class);
             }
             return;
         }
@@ -113,4 +115,8 @@
                     .to(ClientInstanceInjectionTest.InjectableClientServer.class);
         }
     }
+
+    @Override
+    public void preregister(RuntimeType runtimeType, InjectionManager registrator) {
+    }
 }
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..4df5aa0 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
@@ -25,6 +25,7 @@
 import jakarta.inject.Inject;
 import jakarta.inject.Singleton;
 
+import org.glassfish.jersey.inject.weld.TestParent;
 import org.glassfish.jersey.internal.inject.PerThread;
 import org.glassfish.jersey.process.internal.RequestScope;
 
diff --git a/incubator/cdi-inject-weld/src/test/resources/META-INF/services/org.glassfish.jersey.innate.BootstrapPreinitialization b/incubator/cdi-inject-weld/src/test/resources/META-INF/services/org.glassfish.jersey.innate.BootstrapPreinitialization
new file mode 100644
index 0000000..f47d280
--- /dev/null
+++ b/incubator/cdi-inject-weld/src/test/resources/META-INF/services/org.glassfish.jersey.innate.BootstrapPreinitialization
@@ -0,0 +1,2 @@
+org.glassfish.jersey.inject.weld.binder.client.ClientOnlyPreinitialization
+org.glassfish.jersey.inject.weld.internal.managed.TestPreinitialization
\ No newline at end of file
diff --git a/incubator/injectless-client/src/main/java/org/glassfish/jersey/inject/injectless/NonInjectionManagerFactory.java b/incubator/injectless-client/src/main/java/org/glassfish/jersey/inject/injectless/NonInjectionManagerFactory.java
index 61e6455..b9033f2 100644
--- a/incubator/injectless-client/src/main/java/org/glassfish/jersey/inject/injectless/NonInjectionManagerFactory.java
+++ b/incubator/injectless-client/src/main/java/org/glassfish/jersey/inject/injectless/NonInjectionManagerFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2024 Oracle and/or its affiliates. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0, which is available at
@@ -22,6 +22,7 @@
 import jakarta.annotation.Priority;
 import jakarta.inject.Inject;
 import jakarta.ws.rs.ConstrainedTo;
+import jakarta.ws.rs.core.Configuration;
 import jakarta.ws.rs.core.Context;
 import jakarta.ws.rs.RuntimeType;
 
@@ -44,4 +45,9 @@
     public InjectionManager create(Object parent) {
         return new NonInjectionManager(false);
     }
+
+    @Override
+    public InjectionManager create(Object parent, Configuration configuration) {
+        return create(parent); // RuntimeType is always client
+    }
 }
diff --git a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/CdiSeInjectionManagerFactory.java b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/CdiSeInjectionManagerFactory.java
index e1c79a0..128e40f 100644
--- a/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/CdiSeInjectionManagerFactory.java
+++ b/inject/cdi2-se/src/main/java/org/glassfish/jersey/inject/cdi/se/CdiSeInjectionManagerFactory.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,6 +17,7 @@
 package org.glassfish.jersey.inject.cdi.se;
 
 import jakarta.annotation.Priority;
+import jakarta.ws.rs.core.Configuration;
 
 import org.glassfish.jersey.internal.inject.InjectionManager;
 import org.glassfish.jersey.internal.inject.InjectionManagerFactory;
@@ -33,4 +34,9 @@
     public InjectionManager create(Object parent) {
         return new CdiSeInjectionManager();
     }
+
+    @Override
+    public InjectionManager create(Object parent, Configuration configuration) {
+        return create(parent); // no configuration used at the moment
+    }
 }
diff --git a/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/Hk2InjectionManagerFactory.java b/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/Hk2InjectionManagerFactory.java
index ce30dd1..9a8dcf0 100644
--- a/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/Hk2InjectionManagerFactory.java
+++ b/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/Hk2InjectionManagerFactory.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
@@ -19,6 +19,7 @@
 import java.security.AccessController;
 
 import jakarta.annotation.Priority;
+import jakarta.ws.rs.core.Configuration;
 
 import org.glassfish.jersey.internal.inject.Bindings;
 import org.glassfish.jersey.internal.inject.InjectionManager;
@@ -73,6 +74,11 @@
         return initInjectionManager(getStrategy().createInjectionManager(parent));
     }
 
+    @Override
+    public InjectionManager create(Object parent, Configuration configuration) {
+        return create(parent); // ignore configuration for HK2
+    }
+
     /**
      * Check HK2 Strategy property {@link #HK2_INJECTION_MANAGER_STRATEGY} and returns {@code true} if the current HK2 Strategy is
      * "immediate".
diff --git a/media/sse/src/main/java/org/glassfish/jersey/media/sse/internal/SseBootstrapPreinitialization.java b/media/sse/src/main/java/org/glassfish/jersey/media/sse/internal/SseBootstrapPreinitialization.java
new file mode 100644
index 0000000..19970b2
--- /dev/null
+++ b/media/sse/src/main/java/org/glassfish/jersey/media/sse/internal/SseBootstrapPreinitialization.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.media.sse.internal;
+
+import org.glassfish.jersey.innate.BootstrapPreinitialization;
+import org.glassfish.jersey.internal.inject.InjectionManager;
+
+import jakarta.ws.rs.RuntimeType;
+
+public class SseBootstrapPreinitialization implements BootstrapPreinitialization {
+    @Override
+    public void preregister(RuntimeType runtimeType, InjectionManager injectionManager) {
+        if (runtimeType == RuntimeType.SERVER) {
+            injectionManager.register(new SseBinder());
+        }
+    }
+}
diff --git a/media/sse/src/main/resources/META-INF/services/org.glassfish.jersey.innate.BootstrapPreinitialization b/media/sse/src/main/resources/META-INF/services/org.glassfish.jersey.innate.BootstrapPreinitialization
new file mode 100644
index 0000000..d41c8b7
--- /dev/null
+++ b/media/sse/src/main/resources/META-INF/services/org.glassfish.jersey.innate.BootstrapPreinitialization
@@ -0,0 +1 @@
+org.glassfish.jersey.media.sse.internal.SseBootstrapPreinitialization
\ No newline at end of file
diff --git a/test-framework/core/src/main/java/org/glassfish/jersey/test/JerseySingleContainerTest.java b/test-framework/core/src/main/java/org/glassfish/jersey/test/JerseySingleContainerTest.java
new file mode 100644
index 0000000..252bdfd
--- /dev/null
+++ b/test-framework/core/src/main/java/org/glassfish/jersey/test/JerseySingleContainerTest.java
@@ -0,0 +1,1007 @@
+/*
+ * Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * 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.test;
+
+import org.glassfish.jersey.Beta;
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.internal.ServiceFinder;
+import org.glassfish.jersey.internal.util.PropertiesHelper;
+import org.glassfish.jersey.internal.util.ReflectionHelper;
+import org.glassfish.jersey.logging.LoggingFeature;
+import org.glassfish.jersey.test.spi.TestContainer;
+import org.glassfish.jersey.test.spi.TestContainerException;
+import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeEach;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.UriBuilder;
+import java.net.URI;
+import java.security.AccessController;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogManager;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+/**
+ * Parent class for testing JAX-RS and Jersey-based applications using Jersey test framework.
+ * <p>
+ * At construction this class will obtain a {@link TestContainerFactory
+ * test container factory} implementation.
+ * </p>
+ * <p>
+ * Before each test method in an extending class is run the test container factory is used to obtain
+ * a configured {@link TestContainer test container}.
+ * Then the {@link TestContainer#start()} method is invoked on the configured test container. After each test method
+ * has run, the {@link TestContainer#stop()} method is invoked on the test container. Stopped test container
+ * generally shouldn't be again started for another test, rather a new test container should be created.
+ * Every test method in the {@code JerseyTest} subclass can invoke the {@link #client()} to obtain a JAX-RS
+ * {@link Client}, from which {@link WebTarget} instances can be created
+ * to send arbitrary requests.
+ * Also, one of the {@code target} methods ({@link #target()} or {@link #target(String)}) may be invoked to obtain
+ * a JAX-RS {@link WebTarget} instances from which requests can be sent to and responses
+ * received from the Web application under test.
+ * </p>
+ * <p>
+ * If a test container factory is not explicitly declared using the appropriate constructor
+ * (see {@link #JerseySingleContainerTest(TestContainerFactory)}) or by overriding the {@link #getTestContainerFactory()} method,
+ * then a default test container factory will be obtained as follows:
+ * <ol>
+ * <li>
+ * If a system property <tt>{@value TestProperties#CONTAINER_FACTORY}</tt> is set
+ * and the value is a fully qualified class name of a class that extends from {@code TestContainerFactory}
+ * then the test container factory used by default will be an instance of that class.
+ * A {@link TestContainerException} will be thrown if the class cannot be loaded or instantiated.
+ * </li>
+ * <li>
+ * Otherwise, {@code META-INF/services} locations on the class path will be scanned for implementation providers
+ * of {@code TestContainerFactory} SPI. If a single implementation is found, it will be used. If multiple implementations
+ * are found, the default <tt>{@value TestProperties#CONTAINER_FACTORY}</tt> implementation
+ * will be selected if present, otherwise the first found implementation will be selected and a warning message will be logged.
+ * </li>
+ * <li>
+ * If no {@code TestContainerFactory} has been selected in the steps above, Jersey test framework will try to
+ * instantiate the default test container factory implementation (
+ * <tt>{@value TestProperties#DEFAULT_CONTAINER_FACTORY}</tt>) directly.
+ * A {@link TestContainerException} will be thrown if this class cannot be loaded or instantiated.
+ * </li>
+ * </ol>
+ * </p>
+ * <p>
+ * The test container is configured by a {@link DeploymentContext} that is either provided
+ * by  subclass or automatically created by {@code JerseyTest} based on the provided JAX-RS / Jersey {@code Application}
+ * class or instance to be tested. A {@link TestContainerException} will be thrown if the configured test container
+ * factory cannot support the deployment context type.
+ * Two deployment context are provided:
+ * <ol>
+ * <li>A basic deployment context, of type {@link DeploymentContext}, compatible with all test containers that are not
+ * based on Servlet deployment model.</li>
+ * <li>A Servlet-based deployment context, of type {@link ServletDeploymentContext}, compatible with Servlet-based test
+ * containers.</li>
+ * </ol>
+ * </p>
+ *
+ * @author Paul Sandoz
+ * @author Srinivas Bhimisetty
+ * @author Pavel Bucek
+ * @author Michal Gajdos
+ * @author Marek Potociar
+ */
+@Beta
+public abstract class JerseySingleContainerTest {
+
+    private static final ThreadLocal<JerseySingleContainerTest> INSTANCE = new ThreadLocal<>();
+
+    private static final Logger LOGGER = Logger.getLogger(JerseySingleContainerTest.class.getName());
+
+    /**
+     * Holds the test container factory class to be used for running the tests by default
+     * (if testContainerFactory has not been set).
+     * This static field is initialized in {@link #getDefaultTestContainerFactory()} method
+     * and is reused by any instances of {@code JerseyTest} that are subsequently run.
+     * This is done to optimize the number of TestContainerFactory service provider look-ups
+     * and class loading.
+     */
+    private static Class<? extends TestContainerFactory> defaultTestContainerFactoryClass;
+
+    /**
+     * Configured deployment context for the tested application.
+     */
+    private final DeploymentContext context;
+
+    /**
+     * The test container factory which creates an instance of the test container
+     * on which the tests would be run.
+     */
+    private TestContainerFactory testContainerFactory;
+
+    /**
+     * The test container on which the tests would be run.
+     */
+    private TestContainer testContainer;
+
+    private final AtomicReference<Client> client = new AtomicReference<>(null);
+
+    /**
+     * JerseyTest property bag that can be used to configure the test behavior.
+     * These properties can be overridden with a system property.
+     */
+    private final Map<String, String> propertyMap = new HashMap<>();
+
+    /**
+     * JerseyTest forced property bag that can be used to configure the test behavior.
+     * These property cannot be overridden with a system property.
+     */
+    private final Map<String, String> forcedPropertyMap = new HashMap<>();
+
+    private JerseyTestLogHandler logHandler;
+    private final Map<Logger, Level> logLevelMap = new IdentityHashMap<>();
+    private final AtomicInteger activeThreadCount = new AtomicInteger(0);
+
+    /**
+     * Initialize JerseyTest instance.
+     * <p>
+     * This constructor can be used from an extending subclass.
+     * <p>
+     * When this constructor is used, the extending concrete subclass must implement one of the
+     * {@link #configure()} or {@link #configureDeployment()} methods to provide the tested application
+     * configuration and deployment context.
+     * </p>
+     */
+    public JerseySingleContainerTest() {
+        // Note: this must be the first call in the constructor to allow setting config
+        // properties (especially around logging) in the configure() or configureDeployment()
+        // method overridden in subclass, otherwise the properties set in the subclass would
+        // not be set soon enough
+        this.context = configureDeployment();
+        this.testContainerFactory = getTestContainerFactory();
+    }
+
+    /**
+     * Initialize JerseyTest instance and specify the test container factory to be used by this test.
+     * <p>
+     * This constructor can be used from an extending subclass.
+     * <p>
+     * When this constructor is used, the extending concrete subclass must implement one of the
+     * {@link #configure()} or {@link #configureDeployment()} methods to provide the tested application
+     * configuration and deployment context.
+     * </p>
+     *
+     * @param testContainerFactory the test container factory to use for testing.
+     */
+    public JerseySingleContainerTest(final TestContainerFactory testContainerFactory) {
+        // Note: this must be the first call in the constructor to allow setting config
+        // properties (especially around logging) in the configure() or configureDeployment()
+        // method overridden in subclass, otherwise the properties set in the subclass would
+        // not be set soon enough
+        this.context = configureDeployment();
+        this.testContainerFactory = testContainerFactory;
+    }
+
+    /**
+     * Initialize JerseyTest instance.
+     * <p>
+     * This constructor can be used from an extending subclass.
+     * <p>
+     * When this constructor is used, the extending concrete subclass must implement one of the
+     * {@link #configure()} or {@link #configureDeployment()} methods are ignored.
+     * </p>
+     * <p>
+     * Please note that when this constructor is used, recording of startup logs as well as configuring
+     * other {@code JerseyTest} properties and features may not work properly. While using this constructor
+     * should generally be avoided, in certain scenarios it may be necessary to use this constructor.
+     * (E.g. when running parameterized tests in which application is created based on test parameters
+     * passed in by JUnit framework via test constructor - in such case it is not possible to propagate
+     * the necessary information to one of the overridden {@code JerseyTest.configure...} methods).
+     * </p>
+     *
+     * @param jaxrsApplication tested application.
+     */
+    public JerseySingleContainerTest(final Application jaxrsApplication) {
+        this.context = DeploymentContext.newInstance(jaxrsApplication);
+        this.testContainerFactory = getTestContainerFactory();
+    }
+
+    /**
+     * Return currently used test container to run the tests in. This method can be overridden.
+     *
+     * @return a test container instance or {@code null} if the container is not set.
+     */
+    /* package */ TestContainer getTestContainer() {
+        return testContainer;
+    }
+
+    /**
+     * Returns old test container used to run the tests in and set a new one. This method can be overridden.
+     *
+     * @param testContainer a test container instance or {@code null} it the current test container should be released.
+     * @return old test container instance.
+     */
+    /* package */ TestContainer setTestContainer(final TestContainer testContainer) {
+        final TestContainer old = this.testContainer;
+        this.testContainer = testContainer;
+        return old;
+    }
+
+    private TestContainer createTestContainer(final DeploymentContext context) {
+        return getTestContainerFactory().create(getBaseUri(), context);
+    }
+
+    /**
+     * Programmatically enable a feature with a given name.
+     * Enabling of the feature may be overridden via a system property.
+     *
+     * @param featureName name of the enabled feature.
+     */
+    protected final void enable(final String featureName) {
+        // TODO: perhaps we could reuse the resource config for the test properties?
+        propertyMap.put(featureName, Boolean.TRUE.toString());
+    }
+
+    /**
+     * Programmatically disable a feature with a given name.
+     * Disabling of the feature may be overridden via a system property.
+     *
+     * @param featureName name of the disabled feature.
+     */
+    protected final void disable(final String featureName) {
+        propertyMap.put(featureName, Boolean.FALSE.toString());
+    }
+
+    /**
+     * Programmatically force-enable a feature with a given name.
+     * Force-enabling of the feature cannot be overridden via a system property.
+     * Use with care!
+     *
+     * @param featureName name of the force-enabled feature.
+     */
+    protected final void forceEnable(final String featureName) {
+        forcedPropertyMap.put(featureName, Boolean.TRUE.toString());
+    }
+
+    /**
+     * Programmatically force-disable a feature with a given name.
+     * Force-disabling of the feature cannot be overridden via a system property.
+     * Use with care!
+     *
+     * @param featureName name of the force-disabled feature.
+     */
+    protected final void forceDisable(final String featureName) {
+        forcedPropertyMap.put(featureName, Boolean.FALSE.toString());
+    }
+
+    /**
+     * Programmatically set a value of a property with a given name.
+     * The property value may be overridden via a system property.
+     *
+     * @param propertyName name of the property.
+     * @param value        property value.
+     */
+    protected final void set(final String propertyName, final Object value) {
+        set(propertyName, value.toString());
+    }
+
+    /**
+     * Programmatically set a value of a property with a given name.
+     * The property value may be overridden via a system property.
+     *
+     * @param propertyName name of the property.
+     * @param value        property value.
+     */
+    protected final void set(final String propertyName, final String value) {
+        propertyMap.put(propertyName, value);
+    }
+
+    /**
+     * Programmatically force-set a value of a property with a given name.
+     * The force-set property value cannot be overridden via a system property.
+     *
+     * @param propertyName name of the property.
+     * @param value        property value.
+     */
+    protected final void forceSet(final String propertyName, final String value) {
+        forcedPropertyMap.put(propertyName, value);
+    }
+
+    /**
+     * Check if the Jersey test boolean property (flag) has been set to {@code true}.
+     *
+     * @param propertyName name of the Jersey test boolean property.
+     * @return {@code true} if the test property has been enabled, {@code false} otherwise.
+     */
+    protected final boolean isEnabled(final String propertyName) {
+        return Boolean.valueOf(getProperty(propertyName));
+    }
+
+    private String getProperty(final String propertyName) {
+        if (forcedPropertyMap.containsKey(propertyName)) {
+            return forcedPropertyMap.get(propertyName);
+        }
+
+        final Properties systemProperties = AccessController.doPrivileged(PropertiesHelper.getSystemProperties());
+        if (systemProperties.containsKey(propertyName)) {
+            return systemProperties.getProperty(propertyName);
+        }
+
+        if (propertyMap.containsKey(propertyName)) {
+            return propertyMap.get(propertyName);
+        }
+
+        return null;
+    }
+
+    private static String getSystemProperty(final String propertyName) {
+        final Properties systemProperties = AccessController.doPrivileged(PropertiesHelper.getSystemProperties());
+        return systemProperties.getProperty(propertyName);
+    }
+
+    /**
+     * Create the tested JAX-RS /Jersey application.
+     * <p>
+     * This method may be overridden by subclasses to provide the configured JAX-RS /Jersey application to be tested.
+     * The method may be also used to configure {@code JerseyTest} instance properties.
+     * <p>
+     * Unless {@link #configureDeployment()} method is overridden in the subclass, the {@code configure()} method is invoked
+     * by {@code configureDeployment()} to create default deployment context for the tested application. As such, the method
+     * is invoked in the scope of one of the {@code JerseyTest} constructors.
+     * Default implementation of this method throws {@link UnsupportedOperationException}, so that construction of
+     * {@code JerseyTest} instance fails unless one of the {@code configure()} or {@code configureDeployment()} methods is
+     * overridden in the subclass.
+     * </p>
+     * <p>
+     * Note that since the method is invoked from {@code JerseyTest} constructor, the overriding implementation of the method
+     * must not depend on any subclass fields as those will not be initialized yet when the method is invoked.
+     * </p>
+     * <p>
+     * Also note that in case the {@link #JerseySingleContainerTest(Application)} constructor is used, the method is never
+     * invoked.
+     * </p>
+     *
+     * @return tested JAX-RS /Jersey application.
+     */
+    protected Application configure() {
+        throw new UnsupportedOperationException("The configure method must be implemented by the extending class");
+    }
+
+    /**
+     * Create and configure deployment context for the tested application.
+     * <p>
+     * This method may be overridden by subclasses to provide custom test container deployment context for the tested
+     * application. The method may be also used to configure {@code JerseyTest} instance properties.
+     * <p>
+     * The method is invoked from {@code JerseyTest} constructors to provide deployment context for the tested application.
+     * Default implementation of this method creates
+     * {@link DeploymentContext#newInstance(Application) new deployment context}
+     * using JAX-RS application instance obtained by calling the {@link #configure()} method.
+     * </p>
+     * <p>
+     * Note that since the method is invoked from {@code JerseyTest} constructor, the overriding implementation of the method
+     * must not depend on any subclass fields as those will not be initialized yet when the method is invoked.
+     * </p>
+     * <p>
+     * Also note that in case the {@link #JerseySingleContainerTest(Application)} constructor is used, the method is never
+     * invoked.
+     * </p>
+     *
+     * @return configured deployment context for the tested application.
+     * @since 2.8
+     */
+    protected DeploymentContext configureDeployment() {
+        DeploymentContext.Builder contextBuilder = DeploymentContext.builder(configure());
+        if (getSslContext().isPresent() && getSslParameters().isPresent()) {
+            contextBuilder.ssl(getSslContext().get(), getSslParameters().get());
+        }
+        return contextBuilder.build();
+    }
+
+    /**
+     * Return an instance of {@link TestContainerFactory} class.
+     * <p>
+     * <p>
+     * This method is used only once during {@code JerseyTest} instance construction to retrieve the factory responsible
+     * for providing {@link TestContainer} that will be used to deploy the tested application.
+     * </p>
+     * <p>
+     * A default implementation first searches for the {@code TestContainerFactory} set via
+     * {@link #JerseySingleContainerTest(TestContainerFactory) constructor}, then it looks for a
+     * {@code TestContainerFactory} implementation class name set via
+     * <tt>{@value TestProperties#CONTAINER_FACTORY}</tt> system property with a fallback to
+     * searching for {@code TestContainerFactory} service providers on the class path. At last, if no
+     * {@code TestContainerFactory} has been found, the method attempts to create new default
+     * {@code TestContainerFactory} implementation instance
+     * (<tt>{@value TestProperties#DEFAULT_CONTAINER_FACTORY}</tt>).
+     * </p>
+     * <p>
+     * Alternatively, this method may be overridden to directly provide a custom {@code TestContainerFactory} instance.
+     * Note that since the method is invoked from {@code JerseyTest} constructor, the overriding implementation of the method
+     * must not depend on any subclass fields as those will not be initialized yet when the method is invoked.
+     * </p>
+     *
+     * @return an instance of {@link TestContainerFactory} class.
+     * @throws TestContainerException if the initialization of {@link TestContainerFactory} instance is not successful.
+     */
+    protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
+        if (testContainerFactory == null) {
+            testContainerFactory = getDefaultTestContainerFactory();
+        }
+        return testContainerFactory;
+    }
+
+    /**
+     * Return an optional instance of {@link SSLContext} class.
+     * <p>
+     * <p>
+     * This method is used only once during {@code JerseyTest} instance construction to retrieve the ssl configuration.
+     * By default the ssl configuration is absent, to enable it please override this method and {@link JerseySingleContainerTest#getSslParameters()}
+     * </p>
+     * </p>
+     * @return an optional instance of {@link SSLContext} class.
+     */
+    protected Optional<SSLContext> getSslContext() {
+        return Optional.empty();
+    }
+
+    /**
+     * Return an optional instance of {@link SSLParameters} class.
+     * <p>
+     * <p>
+     * This method is used only once during {@code JerseyTest} instance construction to retrieve the ssl configuration.
+     * By default the ssl configuration is absent, to enable it please override this method and {@link JerseySingleContainerTest#getSslContext()} ()}
+     * </p>
+     * </p>
+     * @return an optional instance of {@link SSLContext} class.
+     */
+    protected Optional<SSLParameters> getSslParameters() {
+        return Optional.empty();
+    }
+
+    private static synchronized TestContainerFactory getDefaultTestContainerFactory() {
+
+        if (defaultTestContainerFactoryClass == null) {
+            final String factoryClassName = getSystemProperty(TestProperties.CONTAINER_FACTORY);
+            if (factoryClassName != null) {
+                LOGGER.log(Level.CONFIG,
+                        "Loading test container factory '{0}' specified in the '{1}' system property.",
+                        new Object[] {factoryClassName, TestProperties.CONTAINER_FACTORY});
+
+                defaultTestContainerFactoryClass = loadFactoryClass(factoryClassName);
+            } else {
+                final TestContainerFactory[] factories = ServiceFinder.find(TestContainerFactory.class).toArray();
+                if (factories.length > 0) {
+                    // if there is only one factory instance, just return it
+                    if (factories.length == 1) {
+                        // cache the class for future reuse
+                        defaultTestContainerFactoryClass = factories[0].getClass();
+                        LOGGER.log(
+                                Level.CONFIG,
+                                "Using the single found TestContainerFactory service provider '{0}'",
+                                defaultTestContainerFactoryClass.getName());
+                        return factories[0];
+                    }
+
+                    // if default factory is present, use it.
+                    for (final TestContainerFactory tcf : factories) {
+                        if (TestProperties.DEFAULT_CONTAINER_FACTORY.equals(tcf.getClass().getName())) {
+                            // cache the class for future reuse
+                            defaultTestContainerFactoryClass = tcf.getClass();
+                            LOGGER.log(
+                                    Level.CONFIG,
+                                    "Found multiple TestContainerFactory service providers, using the default found '{0}'",
+                                    TestProperties.DEFAULT_CONTAINER_FACTORY);
+                            return tcf;
+                        }
+                    }
+
+                    // default factory is not in the list - log warning and return the first found factory instance
+                    // cache the class for future reuse
+                    defaultTestContainerFactoryClass = factories[0].getClass();
+                    LOGGER.log(
+                            Level.WARNING,
+                            "Found multiple TestContainerFactory service providers, using the first found '{0}'",
+                            defaultTestContainerFactoryClass.getName());
+                    return factories[0];
+                }
+
+                LOGGER.log(
+                        Level.CONFIG,
+                        "No TestContainerFactory configured, trying to load and instantiate the default implementation '{0}'",
+                        TestProperties.DEFAULT_CONTAINER_FACTORY);
+                defaultTestContainerFactoryClass = loadFactoryClass(TestProperties.DEFAULT_CONTAINER_FACTORY);
+            }
+        }
+
+        try {
+            return defaultTestContainerFactoryClass.newInstance();
+        } catch (final Exception ex) {
+            throw new TestContainerException(String.format(
+                    "Could not instantiate test container factory '%s'", defaultTestContainerFactoryClass.getName()), ex);
+        }
+    }
+
+    private static Class<? extends TestContainerFactory> loadFactoryClass(final String factoryClassName) {
+        Class<? extends TestContainerFactory> factoryClass;
+        final Class<Object> loadedClass = AccessController.doPrivileged(ReflectionHelper.classForNamePA(factoryClassName, null));
+        if (loadedClass == null) {
+            throw new TestContainerException(String.format(
+                    "Test container factory class '%s' cannot be loaded", factoryClassName));
+        }
+        try {
+            return loadedClass.asSubclass(TestContainerFactory.class);
+        } catch (final ClassCastException ex) {
+            throw new TestContainerException(String.format(
+                    "Class '%s' does not implement TestContainerFactory SPI.", factoryClassName), ex);
+        }
+    }
+
+    /**
+     * Create a JAX-RS web target whose URI refers to the {@link #getBaseUri() base URI} the tested
+     * JAX-RS / Jersey application is deployed at, plus the path specified in the {@code path} argument.
+     * <p>
+     * This method is an equivalent of calling <tt>client().target(getBaseUri())</tt>.
+     * </p>
+     *
+     * @return the created JAX-RS web target.
+     */
+    public final WebTarget target() {
+        return client().target(getTestContainer().getBaseUri());
+    }
+
+    /**
+     * Create a JAX-RS web target whose URI refers to the {@link #getBaseUri() base URI} the tested
+     * JAX-RS / Jersey application is deployed at, plus the path specified in the {@code path} argument.
+     * <p>
+     * This method is an equivalent of calling {@code target().path(path)}.
+     * </p>
+     *
+     * @param path relative path (from tested application base URI) this web target should point to.
+     * @return the created JAX-RS web target.
+     */
+    public final WebTarget target(final String path) {
+        return target().path(path);
+    }
+
+    /**
+     * Get the JAX-RS test client that is {@link #configureClient(ClientConfig) pre-configured}
+     * for this test.
+     *
+     * @return the configured test client.
+     */
+    public final Client client() {
+        return getClient();
+    }
+
+    /**
+     * Set up the test by creating a test container instance, {@link TestContainer#start() starting} it and by creating a new
+     * {@link #configureClient(ClientConfig) pre-configured} test client.
+     * The test container is obtained from the {@link #getTestContainerFactory() test container factory}.
+     *
+     * @throws TestContainerException if the default test container factory cannot be obtained,
+     *                                or the test application deployment context is not supported
+     *                                by the test container factory.
+     * @throws Exception              if an exception is thrown during setting up the test environment.
+     */
+    @BeforeEach
+    public void setUp() throws Exception {
+        synchronized (this) {
+            if (INSTANCE.get() == null) {
+                registerLogHandlerIfEnabled();
+                final TestContainer testContainer = createTestContainer(context);
+
+                // Set current instance of test container and start it.
+                setTestContainer(testContainer);
+                testContainer.start();
+
+                // Create and set new client.
+                setClient(getClient(testContainer.getClientConfig()));
+                INSTANCE.set(this);
+            }
+        }
+    }
+
+    /**
+     * Tear down the test by {@link TestContainer#stop() stopping} the test container obtained from the
+     * {@link #getTestContainerFactory() test container factory} and by {@link Client#close() closing}
+     * and discarding the {@link #configureClient(ClientConfig) pre-configured} test client
+     * that was {@link #setUp() set up} for the test.
+     *
+     * @throws Exception if an exception is thrown during tearing down the test environment.
+     */
+    public void tearDown() throws Exception {
+        if (isLogRecordingEnabled()) {
+            unregisterLogHandler();
+        }
+
+        try {
+            TestContainer oldContainer = setTestContainer(null);
+            if (oldContainer != null) {
+                oldContainer.stop();
+            }
+        } finally {
+            closeIfNotNull(setClient(null));
+        }
+    }
+
+    @AfterAll
+    public static void tearDownAll() throws Exception {
+        INSTANCE.get().tearDown();
+    }
+
+    /**
+     * Get the JAX-RS test client that is {@link #configureClient(ClientConfig) pre-configured}
+     * for this test. This method can be overridden.
+     *
+     * @return the configured test client.
+     */
+    protected Client getClient() {
+        return client.get();
+    }
+
+    /**
+     * Get the old JAX-RS test client and set a new one. This method can be overridden.
+     *
+     * @param client the configured test client.
+     * @return old configured test client.
+     */
+    protected Client setClient(final Client client) {
+        return this.client.getAndSet(client);
+    }
+
+    /**
+     * Create an instance of test {@link Client} using the client configuration provided by the configured
+     * {@link TestContainer}.
+     * <p>
+     * If the {@code TestContainer} does not provide any client configuration (passed {@code clientConfig} is {@code null}),
+     * the default implementation of this method first creates an empty new {@link ClientConfig}
+     * instance. The client configuration (provided by test container or created) is then passed to
+     * {@link #configureClient(ClientConfig)} which can be overridden in the {@code JerseyTest}
+     * subclass to provide custom client configuration. At last, new JAX-RS {@link Client} instance is created based on the
+     * resulting client configuration.
+     * </p>
+     *
+     * @param clientConfig test client default configuration. May be {@code null}.
+     * @return A Client instance.
+     */
+    private Client getClient(ClientConfig clientConfig) {
+        if (clientConfig == null) {
+            clientConfig = new ClientConfig();
+        }
+
+        //check if logging is required
+        if (isEnabled(TestProperties.LOG_TRAFFIC)) {
+            clientConfig.register(new LoggingFeature(LOGGER, isEnabled(TestProperties.DUMP_ENTITY)
+                    ? LoggingFeature.Verbosity.PAYLOAD_ANY
+                    : LoggingFeature.Verbosity.HEADERS_ONLY));
+
+        }
+
+        configureClient(clientConfig);
+
+        return ClientBuilder.newClient(clientConfig);
+    }
+
+    /**
+     * Configure the test client.
+     * <p>
+     * The method can be overridden by {@code JerseyTest} subclasses to conveniently configure the test client instance
+     * used by Jersey test framework (either returned from {@link #client()} method or used to create
+     * {@link WebTarget} instances returned from one of the {@code target} methods
+     * ({@link #target()} or {@link #target(String)}).
+     * <p>
+     * Prior to every test method run, a new client instance is configured and created using the client configuration
+     * provided by the {@link TestContainer} as well as any internal {@code JerseyTest}
+     * client configuration settings.
+     * </p>
+     * <p>
+     * Before the actual client instance creation, Jersey test framework invokes this method in order to allow the subclasses
+     * to further customize created client instance.
+     * </p>
+     * <p>
+     * After each test method is run, the existing client instance is {@link Client#close() closed}
+     * and discarded.
+     * </p>
+     * <p>
+     * Default implementation of the method is "no-op".
+     * </p>
+     *
+     * @param config Jersey test client configuration that can be modified before the client is created.
+     */
+    protected void configureClient(final ClientConfig config) {
+        // do nothing
+    }
+
+    /**
+     * Returns the base URI of the tested application.
+     *
+     * @return the base URI of the tested application.
+     */
+    // TODO make final
+    protected URI getBaseUri() {
+        final TestContainer container = getTestContainer();
+
+        if (container != null) {
+            // called from outside of JerseyTest constructor
+            return container.getBaseUri();
+        }
+
+        // called from within JerseyTest constructor
+        return UriBuilder.fromUri("http://localhost/").port(getPort()).build();
+    }
+
+    /**
+     * Get the port to be used for test application deployments.
+     *
+     * @return The HTTP port of the URI
+     */
+    protected final int getPort() {
+        final TestContainer container = getTestContainer();
+
+        if (container != null) {
+            // called from outside of JerseyTest constructor
+            return container.getBaseUri().getPort();
+        }
+
+        // called from within JerseyTest constructor
+        final String value = getProperty(TestProperties.CONTAINER_PORT);
+        if (value != null) {
+
+            try {
+                final int i = Integer.parseInt(value);
+                if (i < 0) {
+                    throw new NumberFormatException("Value not positive.");
+                }
+                return i;
+            } catch (final NumberFormatException e) {
+                LOGGER.log(Level.CONFIG,
+                        "Value of " + TestProperties.CONTAINER_PORT
+                                + " property is not a valid positive integer [" + value + "]."
+                                + " Reverting to default [" + TestProperties.DEFAULT_CONTAINER_PORT + "].",
+                        e
+                );
+            }
+        }
+        return TestProperties.DEFAULT_CONTAINER_PORT;
+    }
+
+    /**
+     * Get stored {@link LogRecord log records} if enabled by setting {@link TestProperties#RECORD_LOG_LEVEL} or an empty list.
+     *
+     * @return list of log records or an empty list.
+     */
+    protected final List<LogRecord> getLoggedRecords() {
+        return getLogHandler().getRecords();
+    }
+
+    /**
+     * Get last stored {@link LogRecord log record} if enabled by setting {@link TestProperties#RECORD_LOG_LEVEL}
+     * or {@code null}.
+     *
+     * @return last stored {@link LogRecord log record} or {@code null}.
+     */
+    protected final LogRecord getLastLoggedRecord() {
+        final List<LogRecord> loggedRecords = getLoggedRecords();
+        return loggedRecords.isEmpty() ? null : loggedRecords.get(loggedRecords.size() - 1);
+    }
+
+    /**
+     * Retrieves a list of root loggers.
+     *
+     * @return list of root loggers.
+     */
+    private Set<Logger> getRootLoggers() {
+        final LogManager logManager = LogManager.getLogManager();
+        final Enumeration<String> loggerNames = logManager.getLoggerNames();
+
+        final Set<Logger> rootLoggers = new HashSet<>();
+
+        while (loggerNames.hasMoreElements()) {
+            Logger logger = logManager.getLogger(loggerNames.nextElement());
+            if (logger != null) {
+                while (logger.getParent() != null) {
+                    logger = logger.getParent();
+                }
+                rootLoggers.add(logger);
+            }
+        }
+
+        return rootLoggers;
+    }
+
+    /**
+     * Register {@link Handler log handler} to the list of root loggers
+     * if log recording is enabled.
+     */
+    private void registerLogHandlerIfEnabled() {
+        if (isLogRecordingEnabled()) {
+            registerLogHandler();
+        }
+    }
+
+    /**
+     * Register {@link Handler log handler} to the list of root loggers.
+     */
+    private void registerLogHandler() {
+        final String recordLogLevel = getProperty(TestProperties.RECORD_LOG_LEVEL);
+        final int recordLogLevelInt = Integer.valueOf(recordLogLevel);
+        final Level level = Level.parse(recordLogLevel);
+
+        logLevelMap.clear();
+
+        for (final Logger root : getRootLoggers()) {
+            logLevelMap.put(root, root.getLevel());
+
+            if (root.getLevel().intValue() > recordLogLevelInt) {
+                root.setLevel(level);
+            }
+
+            root.addHandler(getLogHandler());
+        }
+    }
+
+    /**
+     * Un-register {@link Handler log handler} from the list of root loggers.
+     */
+    private void unregisterLogHandler() {
+        for (final Logger root : getRootLoggers()) {
+            root.setLevel(logLevelMap.get(root));
+            root.removeHandler(getLogHandler());
+        }
+        logHandler = null;
+    }
+
+    /**
+     * Return {@code true} if log recoding is enabled.
+     *
+     * @return {@code true} if log recoding is enabled, {@code false} otherwise.
+     */
+    private boolean isLogRecordingEnabled() {
+        return getProperty(TestProperties.RECORD_LOG_LEVEL) != null;
+    }
+
+    /**
+     * Retrieves {@link Handler log handler} capable of storing {@link LogRecord logged records}.
+     *
+     * @return log handler.
+     */
+    private JerseyTestLogHandler getLogHandler() {
+        if (logHandler == null) {
+            logHandler = new JerseyTestLogHandler();
+        }
+        return logHandler;
+    }
+
+    /**
+     * Returns {@link TestProperties#ASYNC_TIMEOUT_MULTIPLIER} or {@code 1} if the property is not defined.
+     *
+     * @return Multiplier of the async timeout for async test.
+     */
+    protected int getAsyncTimeoutMultiplier() {
+        final String property = getProperty(TestProperties.ASYNC_TIMEOUT_MULTIPLIER);
+        Integer multi = 1;
+        if (property != null) {
+            multi = Integer.valueOf(property);
+            if (multi <= 0) {
+                throw new NumberFormatException(
+                        "Property " + TestProperties.ASYNC_TIMEOUT_MULTIPLIER + " must be a number greater than 0.");
+            }
+        }
+        return multi;
+
+    }
+
+    /**
+     * Utility method that safely closes a response without throwing an exception.
+     *
+     * @param responses responses to close. Each response may be {@code null}.
+     * @since 2.5
+     */
+    public final void close(final Response... responses) {
+        if (responses == null || responses.length == 0) {
+            return;
+        }
+
+        for (final Response response : responses) {
+            if (response == null) {
+                continue;
+            }
+            try {
+                response.close();
+            } catch (final Throwable t) {
+                LOGGER.log(Level.WARNING, "Error closing a response.", t);
+            }
+        }
+    }
+
+    /**
+     * Utility method that safely closes a client instance without throwing an exception.
+     *
+     * @param clients client instances to close. Each instance may be {@code null}.
+     * @since 2.5
+     */
+    public static void closeIfNotNull(final Client... clients) {
+        if (clients == null || clients.length == 0) {
+            return;
+        }
+
+        for (final Client c : clients) {
+            if (c == null) {
+                continue;
+            }
+            try {
+                c.close();
+            } catch (final Throwable t) {
+                LOGGER.log(Level.WARNING, "Error closing a client instance.", t);
+            }
+
+        }
+    }
+
+    /**
+     * Custom logging handler used to store log records produces during an invocation of a test.
+     */
+    private class JerseyTestLogHandler extends Handler {
+
+        private final int logLevel;
+        private final List<LogRecord> records;
+
+        private JerseyTestLogHandler() {
+            this.logLevel = Integer.parseInt(getProperty(TestProperties.RECORD_LOG_LEVEL));
+            this.records = new ArrayList<>();
+        }
+
+        @Override
+        public void publish(final LogRecord record) {
+            final String loggerName = record.getLoggerName();
+
+            if (record.getLevel().intValue() >= logLevel
+                    && loggerName.startsWith("org.glassfish.jersey")
+                    && !loggerName.startsWith("org.glassfish.jersey.test")) {
+                records.add(record);
+            }
+        }
+
+        @Override
+        public void flush() {
+        }
+
+        @Override
+        public void close() throws SecurityException {
+        }
+
+        public List<LogRecord> getRecords() {
+            return records;
+        }
+    }
+}
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/TestRuntimeDelegate.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/TestRuntimeDelegate.java
index 12b2a54..456ef30 100644
--- a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/TestRuntimeDelegate.java
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/TestRuntimeDelegate.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2023 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,6 +16,7 @@
 
 package org.glassfish.jersey.tests.e2e.common;
 
+import jakarta.ws.rs.RuntimeType;
 import jakarta.ws.rs.SeBootstrap;
 import jakarta.ws.rs.WebApplicationException;
 import jakarta.ws.rs.core.Application;
@@ -42,7 +43,7 @@
 public class TestRuntimeDelegate extends AbstractRuntimeDelegate {
 
     public TestRuntimeDelegate() {
-        super(new MessagingBinders.HeaderDelegateProviders().getHeaderDelegateProviders());
+        super(new MessagingBinders.HeaderDelegateProviders(RuntimeType.SERVER).getHeaderDelegateProviders());
     }
 
     @Override
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/ContextResolverFactoryTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/ContextResolverFactoryTest.java
index bd07da2..bda770f 100644
--- a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/ContextResolverFactoryTest.java
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/internal/ContextResolverFactoryTest.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
@@ -19,6 +19,7 @@
 import java.util.Collections;
 
 import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.RuntimeType;
 import jakarta.ws.rs.core.MediaType;
 import jakarta.ws.rs.ext.ContextResolver;
 import jakarta.ws.rs.ext.Provider;
@@ -30,6 +31,8 @@
 import org.glassfish.jersey.internal.inject.InjectionManager;
 import org.glassfish.jersey.internal.inject.Injections;
 import org.glassfish.jersey.internal.inject.ProviderBinder;
+import org.glassfish.jersey.model.internal.CommonConfig;
+import org.glassfish.jersey.model.internal.ComponentBag;
 import org.glassfish.jersey.tests.e2e.common.TestRuntimeDelegate;
 
 import org.junit.jupiter.api.BeforeEach;
@@ -115,6 +118,7 @@
         injectionManager.register(new Binder());
 
         BootstrapBag bootstrapBag = new BootstrapBag();
+        bootstrapBag.setConfiguration(new CommonConfig(RuntimeType.SERVER, ComponentBag.INCLUDE_ALL));
         ContextResolverFactory.ContextResolversConfigurator configurator =
                 new ContextResolverFactory.ContextResolversConfigurator();
         configurator.init(injectionManager, bootstrapBag);
diff --git a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/process/internal/ExecutorProvidersTest.java b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/process/internal/ExecutorProvidersTest.java
index 040aeb2..bf9de7b 100644
--- a/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/process/internal/ExecutorProvidersTest.java
+++ b/tests/e2e-core-common/src/test/java/org/glassfish/jersey/tests/e2e/common/process/internal/ExecutorProvidersTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -28,6 +28,7 @@
 import jakarta.inject.Named;
 import jakarta.inject.Qualifier;
 import jakarta.inject.Singleton;
+import jakarta.ws.rs.RuntimeType;
 
 import org.glassfish.jersey.internal.inject.AbstractBinder;
 import org.glassfish.jersey.internal.inject.InjectionManager;
@@ -208,7 +209,7 @@
     @BeforeEach
     public void setup() {
         injectionManager = Injections.createInjectionManager(this);
-        ExecutorProviders.registerExecutorBindings(injectionManager);
+        ExecutorProviders.registerExecutorBindings(injectionManager, RuntimeType.SERVER);
         injectionManager.completeRegistration();
     }
 
diff --git a/tests/integration/cdi-integration/cdi-inject-weld-test/pom.xml b/tests/integration/cdi-integration/cdi-inject-weld-test/pom.xml
new file mode 100644
index 0000000..00a3b58
--- /dev/null
+++ b/tests/integration/cdi-integration/cdi-inject-weld-test/pom.xml
@@ -0,0 +1,80 @@
+<?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">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.glassfish.jersey.tests.integration.cdi</groupId>
+        <artifactId>cdi-integration-project</artifactId>
+        <version>4.0.99-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>cdi-inject-weld-test</artifactId>
+    <packaging>jar</packaging>
+    <name>jersey-tests-cdi-inject-weld</name>
+
+    <description>Jersey CDI Inject-Weld Tests</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>jakarta.ws.rs</groupId>
+            <artifactId>jakarta.ws.rs-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.enterprise</groupId>
+            <artifactId>jakarta.enterprise.cdi-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.media</groupId>
+            <artifactId>jersey-media-sse</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-cdi-inject-weld</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.weld.se</groupId>
+            <artifactId>weld-se-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <skipTests>${skip.tests}</skipTests>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/tests/integration/cdi-integration/cdi-inject-weld-test/src/test/java/org/glassfish/jersey/tests/cdi/inject/weld/SseTest.java b/tests/integration/cdi-integration/cdi-inject-weld-test/src/test/java/org/glassfish/jersey/tests/cdi/inject/weld/SseTest.java
new file mode 100644
index 0000000..d47f35f
--- /dev/null
+++ b/tests/integration/cdi-integration/cdi-inject-weld-test/src/test/java/org/glassfish/jersey/tests/cdi/inject/weld/SseTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.inject.weld;
+
+import org.glassfish.jersey.internal.inject.InjectionManager;
+import org.glassfish.jersey.internal.inject.Injections;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseySingleContainerTest;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import jakarta.enterprise.inject.se.SeContainer;
+import jakarta.enterprise.inject.se.SeContainerInitializer;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Application;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.sse.Sse;
+import jakarta.ws.rs.sse.SseEventSink;
+import jakarta.ws.rs.sse.SseEventSource;
+
+public class SseTest extends JerseySingleContainerTest {
+    protected static SeContainer container;
+    protected InjectionManager injectionManager;
+
+    @BeforeAll
+    public static void setup() {
+        SeContainerInitializer containerInitializer = SeContainerInitializer.newInstance();
+        container = containerInitializer.initialize();
+    }
+
+    @AfterAll
+    public static void weldTearDown() throws Exception {
+        container.close();
+    }
+
+    @Path("/sse")
+    public static class SseResource {
+        @GET
+        @Produces(MediaType.SERVER_SENT_EVENTS)
+        public void eventStream(@Context SseEventSink eventSink, @Context Sse sse) {
+            try (SseEventSink sink = eventSink) {
+                eventSink.send(sse.newEvent("event1"));
+                eventSink.send(sse.newEvent("event2"));
+                eventSink.send(sse.newEvent("event3"));
+            }
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        return new ResourceConfig(SseResource.class);
+    }
+
+    @Test
+    public void sseBinderTest() {
+        injectionManager = Injections.createInjectionManager();
+        injectionManager.completeRegistration();
+
+        Sse sse = injectionManager.getInstance(Sse.class);
+        Assertions.assertEquals("org.glassfish.jersey.media.sse.internal.JerseySse", sse.getClass().getName());
+
+        injectionManager.shutdown();
+    }
+
+    @Test
+    public void sseTest() {
+        WebTarget target = target("sse");
+        try (SseEventSource source = SseEventSource.target(target).build()) {
+            source.register(System.out::println);
+            source.open();
+            Thread.sleep(500); // Consume events for just 500 ms
+        } catch (InterruptedException e) {
+        }
+    }
+}
diff --git a/tests/integration/cdi-integration/cdi-inject-weld-test/src/test/resources/META-INF/beans.xml b/tests/integration/cdi-integration/cdi-inject-weld-test/src/test/resources/META-INF/beans.xml
new file mode 100644
index 0000000..c175b60
--- /dev/null
+++ b/tests/integration/cdi-integration/cdi-inject-weld-test/src/test/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="https://jakarta.ee/xml/ns/jakartaee"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd"
+       version="4.0" bean-discovery-mode="all">
+</beans>
diff --git a/tests/integration/cdi-integration/pom.xml b/tests/integration/cdi-integration/pom.xml
index bc23bb7..24a511e 100644
--- a/tests/integration/cdi-integration/pom.xml
+++ b/tests/integration/cdi-integration/pom.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
 
-    Copyright (c) 2019, 2023 Oracle and/or its affiliates. All rights reserved.
+    Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
 
     This program and the accompanying materials are made available under the
     terms of the Eclipse Public License v. 2.0, which is available at
@@ -37,6 +37,7 @@
         <module>cdi-client-on-server</module>
         <module>cdi-ejb-test-webapp</module>
         <module>cdi-iface-with-non-jaxrs-impl-test-webapp</module>
+        <module>cdi-inject-weld-test</module>
         <module>cdi-manually-bound</module>
         <module>cdi-log-check</module>
         <module>cdi-multimodule</module>
diff --git a/tests/jmockit/src/test/java/org/glassfish/jersey/tests/jmockit/server/WebServerFactoryTest.java b/tests/jmockit/src/test/java/org/glassfish/jersey/tests/jmockit/server/WebServerFactoryTest.java
index 974404c..6a0290f 100644
--- a/tests/jmockit/src/test/java/org/glassfish/jersey/tests/jmockit/server/WebServerFactoryTest.java
+++ b/tests/jmockit/src/test/java/org/glassfish/jersey/tests/jmockit/server/WebServerFactoryTest.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.
  * Copyright (c) 2018 Markus KARG. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
@@ -26,6 +26,7 @@
 import jakarta.ws.rs.SeBootstrap;
 import jakarta.ws.rs.core.Application;
 
+import jakarta.ws.rs.core.Configuration;
 import org.glassfish.jersey.internal.ServiceFinder;
 import org.glassfish.jersey.internal.ServiceFinder.ServiceIteratorProvider;
 import org.glassfish.jersey.internal.guava.Iterators;
@@ -78,10 +79,16 @@
                             }
                         }
                                 : service == InjectionManagerFactory.class ? new InjectionManagerFactory() {
+
                             @Override
                             public final InjectionManager create(final Object parent) {
                                 return mockInjectionManager;
                             }
+
+                            @Override
+                            public InjectionManager create(Object parent, Configuration configuration) {
+                                return mockInjectionManager;
+                            }
                         }
                                 : null));
             }