简体   繁体   中英

CDI Dependency Injection on explicitly added classes fails

Soo i thought it would be simple, but then:

I have some small test. It tests a CDI Dependency injection:

//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
      }
 }

The CustomerEditController injects a private CustomerListController, who itself injects a private CustomerDetailsController.
All the controllers are SessionScoped (I know I shouldn't, but it is a prototype project either way, also i wasn't able to get events running yet.)
Resources is a custom class to provide Logger, EntityManager for Persistence and FacesContext for error messages. All Controllers are in the Package "company.product.controller"

When I now run this test as a Standard JUnit test ( Alt + Shift + X , T ) i get the Error message:

org.jboss.arquillian.container.spi.client.container.DeploymentException: Could not deploy to container: {"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 Unsatisfied dependencies for type [CustomerDetailsController] with qualifiers [@Default] at injection point [[field] @Inject company.product.controller.CustomerListController.customerDetailsController]"}}

I tried to add all the Controllers explicitly in the addClasses call, but unfortunately there were no changes in the result.

EDIT:

here is a skeletalized 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();
}

The controllers all work almost the same, the annotations are the same, so i'll just post one of 'em here:

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

And here are the Services:

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

And this is the corresponding implementation:

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

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

EDIT 2:
After commenting the problematic injected CustomerDetailsController (even though i really need it), I got a new Error message: Could not inject CDI Bean
After moving through the StackTrace a bit, i found that the persistence is not included, so I adjusted the @Deployment Method. unfortunately now i get the error, that my persistenceunit cannot find the datasource.

I double checked the names, and i am positive they are the same.

After hours of searching i found out, that (as mentioned in the question) the hibernate Datasource used in the CustomerListProducer and the Services Package was configured incorrectly.

Thanks to @rubenlop88 I was able to add the datasource in the correct manner. this resolved the underlying conflict. I still got a load of errors from the missing services Package.

To make creating new Tests easier and to centralize the testarchive-creation I introduced a new abstract class, that does this for all Tests:

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

this class gets extended by all tests, so any changes necessary to the package-generation can be made centralized

To point out the obvious, CustomerDetailsController has a qualifier annotation on it (@Named), which prevents it from being picked up by a default inject. That's what the Weld warning is about. You'll need to either remove the qualifier from the bean or add it to your injection point.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM