2

Су, я думал, это будет просто, но затем:CDI Dependency Injection на явно добавленных классах не работает

У меня есть небольшой тест. Он проверяет инъекцию 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 (я знаю, что не должен, но это прототип проекта в любом случае, также я еще не смог запустить события.)
Ресурсы - это настраиваемый класс для обеспечения Logger, EntityManager для 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 в сервисе jboss.deployment.unit. \" testCDI.war \ ". WeldService: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Неудовлетворенный отпечаток endencies для типа [CustomerDetailsController] с классификаторами [@default] в точке инъекции [[поле] @Inject company.product.controller.CustomerListController.customerDetailsController] "}}

Я пытался добавить все контроллеры явно в вызове addClasses, но, к сожалению, изменений в результате не было.

EDIT:

вот 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(); 
} 

Контроллеры все работают почти то же самое, что аннотаций являются то же самое, так что я буду просто разместить одну из " 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 
} 

И вот услуги:

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

EDIT 2:
После комментирования проблемное впрыскивается CustomerDetailsController (хотя я на самом деле это нужно), я получил новое сообщение об ошибке: Could not inject CDI Bean
Немного переместившись через StackTrace, я обнаружил, что постоянство не включено, поэтому я скорректировал метод @Deployment. к сожалению, теперь я получаю ошибку, что мой persistenceunit не может найти источник данных.

Я дважды проверял имена, и я уверен, что они такие же.

+0

- CustomerListController вводит единственный объект CustomerDetailsListController ob; или коллекция List ob; –

+0

@bhutto Его единственный объект. Там только введенный список , который поступает от CustomerListProducer. Он вводится в CustomerListController, который будет выбирать одного клиента для перехода к CustomerDetailsController для отображения деталей. Та же процедура выполняется при редактировании Клиента. Он просто передает материал CustomerEditController вместо – Vogel612

+0

Можете ли вы опубликовать классы? Любые квалификаторы в классе? –

ответ

0

После нескольких часов поиска я узнал, что (как упоминалось в вопросе) спящий источник данных, используемый в CustomerListProducer и пакете услуг, был настроен неправильно.

Благодаря @ 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"); 
    } 
} 

этот класс получает продлен на всех тестах, так что любые изменения, необходимые к пакетной генерации может быть сделана централизованная

0

Чтобы указать на очевидное, CustomerDetailsController имеет аннотацию классификатора на ней (@Named), которая предотвращает ее получение по умолчанию. Это то, о чем предупреждает Свард. Вам нужно либо удалить классификатор из компонента, либо добавить его в точку инъекции.

+0

Как вы можете заметить из моего ответа, я решил эту проблему почти два года назад ... и решение не включало ни удалив классификатор из компонента или добавив его в точку ввода, так что есть ... – Vogel612

+0

Да, может быть, мне нужно привыкнуть к чтению временных меток. Просто заметил, что Weld попытался найти (т. Е. Классификатор по умолчанию) и то, что было указано в исходных фрагментах. Не означает, что нужно драться. – jvalli