2017-06-12 23 views
0

我有一个由Resteasy实现的REST服务。在我注入的服务中(由Guice)一个应用程序(实现了业务逻辑并已经注入了EJB),这个应用程序注入了@EJB。当我部署它时,Wildfly 10在底部给我例外。为什么Wildfly说在部署我的REST资源文件时注解了@RequestScoped,但它不是?

只要搜索错误消息,我发现我可能会错误配置CDI(Weld?)。

[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! 

我有几个问题,因为我在这方面是新的,我需要一些方向前进,因为我不知道我是否有未读的东西有此应用程序启动并运行我遇到了一个奇怪的例子。

  • 如何焊接到@EJB周围?我知道我的会话bean被注入了,但是我感觉它没有任何配置需要。
  • 为什么Weld认为我的CurrencyResource类是注释?不是这样。
  • 它总是需要配置吗?我已经检查过Github上的Wildfly示例项目,并且我还没有看到配置。
  • 我必须使用beans.xml吗?
  • 嵌套注入可能导致这个问题?
  • 你需要我的项目中的其他代码示例吗?

请在下面找到我的应用程序代码:

RestEasy的资源类:

@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:从Wildfly

@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); 
     } 
    } 
} 

完整的错误消息:

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$1.doWork(ConcurrentValidator.java:68) 
     at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:66) 
     at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:63) 
     at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.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 } 
+0

jax-rs spec说服务必须有一个无参数构造函数。更改CurrencyResource以使用字段注入而不是构造函数注入。 –

+0

出于好奇,是否有你使用Guice而不仅仅是默认的Java EE CDI的原因?我对萤火虫/焊缝不熟悉,但我认为Weld是JBoss/Wildfly的注入实施,这将消除对Guice的需求。 –

回答

0

感谢所有的答案!

有我的代码中的许多问题:

  • 没有实现一些业务逻辑代码全部由@EJB
  • 进行注释,我想通过吉斯注入并以某种方式进口涨跌互现
  • 有是一个@EJB注入,我引用的,而不是接口

我做了什么来解决这个类:

  • 我的业务逻辑类重构和所有的人都无状态会话Bean
  • 他们可以通过CDI很容易地纳入,并且不再需要
  • 吉斯我固定的参考的问题太多

它工作不好。

1

首先,你的构造标注有

@com.google.inject.Inject 

这肯定是不正确的。Inject注释来自javax.inject包。

其次,你的bean必须有一个没有参数的构造函数。如果你想通过你的构造函数@注入一些东西,它肯定是一个CDI知道的bean。

你可以试试:

  • 删除从CurrencyResource构造函数中的参数。
  • 修复@Inject注释(javax。注入包)
+0

每个CDI规范允许带参数的构造函数的Bean。只有JAX-RS资源需要有一个无参数构造函数。他的问题是由Java EE平原CDI和Guice混合造成的。 –

+0

我在说“你想通过你的构造函数注入一些东西,它必须是一个bean CDI知道的”部分。 – 2017-06-14 07:35:31

1

要你的答案,从标题你的问题:在WildFly在默认情况下(如果CDI和JAX-RS启用),任何JAX-RS资源由CDI扩展分析,如果它不带注释范围注释,@RequestScoped自动添加。

还支持构造函数注入JAX-RS资源的是可选的,即规范不要求。我不确定RESTEasy是否支持这一点......我认为它不支持。

1

这只是对以前答案的补充。

当您更改您的构造函数以不采用任何参数时,您还可以将注入移至init方法而不是逐个域注入。这就是我们在公司里的做法,我们也使用标准CDI的wildfly 10。

这会喜欢这样:

public CurrencyResource(){ 
} 

@Javax.inject.Inject 
public void init(final CurrencyAppInterface currencyApp){ 
    this.currencyApp = currencyApp; 
} 
相关问题