2012-01-24 12 views
2

CDIを依存インジェクションに使用します。すべてのデータテーブルBean(以下のDataTableBeanなど)によって使用/注入される汎用クラスLazyAccountDataModelを実装する必要があります。一般的なLazyAccountDataModelは、それを注入するデータテーブルBeanに応じて、特定のタイプのファサードを処理する必要があります。私は次のようにLazyAccountDataModelで使用するファサードを決定するためのアプローチとして、ジェネリックを使用してみましたが、それは次の例外がスローされます。CDI:多重継承とジェネリック抽象化によるプロパティインジェクションの問題

@Named 
@RequestScoped 
public class DataTableBean 
{ 
    @Inject 
    private LazyAccountDataModel<IAccount, IAccountFacade> lazyModel; 
} 

@Named 
@RequestScoped 
public class LazyAccountDataModel<DO extends IDomainObject, FACADE extends 
IPersistableFacade<DO>> extends LazyDataModel<DO> 
{ 
    @EJB (@Named doesn't work here due to WELD bug GLASSFISH-16186 which is not-optimal) 
    private FACADE facade; 

    private List<DO> datasource; 

    @Override 
    public List<DO> load(int first, int pageSize, String sortField, SortOrder 
     sortOrder, Map<String, String> filters) 
    { 
    setRowCount((int) facade.findTotalCount()); 

    // do more work on specific facade derivation (IAccountFacade in this case) 

    return datasource; 
    } 
} 

public interface IAccountFacade extends IPersistableFacade<IAccount> 
{ 
    public void logIn(String userName); 
} 

public interface IPersistableFacade<DO extends IDomainObject> extends IFacade<DO> 
{ 
    void create(DO domainData); 

    List<DO> getAll(); 

    long findTotalCount(); 
} 

例外スタックトレース

SEVERE: Exception while loading the app : WELD-001408 Unsatisfied dependencies for type [LazyAccountDataModel<IAccount, IAccountFacade>] with qualifiers [@Default] at injection point [[field] @Inject private view.dashDOard.DataTableBean.lazyModel] 
    org.jDOss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [LazyAccountDataModel<IAccount, IAccountFacade>] with qualifiers [@Default] at injection point [[field] @Inject private view.dashboard.DataTableBean.lazyModel] 
     at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:270) 
     at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:106) 
     at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:129) 
     at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.java:351) 
     at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:336) 
     at org.jboss.weld.bootstrap.WeldDOotstrap.validateBeans(WeldDOotstrap.java:396) 
     at org.glassfish.weld.WeldDeployer.event(WeldDeployer.java:190) 
     at org.glassfish.kernel.event.EventsImpl.send(EventsImpl.java:128) 
     at org.glassfish.internal.data.ApplicationInfo.start(ApplicationInfo.java:306) 
     at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:462) 
     at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:240) 
     at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:382) 
     at com.sun.enterprise.v3.admin.CommandRunnerImpl$1.execute(CommandRunnerImpl.java:355) 
     at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:370) 
     at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1064) 
     at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$1200(CommandRunnerImpl.java:96) 
     at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1244) 
     at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1232) 
     at com.sun.enterprise.v3.admin.AdminAdapter.doCommand(AdminAdapter.java:459) 
     at com.sun.enterprise.v3.admin.AdminAdapter.service(AdminAdapter.java:209) 
     at com.sun.grizzly.tcp.http11.GrizzlyAdapter.service(GrizzlyAdapter.java:168) 
     at com.sun.enterprise.v3.server.HK2Dispatcher.dispath(HK2Dispatcher.java:117) 
     at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:238) 
     at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:828) 
     at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:725) 
     at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019) 
     at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225) 
     at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137) 
     at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104) 
     at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90) 
     at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79) 
     at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54) 
     at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59) 
     at com.sun.grizzly.ContextTask.run(ContextTask.java:71) 
     at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532) 
     at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513) 
     at java.lang.Thread.run(Thread.java:662) 

私たちの問題は非常によく似ています投稿の後:CDI producer method for data model。 誰かがLazyAccountDataModelを注入する方法に関するポインタを提供し、どのファサードを使用する必要があるかを指定できますか?

可能な解決策の1つは、特定のファサードタイプをLazyAccountDataModelとともに注入し、ファサードタイプを明示的に設定することです。しかし、これはクリーンなソリューションではありません。

@Named 
@RequestScoped 
public class DataTableBean 
{ 
    @EJB 
    private IAccountFacade facade; 

    @Inject 
    private LazyAccountDataModel<IAccount> lazyModel; 

@PostConstruct 
public void init() 
{ 
    // would rather this stayed decoupled/handled by IoC framework 
    lazyModel.setfacade(facade); 
} 


@Named 
@RequestScoped 
public class LazyAccountDataModel<DO extends IDomainObject> extends LazyDataModel<DO> 
{ 
    private IPersistableFacade<DO> facade; 

    private List<DO> datasource; 

    @Override 
    public List<DO> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters) 
    { 
      setRowCount((int) facade.findTotalCount()); 

     // do more work on specific facade derivation (IAccountFacade in this  case) 
     return datasource; 
    } 

    public void setfacade(IPersistableBusinessObjectfacade<DO> facade) 
    { 
     this.facade = facade; 
    } 
} 

別の解決策は次のように文脈の生産を使用することがありますhttp://blog.frankel.ch/further-into-cdi しかし、これは抽象化の2-深層のために動作するようには思えません。このユースケースは、コンテキストXMLにネストされたプロパティを指定することで、Springで簡単に実装できます。 CDIでこれをどのように行うことができるのか、誰でも入力できますか?どんな助けもありがとう。

ありがとうございました。

答えて

3

Pete Muir(Weldを使用している場合)によると、これはバグです。詳細はこちらCDI events and generics

+0

は、私たちの質問を読んでために時間を取って、対応していただきありがとうございます。 – gkari

0

まず、@Named修飾子を使用する理由は?あなたがクラスでそれを使用していた場合は、注入ポイントにある必要があります。そうしないと、依存関係が解決されません。

2回目は私の経験から、CDIはジェネリック医薬品が好きではないと言うことができましたが、そのように動作させることはできません。しかし、あなたは次の操作を行います場合は、それが動作することがあります。 インターフェイスとして、このいずれかを行います。

LazyAccountDataModel<DO extends IDomainObject, FACADE extends IPersistableFacade<DO>> 

そして実装するクラスます次に、あなたはあなたの例のようにのように注入することができ

LazyAccountDataModel<IAccount, IAccountFacade> 

を。
私はこの部分が今まで動作することを疑う:

@EJB (@Named doesn't work here due to WELD bug GLASSFISH-16186 which is not-optimal) 
private FACADE facade;