【问题标题】:CDI Dependency Injection on explicitly added classes fails显式添加的类上的 CDI 依赖注入失败
【发布时间】:2013-12-02 14:29:21
【问题描述】:

我以为这很简单,但后来:

我有一些小测试。它测试 CDI 依赖注入:

//Imports
@RunWith(Arquillian.class)
public class EditCustomerTest
{
     @Deployment
     public WebArchive createTestArchive()
     {
        return ShrinkWrap
           .create(WebArchive.class, "testcrm.war")
           .addClass(CustomerListProducer.class)
           .addPackage("company.product.controller")
           .addPackage("company.product.model")
           .addPackage("company.product.util")
           .addPackage("company.product.services")
           .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
           .addAsResource("test-ds.xml", "ds.xml")
           .addAsResource("META-INF/test-persistence.xml", "META-INF/persistence.xml");
      }

      @Inject 
      CustomerEditController customerEditController;

      @Inject
      List<Customer> customers;

      @Test
      public void testInjectionResolution(){
           Assert.assertNotNull(customerEditController);
           //do some stuff, where actually nothing happens
      }
 }

CustomerEditController 注入一个私有的 CustomerListController,它自己注入一个私有的 CustomerDetailsController。
所有控制器都是 SessionScoped(我知道我不应该这样做,但无论如何它都是一个原型项目,而且我还无法让事件运行。)
Resources 是一个自定义类,用于提供 Logger、EntityManager for Persistence 和 FacesContext 用于错误消息。 所有控制器都在“company.product.controller”包中

当我现在将此测试作为标准 JUnit 测试运行时 (Alt+ Shift + X, T) 我收到错误消息:

org.jboss.arquillian.container.spi.client.container.DeploymentException: 无法部署到容器:{"JBAS014671: Failed services" => {"jboss.deployment.unit.\"testCDI.war\". WeldService" => "org.jboss.msc.service.StartException in service jboss.deployment.unit.\"testCDI.war\".WeldService: org.jboss.weld.exceptions.DeploymentException: WELD-001408 不满足的依赖关系 用于类型 [CustomerDetailsController],在注入点 [[field] @Inject company.product.controller.CustomerListController.customerDetailsController]"}}

带有限定符 [@Default]

我尝试在 addClasses 调用中显式添加所有控制器,但不幸的是结果没有变化。

编辑:

这是一个骨架化的 CustomerListProducer:

@ApplicationScoped
public class CustomerListProducer implements Serializable{

     @Inject
     CustomerService customerServiceBean;

     private static final long serialVersionUID = 1L;
     private List<Customer> customers = new ArrayList<Customer>();
     private Random rnd;
     //some private static final String[] to create DummyData from

     @PostConstruct
     public void init(){
         //check if database is empty, and if then generate DummyData and persist them
     }

     //these call the ServiceBeans implementation to persist the changes
     //the qualifiers are declared in class Events in the package company.product.util
     public void onCustomerAdded(@Observes @Added Customer customer);
     public void onCustomerDeleted(@Observes @Deleted Customer customer);
     public void onCustomerUpdated(@Observes @Updated Customer customer);

     @Named
     @Produces
     public List<Customer> getCustomers();
}

所有控制器的工作方式几乎相同,注释相同,所以我将在此处发布其中一个:

@Named
@SessionScoped
public class  CustomerDetailsController implements Serializable {
     private static final long serialVersionUID = 1L;

     private Customer customer = new Customer();

     // Inject dependent Controllers. there are no events to pass data between views yet
     @Inject
     ContractEditController contractEditController;
     @Inject
     AddContactPersonController addContactPersonController;

     @Inject
     Resources res;

     @Named
     @Produces
     public Customer getCustomer();

     //CRUD-Events for the Customer that are fired, to persist modifications
}

这里是服务:

@Named
@ApplicationScoped
public interface CustomerService{
    public List<Customer> getAllCustomers();
    public void addCustomer(Customer c);
    public void deleteCustomer(Customer c);
    public void updateCustomer(Customer c);
}

这是对应的实现:

@Stateless
public class CustomerServiceBean implements CustomerService{
    @Inject
    EntityManager entityManager;

    //implementations for the CustomerService Methods, using the Entity Manager
}

编辑 2:
在评论了有问题的注入 CustomerDetailsController(即使我真的需要它)后,我收到一条新的错误消息:Could not inject CDI Bean
通过StackTrace移动了一下,我发现持久化不包括在内,所以我调整了@Deployment Method。不幸的是,现在我得到了错误,即我的持久性单元找不到数据源。

我仔细检查了名字,我确定它们是一样的。

【问题讨论】:

  • 是CustomerListController注入单个对象CustomerDetailsListController ob;或 List ob; 的集合
  • @bhutto 它是唯一的对象。只有一个来自 CustomerListProducer 的注入列表 。它被注入到 CustomerListController,它将选择一个客户传递给 CustomerDetailsController 以显示详细信息。编辑客户时运行相同的过程。它只是将东西传递给 CustomerEditController
  • 你能发布课程吗?课堂上有任何限定词吗?
  • 嗨@JohnAment 目前它在 getmany 的凌晨 1 点,我没有在工作......这使得完成您的请求有点困难。你还能问我具体的课程吗?我不想包含那么多不相关的代码以使问题尽可能容易理解。
  • @Vogel612 很难从针对此问题发布的较少信息中识别出来,Jhon Ament 是对的,您必须发布您的 Qualifier 并且只需使用虚拟骨架主体的接口/类。

标签: java dependency-injection cdi jboss-arquillian shrinkwrap


【解决方案1】:

经过数小时的搜索,我发现(如问题中所述)CustomerListProducer 和服务包中使用的休眠数据源配置不正确。

感谢@rubenlop88,我能够以正确的方式添加数据源。这解决了潜在的冲突。我仍然从缺少的服务包中得到很多错误。

为了使创建新测试更容易并集中测试归档创建,我引入了一个新的抽象类,它对所有测试都执行此操作:

@RunWith(Arquillian.class)
public abstract class TestBundle{
     @Deployment
     public static WebArchive createTestArchive() {
         return ShrinkWrap
            .create(WebArchive.class, "testArchive.war")
            .addClass(CustomerListProducer.class)
            .addPackage("company.product.controller")
            .addPackage("company.product.model")
            .addPackage("company.product.util")
            .addPackage("company.product.services")
            .addPackage("company.product.test")
            .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
            .addAsWebInfResource("test-ds.xml", "product-ds.xml")
            .addAsResource("META-INF/test-persistence.xml", "META-INF/persistence.xml");
     }
}

这个类得到了所有测试的扩展,因此包生成所需的任何更改都可以集中进行

【讨论】:

    【解决方案2】:

    为了明确指出,CustomerDetailsController 上有一个限定符注释 (@Named),它可以防止它被默认注入获取。这就是 Weld 警告的内容。您需要从 bean 中删除限定符或将其添加到您的注入点。

    【讨论】:

    • 正如您从我的回答中看到的那样,我大约在两年前解决了这个问题......并且解决方案不包括从 bean 中删除限定符或将其添加到 injectionio m 点所以有那...
    • 是的,也许我应该养成阅读时间戳的习惯。只是注意到 Weld 试图找到的内容(即默认限定符)以及源 sn-ps 中列出的内容。不是故意要打架的。
    猜你喜欢
    • 1970-01-01
    • 2017-09-16
    • 2012-08-13
    • 2017-09-24
    • 1970-01-01
    • 2014-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多