Я работаю над проектом JSF с использованием CDI. Мы используем SonarQube для управления качеством кода. Одной из проблем, возникших после сканирования в нашем проекте, является S3306: «Constructor injection should be used instead of field injection».Как использовать @Inject в управляемых битах CDI, соответствующих правилу SonarQube S3306
Это было вызвано впрыскивает, которые мы используем в наших бобах, например:
@Named
@ViewScoped
public class AccountsController extends AbstractController<Account> {
@Inject
private AccountsFacade accountsFacade;
public AccountsController() {
super(Account.class);
}
...
}
Введенный являются фасадами, как:
@Stateless
public class AccountsFacade extends AbstractFacade<Account> {
@PersistenceContext(unitName = "...")
private EntityManager entityManager;
public AccountsFacade() {
super(Account.class);
}
...
}
Информационных по данному вопросу, предоставленный SonarQube:
Field injection seems like a tidy way to get your classes what they need to do their jobs, but it's really a
NullPointerException
waiting to happen unless all your class constructors areprivate
. That's because any class instances that are constructed by callers, rather than instantiated by the Spring framework, won't have the ability to perform the field injection.Instead
@Inject
should be moved to the constructor and the fields required as constructor parameters.This rule raises an issue when classes with non-
private
constructors (including the default constructor) use field injection.
Предлагаемое решение:
class MyComponent {
private final MyCollaborator collaborator;
@Inject
public MyComponent(MyCollaborator collaborator) {
Assert.notNull(collaborator, "MyCollaborator must not be null!");
this.collaborator = collaborator;
}
public void myBusinessMethod() {
collaborator.doSomething();
}
}
С managed beans are created using a constructor with no arguments, существует ли какой-либо способ соблюдения правила SonarQube?
Редактировать: Я считаю это актуальным: мы используем CDI. Я не уверен, что здесь применяется предыдущая ссылка (документация Oracle).
Редактировать 2: Я просто попробовал предлагаемое решение после того, как прочитал документацию по адресу WELD injection points. Но это дает мне эту ошибку:
WELD-001435: Normal scoped bean class ...AccountsController is not proxyable because it has no no-args constructor
Редактировать 3: Ошибка редактирования 2 действительно (см комментарии на вопрос), вызванные @Inject
из AccountsController
в другой контроллер. См. Также ответ.
Вы уверены, что это должно быть '@Inject общественного MyComponent (MyCollaborator сотрудник) {...}' и 'не общественное MyComponent (@Inject MyCollaborator соавтор) {...} '? См. Также http://stackoverflow.com/questions/19381846/why-use-constructor-over-setter-injection-in-cdi – Kukeltje
Хмммм ... противоречивая информация ... (никогда не использовалась конструкция конструктора) ... – Kukeltje
Ваш пример кажется действительно правильным ... Странно и btw ... 'Spring framework' в документах sonarcube? Hmmmm Может быть, переопределить правило sonarcube ;-) – Kukeltje