将JAX-RS与CDI集成的正确方法? [英] Correct way to Integrate JAX-RS with CDI?
问题描述
我曾经在Jersey REST资源中集成Service和DAO bean,在 @Path 注释它们javaee / 7 / tutorial / jaxrs-advanced004.htmrel =nofollow noreferrer> 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 Job进入我的应用程序,我想找到一种方法在这样的工作中注入我的 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
来做Job,所以我将以下依赖项添加到我的 pom.xml
,并且不向任何类添加任何代码行 accountService
到我的工作
工作正常
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>
但是,我意识到当我删除 @Path()
来自 AccountService
,其实例仍在 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:
- 为什么添加
DeltaSpike
依赖关系使它成为现实可以在不使用@Path
的情况下注入我的bean吗? - 通过搜索更多,我明白了
DeltaSpike
在内部使用Weld
进行注射,因为我已经在使用GlassFish 4.0
,我知道Weld
已经存在,那么为什么注入在我的Job
类和ServiceResource
类没有在我的bean上添加@Path
?实际上为什么在Java教程中甚至会建议添加@Path
? - 是否有任何不良副作用,我没有看到我的代码,因为我认为我在这里混合了多种DI方法而没有真正了解它们是如何工作的?
- Why adding
DeltaSpike
dependencies made it possible to inject my beans without using@Path
on them? - By searching more, I understood that
DeltaSpike
internally usesWeld
to do the injection, and since I am already usingGlassFish 4.0
, I know thatWeld
is already there, so why the injection is not working by default in myJob
class and inServiceResource
class without adding@Path
on my beans? Actually why adding@Path
is even suggested in the Java tutorial? - 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
,当我尝试注入<$ c $时,一个不同的框架也恰好是 GlassFish
的一部分c> AccountService 不使用 @Path
它显示以下异常
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:
- 如何使
HK2
注射有效? //不使用Java EE教程中提到的@Path
- 如果我设法做
DI
HK2
,使用DeltaSpike
安全DI
用于Quartz Job?是否可以将两个CDI framewroks混合在一起扫描类并进行注入?
- How to make
HK2
injections works? // Without using@Path
as mentioned in the Java EE Tutorial - If I managed to to do
DI
withHK2
, will it be safe to useDeltaSpike
to doDI
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。如果在您的应用程序上启用了CDI(CDI 1.0中的空beans.xml或CDI> 1.0中的discovery-mode = all),则可以 @Inject
中的任何CDI bean您的JAX-RS资源。
所以你只需要编写以下课程:
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 :
- 您的Rest资源中的EJB事务的好处(即使现在您可以使用
@Transactional
拦截器绑定) - 设置资源池
- 等。
- Benefit of EJB transaction in your Rest resource (even if now you can use
@Transactional
interceptor binding) - Set a pool of resources
- etc.
请注意,所有这些都没有deltaspike依赖的帮助。
Note that all of this works without the help of deltaspike dependency.
对于你的第二个问题,作为Quartz管理自己的线程,类不由CDI处理,因此您不能在Quartz类中注入bean。 deltaspike模块的目的是允许在Quartz Jobs中注入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.
编辑
对于您的上一个问题:
For your last questions:
-
您的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屋!