@ManagedBean の代わりに CDI を使用する:スーパークラスに引数なしのコンストラクターがないため、UnproxyableResolutionException が発生する

StackOverflow https://stackoverflow.com/questions/3840240

  •  27-09-2019
  •  | 
  •  

質問

JSF/Java EE アプリケーションに CDI を使用しようとしています。次のクラス階層があります。

/**
 * base controller class
 * also contains some final methods and an inner enum class declaration
 */
public abstract class AbstractCrudController<K, E> implements Serializable {
  private Class<E> entityClass;

  public AbstractCrudController(Class<E> entityClass) {
    this.entityClass = entityClass;
  }

  // ...
}


import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

@Named
@SessionScoped
public class CategoryController extends AbstractCrudController<Long, Category> implements Serializable {
  public CategoryController() {
    super(Category.class);
  }
  //...
}

アプリケーションを GF 3.1 にデプロイしようとすると、次の CDI/Weld 例外が発生します。

厳しい:アプリのロード中の例外:weld-001435通常のスコープビーンクラスcom.web.abstractcrudcontrollerには、ARGSコンストラクターがないため、プロキシできません。org.jboss.weld.Exceptions.UnproxyableResolutionException:weld-001435通常のスコープビーンクラスcom.web.abstractcrudcontrollerには、ARGSコンストラクターがないため、プロキシできません。at org.jboss.weld.util.Proxies.getUnproxyableClassException(Proxies.java:215) at org.jboss.weld.util.Proxies.getUnproxyableTypeException(Proxies.java:166) at org.jboss.weld.util.Proxies.getUnproxyableTypesException (proxies.java:191)atorg.jboss.weld.bootstrap.validator.validatebean(validator.java:134)at org.jboss.weld.weld.weld.validator.validateribean(validator.java:148)at org.jboss。 weld.bootstrap.validator.validatebeans(validator.java:363)at org.jboss.weld.bootstrap.validator.validatedeployment(validator.java:349)at org.jboss.weld.weld.boottrap.weldboottrap.validatebians(weldbottrap.jaba: 416)atorg.glassfish.weld.welddeployer.event(welddeployer.java:178)atorg.glassfish.kernel.event.eventsimpl.send(eventsimpl.java:128) (applicationinfo.java:265)atcom.sun.enterprise.v3.server.applicationlifecycle.deploy(applicationlifecycle.java:402)at com.sun.enterprise.v3.server.applicationlifecycle.deploy(ApplicationLifecyce.Java:221) com.sun.enterprise.v3.admin.commandrunnerimpl $ 1.execute(commandrunnerimpl.java:360)at com.sun.v3.dminmin.v3.olprise.v3.olprise.v3.olprise.v3.olprise.v3.dminminのdexecute(deploycommand.java:351)at com.sun.enterprise.v3.adminsrunnerimpl at com.sun.v3.olprise.V3. Com.sun.enterprise.v3.admin.commandrunnerimpl.docommand(commandrunnerimpl.java:1072)at com.sun.enterprise.v3.admin.commandrunnermpl.runnermpl.chess $ 12.cesss $ 12.cess $ 12.cess $ 12.cess $ 12.cess $ 12.cess $ 12。 Java:101)atcom.sun.enterprise.v3.admin.commandrunnerimpl $ executioncontext.execute(commandrunnerimpl.java:1221)at com.sun.enterprise.v3.admin.commandrunnerimpl $ exexutioncontext.execute(commandrunnerimpl.java:1210) com.sun.enterprise.v3.admin.adminadapter.docommand(adminadapter.java:375)at com.sun.enterprise.v3.admin.adminadapter.service(adminadapter.java:209)at com.sun.tcpp .http11.grizzlyadapter.service(grizzlyadapter.java:166)at com.sun.enterprise.v3.server.hk2dispatcher.dispath(hk2dispatcher.java:117)at com.sun.enterprise.v3.Services.impl.continermapperseverseversever (conterermapper.java:234)com.sun.grizzly.http.processortask.invokeadapter(processortask.java:824)at com.sun.grizzly.http.processortask.doprocess(processortask.java:721) grizzly.http.processortask.process(processortask.java:1014)at com.sun.grizzly.http.defaultprotocolfilter.execute(defaultprotocolfilter.java:220)at com.sun.sun.grizzly.defaultprotocolchain com.sun.grizzly.defaultprotocolchain.execute(defaultprotocolchain.java:102)でcom.sun.grizzly.defaultprotocolchain.execute(defaultprotocolchain.java:88)at com.sun.grizzly.http.htppptprotocolchain(htpprotocolchain)execolchain.htppprotocolchain execolchain. :76)com.sun.grizzly.protocolchaincontexttask.docall(protocolchaincontexttask.java:53)at com.sun.grizzly.selectionKeycontexttask.call(selectionkeycontexttask.java:57) Java:69)atcom.sun.grizzly.util.abstractthreadpool $ worker.dowork(abstractthreadpool.java:530)at com.sun.grizzly.utilttractthreadpool $ worker.run(abstractthreadpool.java:511) .thread.run(thread.java:637)

引数なしのコンストラクターを基本クラスに追加した場合でも、Weld は依然として、クラスには Final メソッドがあるためプロキシ可能ではないという同じ例外を報告します。WELD によってクラス設計の変更が強制されるのはなぜですか?JSF @ManagedBean アノテーションを使用すると、すべてが正常に機能しました。

助けていただければ幸いです。ありがとう、テオ

役に立ちましたか?

解決

WELD によってクラス設計の変更が強制されるのはなぜですか?JSF @ManagedBean アノテーションを使用すると、すべてが正常に機能しました。

まあ、Weld/CDI は同じようには機能しません。私の理解では、インジェクションを使用して Bean への参照を取得すると、得られるものは次のとおりです。 ほとんどの場合 プロキシオブジェクト。このプロキシ オブジェクトは Bean をサブクラス化し、メソッドをオーバーライドして委任を実装します。これにより、CDI がプロキシできるクラスにいくつかの制限が導入されます。

CDI 仕様では次のように記述されています。

5.4.1.プロキシ不可能な Bean タイプ

特定の合法的な豆の種類は、コンテナによってプロキシ化することはできません。

  • パラメーターのない非プライベートコンストラクターを持たないクラス、
  • Final として宣言されたクラス、または Final メソッドを持つクラス、
  • プリミティブ型、
  • そして配列型。

宣言されたタイプをコンテナによってプロキシできない噴射点が通常のスコープで豆に解決できない場合、コンテナは問題を自動的に検出し、展開の問題として扱います。

私の提案は、メソッドを非最終的なものにすることです。

参考文献

  • CDI仕様
    • セクション5.4。「クライアントプロキシ」
    • 5.4.1項「プロキシ不可能なBeanタイプ」
    • セクション6.3。「通常スコープと擬似スコープ」

他のヒント

私は、JSFマネージド豆からCDIへの移行の過程で豆を管理しています、と私は、Aのhref = "http://docs.oracle.com/javase/tutorial/java/ <私が使用することができる午前ことを確認しましたことは、 '拡張'(@default修飾子付き)祖先CDIビーン( 'カスタム' @Descendant修飾子付き)スーパーに成功した子孫CDI Bean内IandI / super.html」のrel = "nofollowを">。

@default修飾子とCDIビーン祖先ます:

@Default
@Named("pf_pointOfContactController")
@SessionScoped
public class pf_PointOfContactController implements Serializable {

祖先Beanは、以下があります:

@PostConstruct
protected void init() {

@Descendant修飾子とCDI豆子孫ます:

@Descendant
@Named("pf_orderCustomerPointOfContactController")
@SessionScoped
public class pf_OrderCustomerPointOfContactController extends pf_PointOfContactController {
子孫Beanは、以下があります:

@PostConstruct
public void init(){
    super.init();
祖先Beanの@PostConstructはCDI @Descendant豆で実行されていないので、祖先CDI Bean内のメソッドが、NullPointerExceptionが引き上げられたためです。

私は、)(/使用でsuper.initを追加する必要がありました

私が見てきた/聞いた/祖先Beanのコンストラクタは、「初期化」のロジックを持っていた、と祖先JSFを使用している場合、Beanのコンストラクタを自動的に実行/起動されたので、CDIを使用するときに代わりにコンストラクタメソッドの@PostConstruct使用することを推奨していることを読みます豆を管理します。

受け入れられた回答は正しいですが不完全なので、将来の読者のために 2 セントを追加してもよいと思います。

OP が遭遇した問題は 2 つの方法で解決できます。

  1. 取り除くことで final メソッドとクラス自体のキーワード
  2. このような「プロキシ不可能なクラス」にマークを付けると、 @Singleton または @Dependent 疑似スコープ (もちろん意味がある場合)。CDI は擬似スコープ Bean のプロキシ オブジェクトを作成しないため、これは機能します。

OP のユースケースでは、コントローラーは確実にシングルトンとしてマークできるため、IMHO の 2 番目のアプローチが推奨されました。

誰かの役に立てば幸いです

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top