From 8b146874af0b5942727ca860984c4e74c5a52f6a Mon Sep 17 00:00:00 2001
From: Jan Supol <jan.supol@oracle.com>
Date: Mon, 16 Dec 2019 20:54:46 +0100
Subject: [PATCH] Prevent HK2 AbstractBinder from being configured twice.
 Revert the change that introduced BinderConfigurationFactory SPI. Added
 possibility to register HK2 AbstractBinder class along with the instance
 option.

Signed-off-by: Jan Supol <jan.supol@oracle.com>
---
 .../spi/BinderConfigurationFactory.java       |  64 ---------
 .../jersey/inject/spi/package-info.java       |  20 ---
 .../JerseyBinderConfigurationFactory.java     |  78 -----------
 .../jersey/model/internal/CommonConfig.java   |  75 +++++------
 .../hk2/DelayedHk2InjectionManager.java       |   4 +-
 .../hk2/HK2BinderConfigurationFactory.java    | 121 ------------------
 .../hk2/ImmediateHk2InjectionManager.java     |   5 +-
 ...rsey.inject.spi.BinderConfigurationFactory |   1 -
 .../HK2BinderConfigurationFactoryTest.java    |  33 -----
 .../hk2/HK2AbstractBinderClassTest.java       |  54 ++++++++
 .../hk2/HK2AbstractBinderInstanceTest.java    |  55 ++++++++
 .../e2e/inject/hk2/HK2AbstractBinderTest.java |   6 +
 12 files changed, 153 insertions(+), 363 deletions(-)
 delete mode 100644 core-common/src/main/java/org/glassfish/jersey/inject/spi/BinderConfigurationFactory.java
 delete mode 100644 core-common/src/main/java/org/glassfish/jersey/inject/spi/package-info.java
 delete mode 100644 core-common/src/main/java/org/glassfish/jersey/internal/inject/JerseyBinderConfigurationFactory.java
 delete mode 100644 inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/HK2BinderConfigurationFactory.java
 delete mode 100644 inject/hk2/src/main/resources/META-INF/services/org.glassfish.jersey.inject.spi.BinderConfigurationFactory
 delete mode 100644 inject/hk2/src/test/java/org/glassfish/jersey/inject/hk2/HK2BinderConfigurationFactoryTest.java
 create mode 100644 tests/e2e-inject/hk2/src/test/java/org/glassfish/jersey/tests/e2e/inject/hk2/HK2AbstractBinderClassTest.java
 create mode 100644 tests/e2e-inject/hk2/src/test/java/org/glassfish/jersey/tests/e2e/inject/hk2/HK2AbstractBinderInstanceTest.java

diff --git a/core-common/src/main/java/org/glassfish/jersey/inject/spi/BinderConfigurationFactory.java b/core-common/src/main/java/org/glassfish/jersey/inject/spi/BinderConfigurationFactory.java
deleted file mode 100644
index c42c2b457d..0000000000
--- a/core-common/src/main/java/org/glassfish/jersey/inject/spi/BinderConfigurationFactory.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2019 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.spi;
-
-import org.glassfish.jersey.internal.inject.InjectionManager;
-import org.glassfish.jersey.model.ContractProvider;
-
-import java.util.Set;
-import java.util.function.Function;
-import java.util.function.Predicate;
-
-/**
- * Factory class creating instances of {@link BinderConfiguration} classes used to configure Binders registered
- * to a configuration. While it is created for a backward compatibility with HK2 {@code AbstractBinder} to be
- * able to be registered to a configuration (while HK2 injection module is on the classpath), a factory
- * implementing this interface is used for registering Jersey {@code AbstractBinder}, too.
- *
- * @since 2.29
- */
-public interface BinderConfigurationFactory {
-
-    /**
-     * Creates a {@link BinderConfiguration} instance that has a reference to {@code getInstances} function returning all
-     * registered instances filtered by provided {@link Predicate<ContractProvider>} that can be further traversed and configured.
-     *
-     * @param getInstances a function returning filtered instances registered to a configuration. The
-     * {@link Predicate<ContractProvider>} is used to filter out all the instances not to be further processed by the
-     * {@link BinderConfiguration}.
-     * @return {@link BinderConfiguration} instance used to register/configure the provided filtered instances.
-     */
-    BinderConfiguration createBinderConfiguration(Function<Predicate<ContractProvider>, Set<Object>> getInstances);
-
-    /**
-     * This configuration object configure all the instances provided by the {@code getInstances} function passed from the
-     * factory {@link BinderConfigurationFactory#createBinderConfiguration(Function)} method.
-     * <p>
-     * The implementation possibly can hold a list of already configured {@code Binders} so that consecutive calls do
-     * not register the already registered {@code Binders} again.
-     */
-    interface BinderConfiguration {
-        /**
-         * The provided {@code getInstances} function is used to get registered (filtered) instances in a
-         * {@link javax.ws.rs.core.Configuration}
-         *
-         * @param injectionManager {@link InjectionManager} to be used to configure the {@code Binder}
-         * @return {@code true} if a {@code Binder} has been configured.
-         */
-        boolean configureBinders(InjectionManager injectionManager);
-    }
-}
diff --git a/core-common/src/main/java/org/glassfish/jersey/inject/spi/package-info.java b/core-common/src/main/java/org/glassfish/jersey/inject/spi/package-info.java
deleted file mode 100644
index 11ec894e29..0000000000
--- a/core-common/src/main/java/org/glassfish/jersey/inject/spi/package-info.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0, which is available at
- * http://www.eclipse.org/legal/epl-2.0.
- *
- * This Source Code may also be made available under the following Secondary
- * Licenses when the conditions for such availability set forth in the
- * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
- * version 2 with the GNU Classpath Exception, which is available at
- * https://www.gnu.org/software/classpath/license.html.
- *
- * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
- */
-
-/**
- * Common Jersey core injection SPI classes.
- */
-package org.glassfish.jersey.inject.spi;
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/inject/JerseyBinderConfigurationFactory.java b/core-common/src/main/java/org/glassfish/jersey/internal/inject/JerseyBinderConfigurationFactory.java
deleted file mode 100644
index 78a3901cb4..0000000000
--- a/core-common/src/main/java/org/glassfish/jersey/internal/inject/JerseyBinderConfigurationFactory.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v. 2.0, which is available at
- * http://www.eclipse.org/legal/epl-2.0.
- *
- * This Source Code may also be made available under the following Secondary
- * Licenses when the conditions for such availability set forth in the
- * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
- * version 2 with the GNU Classpath Exception, which is available at
- * https://www.gnu.org/software/classpath/license.html.
- *
- * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
- */
-
-package org.glassfish.jersey.internal.inject;
-
-import org.glassfish.jersey.inject.spi.BinderConfigurationFactory;
-import org.glassfish.jersey.model.ContractProvider;
-import org.glassfish.jersey.model.internal.ComponentBag;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.IdentityHashMap;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-/**
- * An implementation of {@link BinderConfigurationFactory} used to configure {@link Binder} instances.
- */
-public class JerseyBinderConfigurationFactory implements BinderConfigurationFactory {
-
-    @Override
-    public BinderConfiguration createBinderConfiguration(Function<Predicate<ContractProvider>, Set<Object>> getInstances) {
-        return new JerseyBinderConfiguration(getInstances);
-    }
-
-    private static class JerseyBinderConfiguration implements BinderConfiguration {
-        private Set<Binder> configuredBinders = Collections.emptySet();
-        private final Function<Predicate<ContractProvider>, Set<Object>> getInstances;
-        private static final Function<Object, Binder> CAST_TO_BINDER = Binder.class::cast;
-
-        private JerseyBinderConfiguration(Function<Predicate<ContractProvider>, Set<Object>> getInstances) {
-            this.getInstances = getInstances;
-        }
-
-        @Override
-        public boolean configureBinders(InjectionManager injectionManager) {
-            configuredBinders = configureBinders(injectionManager, configuredBinders);
-            return !configuredBinders.isEmpty();
-        }
-
-        private Set<Binder> configureBinders(InjectionManager injectionManager, Set<Binder> configured) {
-            Set<Binder> allConfigured = Collections.newSetFromMap(new IdentityHashMap<>());
-            allConfigured.addAll(configured);
-
-            Collection<Binder> binders = getBinder(configured);
-            if (!binders.isEmpty()) {
-                injectionManager.register(CompositeBinder.wrap(binders));
-                allConfigured.addAll(binders);
-            }
-
-            return allConfigured;
-        }
-
-        private Collection<Binder> getBinder(Set<Binder> configured) {
-            return getInstances
-                    .apply(ComponentBag.BINDERS_ONLY)
-                    .stream()
-                    .map(CAST_TO_BINDER)
-                    .filter(binder -> !configured.contains(binder))
-                    .collect(Collectors.toList());
-        }
-    }
-}
diff --git a/core-common/src/main/java/org/glassfish/jersey/model/internal/CommonConfig.java b/core-common/src/main/java/org/glassfish/jersey/model/internal/CommonConfig.java
index 5775d6def3..ca51259c3e 100644
--- a/core-common/src/main/java/org/glassfish/jersey/model/internal/CommonConfig.java
+++ b/core-common/src/main/java/org/glassfish/jersey/model/internal/CommonConfig.java
@@ -28,9 +28,11 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import java.util.stream.Collectors;
 
 import javax.ws.rs.ConstrainedTo;
 import javax.ws.rs.Priorities;
@@ -42,11 +44,11 @@
 import javax.annotation.Priority;
 
 import org.glassfish.jersey.ExtendedConfig;
-import org.glassfish.jersey.inject.spi.BinderConfigurationFactory;
 import org.glassfish.jersey.internal.LocalizationMessages;
 import org.glassfish.jersey.internal.ServiceFinder;
+import org.glassfish.jersey.internal.inject.Binder;
+import org.glassfish.jersey.internal.inject.CompositeBinder;
 import org.glassfish.jersey.internal.inject.InjectionManager;
-import org.glassfish.jersey.internal.inject.JerseyBinderConfigurationFactory;
 import org.glassfish.jersey.internal.inject.ProviderBinder;
 import org.glassfish.jersey.internal.spi.AutoDiscoverable;
 import org.glassfish.jersey.internal.spi.ForcedAutoDiscoverable;
@@ -64,6 +66,7 @@
 public class CommonConfig implements FeatureContext, ExtendedConfig {
 
     private static final Logger LOGGER = Logger.getLogger(CommonConfig.class.getName());
+    private static final Function<Object, Binder> CAST_TO_BINDER = Binder.class::cast;
 
     /**
      * Configuration runtime type.
@@ -97,42 +100,6 @@ public class CommonConfig implements FeatureContext, ExtendedConfig {
      */
     private boolean disableMetaProviderConfiguration;
 
-    /**
-     * A utility class that binds binders on all {@link BinderConfigurationFactory.BinderConfiguration BinderConfiguration}
-     * created upon creation of this BinderConfigurations from all {@link BinderConfigurationFactory BinderConfigurationFactories}
-     */
-    private static final class BinderConfigurations {
-        private static final List<BinderConfigurationFactory> BINDER_CONFIGURATION_FACTORIES;
-        static {
-            final ServiceFinder<BinderConfigurationFactory> factoriesFinder =
-                    ServiceFinder.find(BinderConfigurationFactory.class);
-            final List<BinderConfigurationFactory> configurationFactories = new LinkedList<>();
-            configurationFactories.add(new JerseyBinderConfigurationFactory());
-            for (BinderConfigurationFactory configurationFactory : factoriesFinder) {
-                configurationFactories.add(configurationFactory);
-            }
-            BINDER_CONFIGURATION_FACTORIES = Collections.unmodifiableList(configurationFactories);
-        }
-
-        private final List<BinderConfigurationFactory.BinderConfiguration> binderConfigurations;
-
-        private BinderConfigurations(ComponentBag componentBag) {
-            binderConfigurations = new LinkedList<>();
-            for (BinderConfigurationFactory factory : BINDER_CONFIGURATION_FACTORIES) {
-                BinderConfigurationFactory.BinderConfiguration configuration =
-                        factory.createBinderConfiguration(componentBag::getInstances);
-                binderConfigurations.add(configuration);
-            }
-        }
-
-        private void configureBinders(InjectionManager injectionManager) {
-            for (BinderConfigurationFactory.BinderConfiguration configuration : binderConfigurations) {
-                configuration.configureBinders(injectionManager);
-            }
-        }
-
-    }
-
     /**
      * A single feature registration record.
      */
@@ -652,20 +619,40 @@ public void configureAutoDiscoverableProviders(final InjectionManager injectionM
      */
     public void configureMetaProviders(InjectionManager injectionManager, ManagedObjectsFinalizer finalizer) {
         // First, configure existing binders
-        BinderConfigurations binderConfigurations = new BinderConfigurations(componentBag);
-        binderConfigurations.configureBinders(injectionManager);
+        Set<Binder> configuredBinders = configureBinders(injectionManager, Collections.emptySet());
 
         // Check whether meta providers have been initialized for a config this config has been loaded from.
         if (!disableMetaProviderConfiguration) {
-            // Register external meta objects
-            configureExternalObjects(injectionManager);
-            // Next, configure all features
+            // Configure all features
             configureFeatures(injectionManager, new HashSet<>(), resetRegistrations(), finalizer);
+            // Next, register external meta objects
+            configureExternalObjects(injectionManager);
             // At last, configure any new binders added by features
-            binderConfigurations.configureBinders(injectionManager);
+            configureBinders(injectionManager, configuredBinders);
         }
     }
 
+    private Set<Binder> configureBinders(InjectionManager injectionManager, Set<Binder> configured) {
+        Set<Binder> allConfigured = Collections.newSetFromMap(new IdentityHashMap<>());
+        allConfigured.addAll(configured);
+
+        Collection<Binder> binders = getBinder(configured);
+        if (!binders.isEmpty()) {
+            injectionManager.register(CompositeBinder.wrap(binders));
+            allConfigured.addAll(binders);
+        }
+
+        return allConfigured;
+    }
+
+    private Collection<Binder> getBinder(Set<Binder> configured) {
+        return componentBag.getInstances(ComponentBag.BINDERS_ONLY)
+                .stream()
+                .map(CAST_TO_BINDER)
+                .filter(binder -> !configured.contains(binder))
+                .collect(Collectors.toList());
+    }
+
     private void configureExternalObjects(InjectionManager injectionManager) {
         componentBag.getInstances(model -> ComponentBag.EXTERNAL_ONLY.test(model, injectionManager))
                 .forEach(injectionManager::register);
diff --git a/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/DelayedHk2InjectionManager.java b/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/DelayedHk2InjectionManager.java
index 8f981d2afb..5e1bdca3ff 100644
--- a/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/DelayedHk2InjectionManager.java
+++ b/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/DelayedHk2InjectionManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019 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
@@ -91,6 +91,8 @@ public void register(Binder binder) {
     public void register(Object provider) throws IllegalArgumentException {
         if (isRegistrable(provider.getClass())) {
             providers.add((org.glassfish.hk2.utilities.Binder) provider);
+        } else if (Class.class.isInstance(provider) && isRegistrable((Class) provider)) {
+            providers.add((org.glassfish.hk2.utilities.Binder) createAndInitialize((Class) provider));
         } else {
             throw new IllegalArgumentException(LocalizationMessages.HK_2_PROVIDER_NOT_REGISTRABLE(provider.getClass()));
         }
diff --git a/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/HK2BinderConfigurationFactory.java b/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/HK2BinderConfigurationFactory.java
deleted file mode 100644
index d0b377d67b..0000000000
--- a/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/HK2BinderConfigurationFactory.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2019 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.hk2;
-
-import org.glassfish.hk2.api.DynamicConfiguration;
-import org.glassfish.hk2.api.DynamicConfigurationService;
-import org.glassfish.hk2.api.ServiceLocator;
-import org.glassfish.hk2.utilities.Binder;
-import org.glassfish.jersey.inject.spi.BinderConfigurationFactory;
-import org.glassfish.jersey.internal.inject.InjectionManager;
-import org.glassfish.jersey.model.ContractProvider;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.IdentityHashMap;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-/**
- * Implementation of {@link BinderConfigurationFactory} that binds HK2 {@code AbstractBinder} as well as other
- * HK2 {@code Binder} implementation
- */
-public class HK2BinderConfigurationFactory implements BinderConfigurationFactory {
-    @Override
-    public BinderConfiguration createBinderConfiguration(Function<Predicate<ContractProvider>, Set<Object>> getInstances) {
-        return new HK2BinderConfiguration(getInstances);
-    }
-
-    private static class HK2BinderConfiguration implements BinderConfigurationFactory.BinderConfiguration {
-        private final Function<Predicate<ContractProvider>, Set<Object>> getInstances;
-
-        /**
-         * A filtering strategy that includes only models that contain HK2 Binder provider contract.
-         * <p>
-         * This filter predicate returns {@code true} for all {@link org.glassfish.jersey.model.ContractProvider contract provider models}
-         * that represent a provider registered to provide HK2 {@link org.glassfish.hk2.utilities.Binder} contract.
-         * </p>
-         */
-        private static final Predicate<ContractProvider> BINDERS_ONLY = new Predicate<ContractProvider>() {
-            @Override
-            public boolean test(ContractProvider model) {
-                return Binder.class.isAssignableFrom(model.getImplementationClass());
-            }
-        };
-
-        private static final Function<Object, Binder> CAST_TO_BINDER = new Function<Object, Binder>() {
-            @Override
-            public Binder apply(final Object input) {
-                return Binder.class.cast(input);
-            }
-        };
-
-
-        private Set<Binder> configuredBinders = Collections.emptySet();
-
-        public HK2BinderConfiguration(Function<Predicate<ContractProvider>, Set<Object>> getInstances) {
-            this.getInstances = getInstances;
-        }
-
-        @Override
-        public boolean configureBinders(InjectionManager injectionManager) {
-            final ServiceLocator serviceLocator = getServiceLocator(injectionManager);
-            if (serviceLocator != null) {
-                configuredBinders = configureBinders(serviceLocator, configuredBinders);
-                return !configuredBinders.isEmpty();
-            }
-            return false;
-        }
-
-        private Set<Binder> configureBinders(final ServiceLocator locator, final Set<Binder> configured) {
-            final Set<Binder> allConfigured = Collections.newSetFromMap(new IdentityHashMap<>());
-            allConfigured.addAll(configured);
-
-            final Collection<Binder> binders = getBinders(configured);
-            if (!binders.isEmpty()) {
-                final DynamicConfigurationService dcs = locator.getService(DynamicConfigurationService.class);
-                final DynamicConfiguration dc = dcs.createDynamicConfiguration();
-
-                for (final Binder binder : binders) {
-                    binder.bind(dc);
-                    allConfigured.add(binder);
-                }
-                dc.commit();
-            }
-
-            return allConfigured;
-        }
-
-        private Collection<Binder> getBinders(final Set<Binder> configured) {
-            return getInstances
-                    .apply(BINDERS_ONLY)
-                    .stream()
-                    .map(CAST_TO_BINDER)
-                    .filter(binder -> !configured.contains(binder))
-                    .collect(Collectors.toList());
-        }
-
-        private static ServiceLocator getServiceLocator(InjectionManager injectionManager) {
-            if (AbstractHk2InjectionManager.class.isInstance(injectionManager)) {
-                return ((AbstractHk2InjectionManager) injectionManager).getServiceLocator();
-            }
-            return null;
-        }
-    }
-}
diff --git a/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/ImmediateHk2InjectionManager.java b/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/ImmediateHk2InjectionManager.java
index 1a69ca4a44..8d6ee815bb 100644
--- a/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/ImmediateHk2InjectionManager.java
+++ b/inject/hk2/src/main/java/org/glassfish/jersey/inject/hk2/ImmediateHk2InjectionManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019 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,6 +62,9 @@ public void register(Binder binder) {
     public void register(Object provider) {
         if (isRegistrable(provider.getClass())) {
             ServiceLocatorUtilities.bind(getServiceLocator(), (org.glassfish.hk2.utilities.Binder) provider);
+        } else if (Class.class.isInstance(provider) && isRegistrable((Class) provider)) {
+            ServiceLocatorUtilities.bind(getServiceLocator(), (org.glassfish.hk2.utilities.Binder)
+                    createAndInitialize((Class) provider));
         } else {
             throw new IllegalArgumentException(LocalizationMessages.HK_2_PROVIDER_NOT_REGISTRABLE(provider.getClass()));
         }
diff --git a/inject/hk2/src/main/resources/META-INF/services/org.glassfish.jersey.inject.spi.BinderConfigurationFactory b/inject/hk2/src/main/resources/META-INF/services/org.glassfish.jersey.inject.spi.BinderConfigurationFactory
deleted file mode 100644
index 30e9c77749..0000000000
--- a/inject/hk2/src/main/resources/META-INF/services/org.glassfish.jersey.inject.spi.BinderConfigurationFactory
+++ /dev/null
@@ -1 +0,0 @@
-org.glassfish.jersey.inject.hk2.HK2BinderConfigurationFactory
\ No newline at end of file
diff --git a/inject/hk2/src/test/java/org/glassfish/jersey/inject/hk2/HK2BinderConfigurationFactoryTest.java b/inject/hk2/src/test/java/org/glassfish/jersey/inject/hk2/HK2BinderConfigurationFactoryTest.java
deleted file mode 100644
index add954dd92..0000000000
--- a/inject/hk2/src/test/java/org/glassfish/jersey/inject/hk2/HK2BinderConfigurationFactoryTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2019 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.hk2;
-
-import org.glassfish.jersey.inject.spi.BinderConfigurationFactory;
-import org.glassfish.jersey.internal.ServiceFinder;
-import org.junit.Test;
-
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-
-public class HK2BinderConfigurationFactoryTest {
-    @Test
-    public void testServiceFound() {
-        ServiceFinder<BinderConfigurationFactory> factoryFinder = ServiceFinder.find(BinderConfigurationFactory.class);
-        assertTrue(factoryFinder.iterator().hasNext());
-        assertSame(factoryFinder.iterator().next().getClass(), HK2BinderConfigurationFactory.class);
-    }
-}
diff --git a/tests/e2e-inject/hk2/src/test/java/org/glassfish/jersey/tests/e2e/inject/hk2/HK2AbstractBinderClassTest.java b/tests/e2e-inject/hk2/src/test/java/org/glassfish/jersey/tests/e2e/inject/hk2/HK2AbstractBinderClassTest.java
new file mode 100644
index 0000000000..d4587014ec
--- /dev/null
+++ b/tests/e2e-inject/hk2/src/test/java/org/glassfish/jersey/tests/e2e/inject/hk2/HK2AbstractBinderClassTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.hk2;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Test;
+
+import javax.inject.Singleton;
+import javax.ws.rs.core.Application;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class HK2AbstractBinderClassTest extends JerseyTest {
+
+    private static final AtomicInteger counter = new AtomicInteger();
+
+    public static class InjectableHK2Binder extends org.glassfish.hk2.utilities.binding.AbstractBinder {
+        @Override
+        protected void configure() {
+            counter.incrementAndGet();
+            bindAsContract(InjectableImpl.class).to(Injectable.class).in(Singleton.class);
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        return new ResourceConfig(AbstractBinderTestResource.class, InjectableTestFilter.class, InjectableHK2Binder.class);
+    }
+
+    @Test
+    public void testInjectableInjection() {
+        String response = target().request().get(String.class);
+        assertThat(response, is(InjectableImpl.class.getName()));
+        assertThat(1, is(counter.get()));
+    }
+
+}
diff --git a/tests/e2e-inject/hk2/src/test/java/org/glassfish/jersey/tests/e2e/inject/hk2/HK2AbstractBinderInstanceTest.java b/tests/e2e-inject/hk2/src/test/java/org/glassfish/jersey/tests/e2e/inject/hk2/HK2AbstractBinderInstanceTest.java
new file mode 100644
index 0000000000..97113ab7ed
--- /dev/null
+++ b/tests/e2e-inject/hk2/src/test/java/org/glassfish/jersey/tests/e2e/inject/hk2/HK2AbstractBinderInstanceTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package org.glassfish.jersey.tests.e2e.inject.hk2;
+
+import org.glassfish.jersey.server.ResourceConfig;
+import org.glassfish.jersey.test.JerseyTest;
+import org.junit.Test;
+
+import javax.inject.Singleton;
+import javax.ws.rs.core.Application;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class HK2AbstractBinderInstanceTest extends JerseyTest {
+
+    private static final AtomicInteger counter = new AtomicInteger();
+
+    public static class InjectableHK2Binder extends org.glassfish.hk2.utilities.binding.AbstractBinder {
+        @Override
+        protected void configure() {
+            counter.incrementAndGet();
+            bindAsContract(InjectableImpl.class).to(Injectable.class).in(Singleton.class);
+        }
+    }
+
+    @Override
+    protected Application configure() {
+        return new ResourceConfig(AbstractBinderTestResource.class, InjectableTestFilter.class)
+                .register(new InjectableHK2Binder());
+    }
+
+    @Test
+    public void testInjectableInjection() {
+        String response = target().request().get(String.class);
+        assertThat(response, is(InjectableImpl.class.getName()));
+        assertThat(1, is(counter.get()));
+    }
+
+}
diff --git a/tests/e2e-inject/hk2/src/test/java/org/glassfish/jersey/tests/e2e/inject/hk2/HK2AbstractBinderTest.java b/tests/e2e-inject/hk2/src/test/java/org/glassfish/jersey/tests/e2e/inject/hk2/HK2AbstractBinderTest.java
index 7f67df6e0e..d7a6547907 100644
--- a/tests/e2e-inject/hk2/src/test/java/org/glassfish/jersey/tests/e2e/inject/hk2/HK2AbstractBinderTest.java
+++ b/tests/e2e-inject/hk2/src/test/java/org/glassfish/jersey/tests/e2e/inject/hk2/HK2AbstractBinderTest.java
@@ -25,6 +25,8 @@
 import javax.ws.rs.core.Feature;
 import javax.ws.rs.core.FeatureContext;
 
+import java.util.concurrent.atomic.AtomicInteger;
+
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
 
@@ -33,9 +35,12 @@
  */
 public class HK2AbstractBinderTest extends JerseyTest {
 
+    private static final AtomicInteger counter = new AtomicInteger();
+
     public static class InjectableHK2Binder extends org.glassfish.hk2.utilities.binding.AbstractBinder {
         @Override
         protected void configure() {
+            counter.incrementAndGet();
             bindAsContract(InjectableImpl.class).to(Injectable.class).in(Singleton.class);
         }
     }
@@ -57,6 +62,7 @@ protected Application configure() {
     public void testInjectableInjection() {
         String response = target().request().get(String.class);
         assertThat(response, is(InjectableImpl.class.getName()));
+        assertThat(1, is(counter.get()));
     }
 
 }