I am upgrading a legacy project from Jersey 2.22 to the latest version, and I have some problem migrating our dependency injection.
We were using the custom annotation to inject the user / token in the method parameter :
@GET
public Response getAll(@SdnBasicAuth final UserManagement.User user) { 
    // ... Check user rights return Response.accepted().build();
}
And now I cannot get a working solution with the new Jersey decoupled dependency injection.
The system behavior is the following :
- At the startup of the application the 
getAllmethod is called twice with my dummy user (that's not the expected behavior, we want only this call in response to a request). 
Both supplier and resolver are called at the startup but not when I make a "real" request.
Note : In the Resolver the parameter final ServiceHandle<?> root is null.
How can I reproduce the behavior of the Jersey 2.22 (see code at the bottom of the post)
Thanks for helping.
The new code version with jersey 2.29 :
Dependencies list :
    <dependency>
        <groupId>org.glassfish.hk2</groupId>
        <artifactId>hk2-core</artifactId>
        <version>${hk2.version}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.glassfish.hk2</groupId>
        <artifactId>hk2-api</artifactId>
        <version>${hk2.version}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.glassfish.hk2</groupId>
        <artifactId>hk2-locator</artifactId>
        <version>${hk2.version}</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-server</artifactId>
        <version>${jersey.version}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet-core</artifactId>
        <version>${jersey.version}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.inject</groupId>
        <artifactId>jersey-hk2</artifactId>
        <version>${jersey.version}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.ext</groupId>
        <artifactId>jersey-bean-validation</artifactId>
        <version>${jersey.version}</version>
        <scope>provided</scope>
    </dependency>
The Binder :
    import org.glassfish.hk2.api.InjectionResolver;
    import org.glassfish.jersey.internal.inject.AbstractBinder;
    import org.glassfish.jersey.process.internal.RequestScoped;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import javax.inject.Singleton;
    import javax.ws.rs.core.GenericType;
    public class BasicAuthBinder extends AbstractBinder {
        // SLF4J Logger
        private static final Logger LOG = LoggerFactory.getLogger(BasicAuthBinder.class);
        @Override
        protected void configure() {
            bindFactory(BasicAuthSupplier.class)
                .to(UserManagement.User.class)
                .proxyForSameScope(false)
                .in(Singleton.class);
    // I have try to change to this : 
    // .in(RequestScoped.class);
    // But after that I have the following exception at startup.
    // org.glassfish.hk2.api.MultiException: A MultiException has 1 exceptions.  
    // They are:
    // java.lang.IllegalStateException: Not inside a request scope.
            bind(BasicAuthResolver.class)
                .to(new GenericType<InjectionResolver<SdnBasicAuth>>() {})
                .in(Singleton.class);
        }
    }
The resolver
    import org.glassfish.hk2.api.Injectee;
    import org.glassfish.hk2.api.InjectionResolver;
    import org.glassfish.hk2.api.ServiceHandle;
    import javax.inject.Inject;
    import javax.inject.Named;
    public class BasicAuthResolver implements org.glassfish.hk2.api.InjectionResolver<SdnBasicAuth> {
        @Inject
        @Named (InjectionResolver.SYSTEM_RESOLVER_NAME)
        org.glassfish.hk2.api.InjectionResolver<Inject> systemInjectionResolver;
        @Override
        public Object resolve(final Injectee injectee, final ServiceHandle<?> root) {
            if (UserManagement.User.class == injectee.getRequiredType()) {
                return systemInjectionResolver.resolve(injectee, root);
            }
            return null;
        }
        @Override
        public boolean isConstructorParameterIndicator() {
            return false;
        }
        @Override
        public boolean isMethodParameterIndicator() {
            return true;
        }
    }
The supplier:
    import java.util.function.Supplier;
    public class BasicAuthSupplier implements Supplier<UserManagement.User> {
        // SLF4J Logger
        private static final Logger LOG = LoggerFactory.getLogger(BasicAuthSupplier.class);
        public BasicAuthSupplier() {
        }
        @Override
        public UserManagement.User get() {
            // Dummy code to create the user.
            return UserManagement.User.newUser().build();
        }
    }
And the API :
    @Path ("/my-path")
    @Consumes (APPLICATION_JSON)
    @Produces (APPLICATION_JSON)
    public class  {
       @GET
        public Response getAll(@SdnBasicAuth final UserManagement.User user) {
            // ... Check user rights
            return Response.accepted().build();
        }
    }
Below was the working code on jersey 2.22
Annotation:
    @Target ({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
    @Retention (RetentionPolicy.RUNTIME)
    @Documented
    public @interface SdnBasicAuth {
    }
Binder :
    import org.glassfish.hk2.api.InjectionResolver;
    import org.glassfish.hk2.api.TypeLiteral;
    import org.glassfish.hk2.utilities.binding.AbstractBinder;
    import org.glassfish.jersey.server.spi.internal.ValueFactoryProvider;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import javax.inject.Singleton;
    public class BasicAuthBinder extends AbstractBinder {
        // SLF4J Logger
        private static final Logger LOG = LoggerFactory.getLogger(BasicAuthBinder.class);
        private final UserManagement userManagement;
        public BasicAuthBinder(final UserManagement userManagement) {
            this.userManagement = userManagement;
        }
        @Override
        protected void configure() {
            bind(userManagement).to(UserManagement.class);
            bind(BasicAuthFactory.class)
                .to(ValueFactoryProvider.class)
                .in(Singleton.class);
            bind(BasicAuthResolver.class)
                .to(new TypeLiteral<InjectionResolver<SdnBasicAuth>>() {
                })
                .in(Singleton.class);
        }
    }
Factory :
    import org.glassfish.hk2.api.Factory;
    import org.glassfish.hk2.api.ServiceLocator;
    import org.glassfish.jersey.server.internal.inject.AbstractContainerRequestValueFactory;
    import org.glassfish.jersey.server.internal.inject.AbstractValueFactoryProvider;
    import org.glassfish.jersey.server.internal.inject.MultivaluedParameterExtractorProvider;
    import org.glassfish.jersey.server.model.Parameter;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import javax.inject.Inject;
    import javax.inject.Singleton;
    import javax.servlet.http.HttpServletRequest;
    import javax.ws.rs.container.ResourceContext;
    import javax.ws.rs.core.Context;
    @Singleton
    public class BasicAuthFactory extends AbstractValueFactoryProvider {
        // SLF4J Logger
        private static final Logger LOG = LoggerFactory.getLogger(BasicAuthFactory.class);
        @Inject
        private UserManagement userManagement;
        @Inject
        public BasicAuthFactory(MultivaluedParameterExtractorProvider mpep, ServiceLocator injector) {
            super(mpep, injector, Parameter.Source.UNKNOWN);
        }
        @Override
        protected Factory<?> createValueFactory(Parameter parameter) {
            Class<?> classType = parameter.getRawType();
            if (parameter.getAnnotation(SdnBasicAuth.class) == null) {
                LOG.debug("Not injecting user management provider.");
                return null;
            }
            if (classType == null || (!classType.equals(UserManagement.User.class))) {
                LOG.warn("IdentityParam annotation was not placed on correct object type; Injection might not work correctly!");
                return null;
            }
            return new IdentityParamValueFactory(userManagement);
        }
        private static final class IdentityParamValueFactory extends AbstractContainerRequestValueFactory<UserManagement.User> {
            private final UserManagement userManagement;
            @Context
            private ResourceContext context;
            public IdentityParamValueFactory(final UserManagement userManagement) {
                this.userManagement = userManagement;
            }
            public UserManagement.User provide() {
                final HttpServletRequest request = context.getResource(HttpServletRequest.class);
                // Dumb code to do the authorization stuff not related of our problem.
                return UserManagement.User.newUser().build();
            }
        }
    }
The resolver:
    import org.glassfish.jersey.server.internal.inject.ParamInjectionResolver;
    import javax.inject.Singleton;
    @Singleton
    public class BasicAuthResolver extends ParamInjectionResolver<SdnBasicAuth> {
        public BasicAuthResolver() {
            super(BasicAuthFactory.class);
        }
    }