为什么 Wildfly 说在部署时我的 REST 资源文件用 @RequestScoped 注释,但事实并非如此?
Why Wildfly says that at deploy my REST resource file is annotated with @RequestScoped, however it is not?
我有一个由 Resteasy 实现的 REST 服务。在服务中,我(通过 Guice)注入了一个应用程序(实现业务逻辑并且也注入了 EJB),其中注入了 @EJB。当我部署它时,Wildfly 10 在底部给我异常。
只是搜索错误消息,我发现我的 CDI(焊接?)配置可能有误。
[org.jboss.weld.Bootstrap] (Weld Thread Pool -- 9) WELD-000167: Class digitallibrary.masterdata.dataservice.rest.api.resources.CurrencyResource is annotated with @RequestScoped but it does not declare an appropriate constructor therefore is not registered as a bean!
我有几个问题,因为我是这个领域的新手,我需要一些前进的方向,因为我不知道我是否没有读过一些东西来启动这个应用程序 运行 我遇到了一个奇怪的案例
- Weld 是如何出现在@EJB 周围的?我知道我的会话 bean 以某种方式被注入,但我感觉它不需要任何配置就可以发生。
- 为什么 Weld 认为我的 CurrencyResource class 被注释了?不是。
- 总是需要配置吗?我已经检查了 Github 上的 Wildfly 示例项目,但我还没有看到配置。
- 我必须使用 beans.xml 吗?
- 有没有可能是嵌套注入导致的这个问题?
- 您需要我项目中的任何其他代码示例吗?
请在下面找到我的申请代码:
Resteasy 资源class:
@Path("/currency")
public class CurrencyResource {
private final CurrencyAppInterface currencyApp;
@com.google.inject.Inject
public CurrencyResource(final CurrencyAppInterface currencyApp) {
this.currencyApp = currencyApp;
}
@GET
@Path("/currencies")
@Produces(MediaType.APPLICATION_JSON)
public Response getCurrencies() {
System.out.println("stuff");
Collection<String> currencies = new ArrayList<String>();
currencies.add("curr1");
currencies.add("curr2");
return Response
.status(Response.Status.OK)
.entity(currencies)
.build();
}
}
Resteasy 应用文件:
@ApplicationPath("/api")
public class DigitalLibraryMasterDataDataservice extends Application {
private Set<Object> singletons = new HashSet<Object>();
public DigitalLibraryMasterDataDataservice(@Context ServletContext servletContext) {
}
@Override
public Set<Object> getSingletons(){
Injector injector = Guice.createInjector(new CurrencyModule());
CurrencyModule currencyModule = injector.getInstance(CurrencyModule.class);
singletons.add(currencyModule);
return singletons;
}
}
应用程序文件,实现业务逻辑并使用会话 bean。
public class CurrencyApplication implements CurrencyAppInterface {
@EJB(name = "CurrencySessionBean")
private CurrencySessionBean currencySessionBean;
private CurrencyMapperInterface currencyMapper;
@com.google.inject.Inject
public CurrencyApplication(CurrencyMapper currencyMapper) {
this.currencyMapper = currencyMapper;
}
@Override
public Collection<CurrencyDto> getAllCurrencies() throws DigitalLibraryMasterDataDataserviceApplicationException {
try {
Collection<Currency> currencies = this.currencySessionBean.getAllCurrencies();
Collection<CurrencyDto> mappedCurrencies = this.currencyMapper.MapCurrenciesToCurrencyDtos(currencies);
return mappedCurrencies;
} catch (Exception e) {
throw new DigitalLibraryMasterDataDataserviceApplicationException("Error in application", e);
}
}
}
会话 Bean:
@Stateless
public class CurrencySessionBean implements CurrencySessionBeanLocalInterface {
@PersistenceContext(name = "DigitalLibrary.MasterData.Dataservice.PU")
private EntityManager em;
@Override
public Collection<Currency> getAllCurrencies() throws DigitalLibraryMasterDataDataserviceEjbSessionBeanException {
try {
List<Currency> currencies = this.em.createQuery("from Currency", Currency.class).getResultList();
return currencies;
} catch (Exception e) {
throw new DigitalLibraryMasterDataDataserviceEjbSessionBeanException("Error querying currencies", e);
}
}
}
来自 Wildfly 的完整错误消息:
22:56:25,818 INFO [org.hibernate.envers.boot.internal.EnversServiceImpl] (ServerService Thread Pool -- 69) Envers integration enabled? : true
22:56:26,117 WARN [org.jboss.weld.Bootstrap] (Weld Thread Pool -- 9) WELD-000167: Class digitallibrary.masterdata.dataservice.rest.api.resources.CurrencyResource is annotated with @RequestScoped but it does not declare an appropriate constructor therefore is not registered as a bean!
22:56:26,275 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-5) MSC000001: Failed to start service jboss.deployment.unit."DigitalLibrary.MasterData.Dataservice.ear".WeldStartService: org.jboss.msc.service.StartException in service jboss.deployment.unit."DigitalLibrary.MasterData.Dataservice.ear".WeldStartService: Failed to start service
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1904)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type Injector with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject private org.jboss.resteasy.plugins.guice.GuiceResteasyBootstrapServletContextListener.parentInjector
at org.jboss.resteasy.plugins.guice.GuiceResteasyBootstrapServletContextListener.parentInjector(GuiceResteasyBootstrapServletContextListener.java:0)
at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:359)
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:281)
at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:134)
at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:155)
at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:518)
at org.jboss.weld.bootstrap.ConcurrentValidator.doWork(ConcurrentValidator.java:68)
at org.jboss.weld.bootstrap.ConcurrentValidator.doWork(ConcurrentValidator.java:66)
at org.jboss.weld.executor.IterativeWorkerTaskFactory.call(IterativeWorkerTaskFactory.java:63)
at org.jboss.weld.executor.IterativeWorkerTaskFactory.call(IterativeWorkerTaskFactory.java:56)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
at org.jboss.threads.JBossThread.run(JBossThread.java:320)
22:56:26,279 ERROR [org.jboss.as.controller.management-operation] (DeploymentScanner-threads - 1) WFLYCTL0013: Operation ("deploy") failed - address: ([("deployment" => "DigitalLibrary.MasterData.Dataservice.ear")]) - failure description: {
"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"DigitalLibrary.MasterData.Dataservice.ear\".WeldStartService" => "org.jboss.msc.service.StartException in service jboss.deployment.unit.\"DigitalLibrary.MasterData.Dataservice.ear\".WeldStartService: Failed to start service
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type Injector with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject private org.jboss.resteasy.plugins.guice.GuiceResteasyBootstrapServletContextListener.parentInjector
at org.jboss.resteasy.plugins.guice.GuiceResteasyBootstrapServletContextListener.parentInjector(GuiceResteasyBootstrapServletContextListener.java:0) "}, "WFLYCTL0412: Required services that are not installed:" =>["jboss.deployment.unit.\"DigitalLibrary.MasterData.Dataservice.ear\".WeldStartService"], "WFLYCTL0180: Services with missing/unavailable dependencies" => undefined }
首先,你的构造函数用
注释
@com.google.inject.Inject
那绝对不是right.The Inject注解来自javax.inject包
其次,您的 bean 必须有一个不带参数的构造函数。如果您希望通过构造函数 @Inject 某些东西,它必须是 CDI 知道的 bean。
你可以试试:
- 正在从 CurrencyResource 构造函数中删除参数。
- 修复@Inject 注释(javax.inject 包)
根据标题回答你的问题:默认情况下在 WildFly 中(如果启用了 CDI 和 JAX-RS),任何 JAX-RS 资源都由 CDI 扩展分析,如果它没有注释范围注解,@RequestScoped
自动添加。
还支持 构造函数注入 JAX-RS 资源是可选的,即规范不需要。而且我不确定 RESTEasy 是否支持这个...我认为它不支持。
这只是对之前答案的补充。
当您将构造函数更改为不带参数时,您还可以将注入移动到 init 方法而不是按字段注入。我们公司就是这样做的,我们也使用带标准 CDI 的 Wildfly 10。
喜欢这样的:
public CurrencyResource(){
}
@Javax.inject.Inject
public void init(final CurrencyAppInterface currencyApp){
this.currencyApp = currencyApp;
}
感谢大家的回答!
我的代码有很多问题:
- 并非所有实现某些业务逻辑的代码都由@EJB 注释
- 我想通过 Guice 注入,不知何故导入混合了
- 有一个@EJB 注入,我在其中引用了 class 而不是接口
我是如何解决这个问题的:
- 我用业务逻辑重构了classes,全部都是stateless session bean
- 它们可以很容易地包含在 CDI 中,不再需要 Guice
- 我也解决了引用问题
效果不佳。
我有一个由 Resteasy 实现的 REST 服务。在服务中,我(通过 Guice)注入了一个应用程序(实现业务逻辑并且也注入了 EJB),其中注入了 @EJB。当我部署它时,Wildfly 10 在底部给我异常。
只是搜索错误消息,我发现我的 CDI(焊接?)配置可能有误。
[org.jboss.weld.Bootstrap] (Weld Thread Pool -- 9) WELD-000167: Class digitallibrary.masterdata.dataservice.rest.api.resources.CurrencyResource is annotated with @RequestScoped but it does not declare an appropriate constructor therefore is not registered as a bean!
我有几个问题,因为我是这个领域的新手,我需要一些前进的方向,因为我不知道我是否没有读过一些东西来启动这个应用程序 运行 我遇到了一个奇怪的案例
- Weld 是如何出现在@EJB 周围的?我知道我的会话 bean 以某种方式被注入,但我感觉它不需要任何配置就可以发生。
- 为什么 Weld 认为我的 CurrencyResource class 被注释了?不是。
- 总是需要配置吗?我已经检查了 Github 上的 Wildfly 示例项目,但我还没有看到配置。
- 我必须使用 beans.xml 吗?
- 有没有可能是嵌套注入导致的这个问题?
- 您需要我项目中的任何其他代码示例吗?
请在下面找到我的申请代码:
Resteasy 资源class:
@Path("/currency")
public class CurrencyResource {
private final CurrencyAppInterface currencyApp;
@com.google.inject.Inject
public CurrencyResource(final CurrencyAppInterface currencyApp) {
this.currencyApp = currencyApp;
}
@GET
@Path("/currencies")
@Produces(MediaType.APPLICATION_JSON)
public Response getCurrencies() {
System.out.println("stuff");
Collection<String> currencies = new ArrayList<String>();
currencies.add("curr1");
currencies.add("curr2");
return Response
.status(Response.Status.OK)
.entity(currencies)
.build();
}
}
Resteasy 应用文件:
@ApplicationPath("/api")
public class DigitalLibraryMasterDataDataservice extends Application {
private Set<Object> singletons = new HashSet<Object>();
public DigitalLibraryMasterDataDataservice(@Context ServletContext servletContext) {
}
@Override
public Set<Object> getSingletons(){
Injector injector = Guice.createInjector(new CurrencyModule());
CurrencyModule currencyModule = injector.getInstance(CurrencyModule.class);
singletons.add(currencyModule);
return singletons;
}
}
应用程序文件,实现业务逻辑并使用会话 bean。
public class CurrencyApplication implements CurrencyAppInterface {
@EJB(name = "CurrencySessionBean")
private CurrencySessionBean currencySessionBean;
private CurrencyMapperInterface currencyMapper;
@com.google.inject.Inject
public CurrencyApplication(CurrencyMapper currencyMapper) {
this.currencyMapper = currencyMapper;
}
@Override
public Collection<CurrencyDto> getAllCurrencies() throws DigitalLibraryMasterDataDataserviceApplicationException {
try {
Collection<Currency> currencies = this.currencySessionBean.getAllCurrencies();
Collection<CurrencyDto> mappedCurrencies = this.currencyMapper.MapCurrenciesToCurrencyDtos(currencies);
return mappedCurrencies;
} catch (Exception e) {
throw new DigitalLibraryMasterDataDataserviceApplicationException("Error in application", e);
}
}
}
会话 Bean:
@Stateless
public class CurrencySessionBean implements CurrencySessionBeanLocalInterface {
@PersistenceContext(name = "DigitalLibrary.MasterData.Dataservice.PU")
private EntityManager em;
@Override
public Collection<Currency> getAllCurrencies() throws DigitalLibraryMasterDataDataserviceEjbSessionBeanException {
try {
List<Currency> currencies = this.em.createQuery("from Currency", Currency.class).getResultList();
return currencies;
} catch (Exception e) {
throw new DigitalLibraryMasterDataDataserviceEjbSessionBeanException("Error querying currencies", e);
}
}
}
来自 Wildfly 的完整错误消息:
22:56:25,818 INFO [org.hibernate.envers.boot.internal.EnversServiceImpl] (ServerService Thread Pool -- 69) Envers integration enabled? : true
22:56:26,117 WARN [org.jboss.weld.Bootstrap] (Weld Thread Pool -- 9) WELD-000167: Class digitallibrary.masterdata.dataservice.rest.api.resources.CurrencyResource is annotated with @RequestScoped but it does not declare an appropriate constructor therefore is not registered as a bean!
22:56:26,275 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-5) MSC000001: Failed to start service jboss.deployment.unit."DigitalLibrary.MasterData.Dataservice.ear".WeldStartService: org.jboss.msc.service.StartException in service jboss.deployment.unit."DigitalLibrary.MasterData.Dataservice.ear".WeldStartService: Failed to start service
at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1904)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type Injector with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject private org.jboss.resteasy.plugins.guice.GuiceResteasyBootstrapServletContextListener.parentInjector
at org.jboss.resteasy.plugins.guice.GuiceResteasyBootstrapServletContextListener.parentInjector(GuiceResteasyBootstrapServletContextListener.java:0)
at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:359)
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:281)
at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:134)
at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:155)
at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:518)
at org.jboss.weld.bootstrap.ConcurrentValidator.doWork(ConcurrentValidator.java:68)
at org.jboss.weld.bootstrap.ConcurrentValidator.doWork(ConcurrentValidator.java:66)
at org.jboss.weld.executor.IterativeWorkerTaskFactory.call(IterativeWorkerTaskFactory.java:63)
at org.jboss.weld.executor.IterativeWorkerTaskFactory.call(IterativeWorkerTaskFactory.java:56)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
at org.jboss.threads.JBossThread.run(JBossThread.java:320)
22:56:26,279 ERROR [org.jboss.as.controller.management-operation] (DeploymentScanner-threads - 1) WFLYCTL0013: Operation ("deploy") failed - address: ([("deployment" => "DigitalLibrary.MasterData.Dataservice.ear")]) - failure description: {
"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"DigitalLibrary.MasterData.Dataservice.ear\".WeldStartService" => "org.jboss.msc.service.StartException in service jboss.deployment.unit.\"DigitalLibrary.MasterData.Dataservice.ear\".WeldStartService: Failed to start service
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type Injector with qualifiers @Default
at injection point [BackedAnnotatedField] @Inject private org.jboss.resteasy.plugins.guice.GuiceResteasyBootstrapServletContextListener.parentInjector
at org.jboss.resteasy.plugins.guice.GuiceResteasyBootstrapServletContextListener.parentInjector(GuiceResteasyBootstrapServletContextListener.java:0) "}, "WFLYCTL0412: Required services that are not installed:" =>["jboss.deployment.unit.\"DigitalLibrary.MasterData.Dataservice.ear\".WeldStartService"], "WFLYCTL0180: Services with missing/unavailable dependencies" => undefined }
首先,你的构造函数用
注释@com.google.inject.Inject
那绝对不是right.The Inject注解来自javax.inject包
其次,您的 bean 必须有一个不带参数的构造函数。如果您希望通过构造函数 @Inject 某些东西,它必须是 CDI 知道的 bean。
你可以试试:
- 正在从 CurrencyResource 构造函数中删除参数。
- 修复@Inject 注释(javax.inject 包)
根据标题回答你的问题:默认情况下在 WildFly 中(如果启用了 CDI 和 JAX-RS),任何 JAX-RS 资源都由 CDI 扩展分析,如果它没有注释范围注解,@RequestScoped
自动添加。
还支持 构造函数注入 JAX-RS 资源是可选的,即规范不需要。而且我不确定 RESTEasy 是否支持这个...我认为它不支持。
这只是对之前答案的补充。
当您将构造函数更改为不带参数时,您还可以将注入移动到 init 方法而不是按字段注入。我们公司就是这样做的,我们也使用带标准 CDI 的 Wildfly 10。
喜欢这样的:
public CurrencyResource(){
}
@Javax.inject.Inject
public void init(final CurrencyAppInterface currencyApp){
this.currencyApp = currencyApp;
}
感谢大家的回答!
我的代码有很多问题:
- 并非所有实现某些业务逻辑的代码都由@EJB 注释
- 我想通过 Guice 注入,不知何故导入混合了
- 有一个@EJB 注入,我在其中引用了 class 而不是接口
我是如何解决这个问题的:
- 我用业务逻辑重构了classes,全部都是stateless session bean
- 它们可以很容易地包含在 CDI 中,不再需要 Guice
- 我也解决了引用问题
效果不佳。