有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java将Weld托管bean注入ConstraintValidator

我已经找了好几个小时来解决我的问题,但我没能让它发挥作用。我想将Weld托管服务注入一个ConstraintValidator,用于验证发布到JAX-RS Rest服务的用户对象。一切都部署到glassfish 4.1服务器上

我有这样的服务

@ApplicationScoped
public class UserService {

}

我想把它注入一个像这样的ConstraintValidator中

public class UniqueUserNameValidator implements ConstraintValidator<UniqueUserName, ApiUser> {

    @Inject
    private UserService service;

    @Override
    public void initialize(UniqueUserName constraintAnnotation) {
    }

    @Override
    public boolean isValid(ApiUser value, ConstraintValidatorContext context) {
        return service.getByUserName(value.getUserName()) == null;
    }

}

REST资源如下所示

@Path("users")
@Produces(MediaType.APPLICATION_JSON)
public class UserResource {  

    @Inject
    UserService userService;

    @POST
    public Response createUser(@Valid ApiUser apiUser) {
        ApiRepresentation created = userService.create(apiUser);
        return Response.created(createURL(created)).build();
    }
}

当我发布一个json用户对象时,我得到以下异常:

org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=UserService,parent=UniqueUserNameValidator,qualifiers={},position=-1,optional=false,self=false,unqualified=null,173822971)
at org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:74)
at org.jvnet.hk2.internal.Utilities.justInject(Utilities.java:947)
at org.jvnet.hk2.internal.ServiceLocatorImpl.inject(ServiceLocatorImpl.java:902)
at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:977)
at org.jvnet.hk2.internal.ServiceLocatorImpl.createAndInitialize(ServiceLocatorImpl.java:968)
at org.glassfish.jersey.internal.inject.Injections.getOrCreate(Injections.java:173)

我知道jersey使用hk2作为DI提供者,ConstraintValidator是使用InjectingConstraintValidatorFactory创建的,后者反过来使用ResourceContext。由于HK2 doe对我的WELD容器管理bean一无所知,因此在创建ConstraintValidator时,它无法注入正确的服务

为了解决这个问题,我正在寻找

a)为JAX-RS(最好是没有对jersey依赖的纯JAX-RS)提供自定义ConstraintValidatorFactory以创建验证器的方法

或者 b) 强制jersey使用WELD作为DI提供者,或者告诉hk2获取所有容器管理的bean,而无需手动将每个bean添加到hk2。 我不知道如何使用这座桥

谢谢你的帮助

干杯


共 (2) 个答案

  1. # 1 楼答案

    您是否有可能更改项目的底层JAX-RS实现

    当我遇到同样的问题时,我只是从Jersey切换到RestEasy(完全认证的JAX-RS实现)http://resteasy.jboss.org/

    更改实现非常简单:只需通过您最喜欢的构建自动化工具(我使用gradle)包含dependy即可:

    compile 'org.jboss.resteasy:resteasy-servlet-initializer:3.0.11.Final'
    

    此外,为了让CDI发挥作用,包括resteasy CDI JAX-RS CDI桥接器:

    compile 'org.jboss.resteasy:resteasy-cdi:3.0.11.
    

    最后,如果您想要相同的JSON格式,请包括resteasy jackson提供程序:

    compile 'org.jboss.resteasy:resteasy-jackson-provider:3.0.11.Final'
    

    最后,切换到resteasy比尝试实现一个Jersey补丁让我头疼得多

  2. # 2 楼答案

    我也在泽西2.25上遇到了这个问题。x、 焊接2.4。x和Tomcat 8。并且还没有找到一个合适的@Inject解决方案

    作为一种变通方法,我使用以下方法以编程方式查找bean实例:

    SomeSortOfBean bean = CDI.current().select(SomeSortOfBean.class).get();