2016-11-24 8 views
2

CDIを使用してJSFプロジェクトを作成しています。 SonarQubeを使用してコードの品質を管理しています。私たちのプロジェクトでスキャンを実行した後にポップアップした問題の1つは、S3306: "Constructor injection should be used instead of field injection"です。SonarQubeに準拠したCDIマネージドBeanで@Injectを使用する方法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 are private . 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の誤差は、他のコントローラ内のAccountsController@Injectによって引き起こされる(質問にコメントを参照)確かです。答えも見てください。

+0

は、あなたはそれが '@Inject 公共MyComponentの(MyCollaboratorコラボ){...}'はなく '公共MyComponentの(@Inject MyCollaboratorする必要がありますよろしいですコラボレーター){...} '?また、http://stackoverflow.com/questions/19381846/why-use-constructor-over-setter-injection-in-cdi – Kukeltje

+0

Hmmmm ....矛盾した情報...(コンストラクタの方法を使用したことはありません)... – Kukeltje

+1

あなたの例は確かに正しいようです...奇妙でbtw ... sonarcube文書の '春のフレームワーク'? Hmmmm sonarcubeルールをオーバーライドする可能性があります;-) – Kukeltje

答えて

1

@StatelessのクラスをPayara 4.1.1 163を使用してCDI Beanに注入するための推奨解決策があります。ただし、GlassFish 4.1では問題が発生しています。

のような他の豆に豆を注入するときは、このソリューションを適用するとさらに、:

@Named 
@ViewScoped 
public class OtherController extends AbstractController<Other> { 

    private final AccountsController accountsController; 

    @Inject 
    public OtherController(AccountsController accountsController) { 
    Assert.notNull(accountsController, "accountsController must not be null!"); 
    this.accountsController = accountsController; 
    } 

} 

..あなたは(質問の編集2で述べたように)、このエラーが発生します:

WELD-001435: Normal scoped bean class ...AccountsController is not proxyable because it has no no-args constructor

NB AccountsControllerが推奨どおりに修正されました。

私はOmniFaces Beansを使用してこの問題を解決:

@Named 
@ViewScoped 
public class OtherController extends AbstractController<Other> { 

    private final AccountsController accountsController; 

    public OtherController() { 
    this.accountsController = Beans.getInstance(AccountsController.class); 
    } 

} 
+0

これは解決策ですか、「回避策」ですか? – Kukeltje

+1

私はCDI/WELDのエキスパートではありませんが、問題のように感じています。その観点から、これは回避策です。 S3306の遵守の観点からは、これが解決策です。 –

関連する問題