【问题标题】:Jersey Inject Weld managed bean into ConstraintValidatorJersey 将 Weld 托管 bean 注入 ConstraintValidator
【发布时间】:2015-07-13 14:53:43
【问题描述】:

我一直在寻找几个小时来解决我的问题,但我无法让它发挥作用。我想将我的 Weld 托管服务注入到 ConstraintValidator 中,该 ConstraintValidator 用于验证发布到我的 JAX-RS Rest-Service 的用户对象。一切都部署到 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 创建的,而 InjectingConstraintValidatorFactory 作为回报使用 ResourceContext。由于 HK2 对我的 WELD 容器托管 bean 一无所知,因此在创建 ConstraintValidator 时无法注入正确的服务。

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

a) 一种为 JAX-RS(最好是不依赖球衣的纯 JAX-RS 方式)提供自定义 ConstraintValidatorFactory 以创建验证器的方法。

或 b) 一种强制 jersey 使用 WELD 作为 DI 提供者或告诉 hk2 拾取所有容器管理的 bean 而不手动将每个 bean 添加到 hk2 的方法。 我不知道如何使用建议here 的桥。

感谢您的帮助。

干杯

【问题讨论】:

    标签: java rest jersey jax-rs glassfish-4.1


    【解决方案1】:

    我在使用 Jersey 2.25.x、Weld 2.4.x 和 Tomcat 8.x 时也遇到过这个问题,但在 @Inject 上没有找到合适的解决方案。

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      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-provider:

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

      最后,切换到 resteasy 比尝试实施 Jersey 修复让我头疼得多。

      【讨论】:

      • 那么通过避免它来“解决”问题。原来resteasy真的就这么简单。但是我仍然对 jersey 是否可以在我的情况下工作感兴趣,因为它是 JAX-RS 的标准 glassfish 实现,我无法想象像这样简单的事情在 jersey 中不起作用。如果我原来的问题没有其他答案,我会接受这个答案。
      • 只是在这里给其他尝试这个的人留言。事实证明 glassfish 上的 resteasy 存在问题,因为 glassfish 总是加载球衣实现导致竞争条件。先加载的获胜。看看我的其他问题stackoverflow.com/questions/31435475/… 和这里stackoverflow.com/questions/31458850/…
      猜你喜欢
      • 2020-03-25
      • 2014-06-27
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-11
      相关资源
      最近更新 更多