对显式添加的类的CDI依赖注入失败

时间:2013-12-02 14:29:21

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

所以我觉得这很简单,但后来:

我有一些小测试。它测试了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。 所有控制器都在Package&#34; company.product.controller&#34;

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

  

org.jboss.arquillian.container.spi.client.container.DeploymentException:无法部署到容器:{&#34; JBAS014671:服务失败&#34; =&GT; {&#34; jboss.deployment.unit \&#34; testCDI.war \&#34; .WeldService&#34; =&GT;服务中的&#34; org.jboss.msc.service.StartException:jboss.deployment.unit。\&#34; testCDI.war \&#34; .WeldService:org.jboss.weld.exceptions.DeploymentException: WELD-001408类型 [CustomerDetailsController] 的类型 [CustomerDetailsController] ,注入点[[field] @Inject company.product.controller.CustomerListController.customerDetailsController]&#34;带有限定符[@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();
}

控制器的工作方式几乎相同,注释 相同,所以我只是在这里发布一个&#39; em:

@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方法。不幸的是现在我得到错误,我的persistenceunit找不到数据源。

我仔细检查了名字,我很肯定他们是一样的。

2 个答案:

答案 0 :(得分:0)

经过几个小时的搜索后我发现,(在问题中提到),CustomerListProducer和Services Package中使用的hibernate数据源配置不正确。

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

为了使创建新测试变得更容易并集中化testarchive创建,我引入了一个新的抽象类,为所有测试执行此操作:

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

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

答案 1 :(得分:0)

要指出显而易见的,CustomerDetailsController上有一个限定符注释(@Named),这可以防止它被默认注入拾取。那是焊接警告的内容。您需要从bean中删除限定符或将其添加到注入点。