为什么Wildfly说在部署时我的REST资源文件是用@RequestScoped注释的,但它不是?

时间:2017-06-12 21:39:52

标签: java dependency-injection guice jboss-weld

我有一个由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!

我有几个问题,因为我是这个领域的新手,我需要一些指导才能继续前进,因为我不知道我是否还没有看过让这个应用程序启动并运行的东西我遇到了一个奇怪的问题情况下。

  • 围绕@EJB的Weld是如何形成的?我知道我的会话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:

@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$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 }

4 个答案:

答案 0 :(得分:1)

首先,您的构造函数使用

进行注释
@com.google.inject.Inject

这绝对不对。Inject注释来自javax.inject包。

其次,你的bean必须有一个没有参数的构造函数。如果您希望通过构造函数@Inject,它必须是CDI知道的bean。

您可以尝试:

  • 从CurrencyResource构造函数中删除参数。
  • 修复@Inject注释(javax.inject包)

答案 1 :(得分:1)

从标题中回答你的问题:默认情况下在WildFly中(如果启用了CDI和JAX-RS),任何JAX-RS资源都会被CDI扩展分析,如果它没有使用范围注释注释,@RequestScoped会自动添加。

对JAX-RS资源的构造函数注入的支持是可选的,即规范不需要。而且我不确定RESTEasy是否支持这个...我认为它不支持。

答案 2 :(得分:1)

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

当您将构造函数更改为不带参数时,您也可以将注入移动到init方法而不是逐个注入。这就是我们在公司里做的事情,我们也使用标准CDI的wildfly 10。

这就像这样:

public CurrencyResource(){
}

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

答案 3 :(得分:0)

感谢所有答案!

我的代码中存在许多问题:

  • 并非所有实现某些业务逻辑的代码都由@EJB
  • 注释
  • 我想注射Guice并以某种方式混合进口
  • 有一个@EJB注入,我引用了类而不是接口

我为解决这个问题做了什么:

  • 我通过业务逻辑类重构,所有这些都是无状态会话bean
  • CDI可以轻松包含它们,不再需要Guice
  • 我也修复了参考问题

效果不佳。