将 JAX-RS 与 CDI 集成的正确方法? [英] Correct way to Integrate JAX-RS with CDI?

查看:20
本文介绍了将 JAX-RS 与 CDI 集成的正确方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我曾经通过在 Java EE 教程

I used to integrate Service and DAO beans in Jersey REST resources by annotating them with @Path following Java EE tutorial

一般来说,要让 JAX-RS 与企业 bean 一起工作,您需要使用 @Path 注释 bean 的类以将其转换为根资源类.您可以将 @Path 注释与无状态会话 bean 和单例 POJO bean 一起使用.

In general, for JAX-RS to work with enterprise beans, you need to annotate the class of a bean with @Path to convert it to a root resource class. You can use the @Path annotation with stateless session beans and singleton POJO beans.

所以我的代码曾经是这样的:

So my code used to be something like this:

@Path("/")
public class ServiceResource {
   @Inject
   private AccountService accountService;

   @GET
   @Path("/account/get")
   public Account getAccount(@QueryParam("id") String id) {
     return accountService.get(id);
   }
}

@javax.inject.Singleton
@Path("")
public class AccountService {
   public Account get(String id){...}
}

现在,我开始将 Quartz 作业集成到我的应用程序中,我想找到一种方法将我的 AccountService 注入到这样的作业中

Now, I started integrating a Quartz Job into my application, and I wanted to find a way to inject my AccountService inside a job like this

public class AccountJob implements Job {
  @Inject
  private AccountService accountService;

  @Override
  public void execute(JobExecutionContext jec) throws JobExecutionException {
    accountService.updateAllAccounts();
  }
}

我发现这个 answer 告诉我们使用 DeltaSpike 来完成这项工作,所以我在我的 pom.xml 中添加了以下依赖项,并且没有在任何类中添加任何代码行,accountService 到我的 Job 工作正常

I found this answer that tells to use DeltaSpike to do the Job, so I added the following dependencies to my pom.xml, and without adding any more lines of code to any class the inejection of accountService to my Job works fine

<dependency>
    <groupId>org.apache.deltaspike.modules</groupId>
    <artifactId>deltaspike-scheduler-module-api</artifactId>
    <version>1.7.2</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.apache.deltaspike.modules</groupId>
    <artifactId>deltaspike-scheduler-module-impl</artifactId>
    <version>1.7.2</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.apache.deltaspike.cdictrl</groupId>
    <artifactId>deltaspike-cdictrl-api</artifactId>
    <version>1.7.2</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.apache.deltaspike.cdictrl</groupId>
    <artifactId>deltaspike-cdictrl-weld</artifactId>
    <version>1.7.2</version>
    <scope>runtime</scope>
</dependency>

然而,我意识到当我从 AccountService 中删除 @Path("") 时,它的实例仍然被很好地注入到 @Path("")code>ServiceResource,所以我的问题如下:

However, I realized that when I remove the @Path("") from AccountService, its instance is still injected fine inside ServiceResource, so my questions are the following:

  1. 为什么添加 DeltaSpike 依赖项可以在不使用 @Path 的情况下注入我的 bean?
  2. 通过搜索更多,我了解到DeltaSpike 内部使用Weld 进行注入,并且由于我已经在使用GlassFish 4.0,我知道 Weld 已经存在,那么为什么注入在我的 Job 类和 ServiceResource 类中默认不起作用而不添加 @Path 在我的豆子上?实际上为什么Java教程中甚至建议添加@Path?
  3. 是否存在我在代码中没有看到的不良副作用,因为我认为我在这里混合了多个 DI 方法而没有真正了解它们是如何工作的?
  1. Why adding DeltaSpike dependencies made it possible to inject my beans without using @Path on them?
  2. By searching more, I understood that DeltaSpike internally uses Weld to do the injection, and since I am already using GlassFish 4.0, I know that Weld is already there, so why the injection is not working by default in my Job class and in ServiceResource class without adding @Path on my beans? Actually why adding @Path is even suggested in the Java tutorial?
  3. Is there any bad side effects that I don't see in my code, because I think that I am mixing multiple DI methods here without really understanding how do they work?

更新: 经过更多的搜索,我发现Jersey 没有使用Weld 进行依赖注入,而是使用了HK2,一个不同的框架,也恰好是 GlassFish 的一部分,当我尝试在不使用 @Path 的情况下注入 AccountService 时显示以下异常

Update: After more search, I realize that Jersey doesn't use Weld for dependency injection, instead it uses HK2, a different framework that also happens to be a part of GlassFish, when I try to inject AccountService without using @Path it shows the following exception

org.glassfish.hk2.api.UnsatisfiedDependencyException:在 SystemInjecteeImpl(requiredType=AccountService,parent=ServiceResource,qualifiers={} 处没有可注入的对象...

org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=AccountService,parent=ServiceResource,qualifiers={}...

所以这将问题更新为以下内容:

So this updates the questions to the following:

  1. 如何使 HK2 注入工作?//不使用 Java EE 教程中提到的 @Path
  2. 如果我设法用 HK2DI,使用 DeltaSpikeDI 是否安全> 为 Quartz 工作?可以将两个 CDI 框架混合在一起来扫描类并进行注入吗?
  1. How to make HK2 injections works? // Without using @Path as mentioned in the Java EE Tutorial
  2. If I managed to to do DI with HK2, will it be safe to use DeltaSpike to do DI for the Quartz Job? Is it okay to mix two CDI framewroks together to scan the classes and do the injection?

我把我的源代码放在了 pastebin 上;pom.xml这里Java这里

I put my my source code on pastebin; pom.xml is here and the Java is here

推荐答案

您不需要在 AccountService CDI bean 上设置 Path 注释.如果在您的应用程序上启用了 CDI(在 CDI 1.0 中使用空 beans.xml 或在 CDI > 1.0 中使用 discovery-mode=all),您可以@Inject JAX-RS 资源中的任何 CDI bean.所以你只需要编写以下类:

You do not need to set the Path annotation on your AccountService CDI bean. If CDI is enabled on your application (either with empty beans.xml in CDI 1.0 or discovery-mode=all in CDI > 1.0), you can @Inject any CDI bean in your JAX-RS resource. So you just have to write the following class:

@Path("/")
public class ServiceResource {
   @Inject
   private AccountService accountService;

   @GET
   @Path("/account/get")
   public Account getAccount(@QueryParam("id") String id) {
     return accountService.get(id);
   }
}

@javax.inject.Singleton
public class AccountService {
   public void Account get(String id){...}
}

您在帖子中链接的文章涉及混合 EJB 和 CDI 注释.例如,您可以混合使用 @Stateless@Path 注释.例如,这很有趣,因为您可以:

The article you linked in your post deals with mixing EJB and CDI annotations. For example you can mix @Stateless and @Path annotations. It's interesting for example because you can :

  • EJB 事务在您的 Rest 资源中的好处(即使现在您可以使用 @Transactional 拦截器绑定)
  • 设置资源池

请注意,所有这些都不需要 deltaspike 依赖的帮助.

Note that all of this works without the help of deltaspike dependency.

对于您的第二个问题,由于 Quartz 管理自己的线程,CDI 不处理类,因此您不能在 Quartz 类中注入 bean.deltaspike 模块的目的是允许在 Quartz 作业中注入 CDI bean.在内部,deltaspike 控制 CDI 上下文.

For your second question, as Quartz manages its own threads, classes are not handled by CDI so you can not inject beans in Quartz classes. The aim of the deltaspike module is to allow injecting CDI beans in Quartz Jobs. Internally, deltaspike controls CDI Contexts.

编辑

最后的问题:

  • 您的 HK2 问题很确定是由于缺少依赖项(在您的应用程序或服务器中).正如之前的评论中所说,我设法使用您提供的源文件在 Glassfish 4(内部版本 89)上部署了您的应用程序.

  • Your HK2 problem comes pretty sure from a missing dependency (in your application or server). As said in a previous comment, I managed to deploy your App on Glassfish 4 (build 89) with the source files you provided.

关于 CDI 与 Quartz 的集成,我认为最好的方法是实现您自己的 JobFactory 并使用 BeanManager 实例化您的作业.看看这个链接:https://devsoap.com/注入-cdi-managed-beans-into-quarz-jobs/

Regarding the integration of CDI with Quartz, I think the best is to implement your own JobFactory and instanciate your jobs using BeanManager. Take a look at this link : https://devsoap.com/injecting-cdi-managed-beans-into-quarz-jobs/

这篇关于将 JAX-RS 与 CDI 集成的正确方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆