为什么 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!

我有几个问题,因为我是这个领域的新手,我需要一些前进的方向,因为我不知道我是否没有读过一些东西来启动这个应用程序 运行 我遇到了一个奇怪的案例

请在下面找到我的申请代码:

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
  • 我也解决了引用问题

效果不佳。