我将旧项目从Jersey 2.22升级到最新版本,并且在迁移依赖项注入时遇到一些问题。
我们使用自定义注释将用户/令牌注入方法参数中:
@GET
public Response getAll(@SdnBasicAuth final UserManagement.User user) {
// ... Check user rights return Response.accepted().build();
}
现在我无法通过新泽西州解耦依赖注入获得有效的解决方案。
系统行为如下:
getAll
方法(这不是预期的行为,我们只需要此调用来响应请求)。在启动时会同时调用供应商和解析器,但在我发出“真实”请求时不会调用。
注意:在解析器中,参数final ServiceHandle<?> root
为空。
我该如何重现Jersey 2.22的行为(请参见文章底部的代码)
感谢您的帮助。
带有jersey 2.29的新代码版本:
依赖项列表:
<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>
活页夹:
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);
}
}
解析器
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;
}
}
供应商:
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();
}
}
和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();
}
}
以下是球衣2.22上的工作代码
注释:
@Target ({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
@Retention (RetentionPolicy.RUNTIME)
@Documented
public @interface SdnBasicAuth {
}
活页夹:
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);
}
}
工厂:
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();
}
}
}
解析器:
import org.glassfish.jersey.server.internal.inject.ParamInjectionResolver;
import javax.inject.Singleton;
@Singleton
public class BasicAuthResolver extends ParamInjectionResolver<SdnBasicAuth> {
public BasicAuthResolver() {
super(BasicAuthFactory.class);
}
}