2011-06-23 45 views
19

私は、Ajaxのいくつかの動作を使用するJSF 2コンポジットコンポーネントを使用しています。複合コンポーネント内の<f:ajax>タグにlistenerメソッドを追加しますが、listenerメソッドは<composite:interface><composite:attribute>として提供する必要があります。JSF 2 - 複合コンポーネント・インターフェースにAjaxリスナー・メソッドを追加するにはどうすればいいですか?

私の複合コンポーネント内<f:ajax>タグは現在、このようなリスナーにハードコードされている:

<f:ajax 
    event="valueChange" 
    execute="@this" 
    listener="#{controller.genericAjaxEventLogger}" 
    render="#{cc.attrs.ajaxRenderTargets}" /> 

Beanのリスナーメソッドは、このシグネチャを持つ:

public void genericAjaxEventLogger(AjaxBehaviorEvent event) 
     throws AbortProcessingException { 
    // implementation code... 
} 

私が複合したいですコンポーネントはこのようなものになるので、ページは独自のイベントメソッドを提供できますが、インターフェイスの正しい構文を理解できません。

<f:ajax 
    event="valueChange" 
    execute="@this" 
    listener="#{cc.attrs.ajaxEventListener}" 
    render="#{cc.attrs.ajaxRenderTargets}" /> 

どうすればよいですか? SOLUTIONで更新

私はBalusCによって提案されたアプローチを取って、それは素晴らしい作品。関連するスニペットは、以下のとおりです。

複合コンポーネントのインターフェイス宣言

<composite:interface> 
    <composite:attribute 
     name="myattributeUpdatedEventListener" 
     method-signature="void listener()" 
     required="true" /> 
    ... 
</composite:interface> 

私の複合部品

<f:ajax 
    event="valueChange" 
    execute="@this" 
    listener="#{cc.attrs.myattributeUpdatedEventListener}" 
    render="#{cc.attrs.ajaxRenderTargets}" /> 

私は複合コンポーネントを使用して、私のページの代わりに、使用Ajaxのタグ

<h:form> 
    <compcomp:myCompositeComponent 
     myattributeUpdatedEventListener="#{myBackingBean.updatedEventListenerXYZ}" /> 
</h:form> 

そして、私の裏打ち豆の方法

+0

解決に感謝、それは本当に私を助けます。 –

+0

パラメータでメソッドを渡すことは可能ですか?例のように#{myBackingBean.updatedEventListenerXYZ}を渡すのではなく、#{myBackingBean.myMethod(cc.attrs.myparam)}のようなものを渡してください。 – dcalap

答えて

21

あなたは

public void genericAjaxEventLogger() { 
    // ... 
} 

AjaxBehaviorEvent引数の取り除くことができた場合は引数が必須であるなら、あなたは、ロギングのために(

<cc:attribute name="ajaxEventListener" method-signature="void listener()" /> 

を使用することができますか?

SEVERE: javax.faces.FacesException: wrong number of arguments 
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:89) 
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) 
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) 
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:409) 
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1534) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) 
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655) 
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595) 
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98) 
    at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162) 
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:326) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:227) 
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:170) 
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:822) 
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:719) 
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1013) 
    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(Unknown Source) 
Caused by: java.lang.IllegalArgumentException: wrong number of arguments 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at com.sun.el.parser.AstValue.invoke(AstValue.java:234) 
    at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:297) 
    at com.sun.faces.facelets.el.ContextualCompositeMethodExpression.invoke(ContextualCompositeMethodExpression.java:177) 
    at com.sun.faces.facelets.tag.TagAttributeImpl$AttributeLookupMethodExpression.invoke(TagAttributeImpl.java:450) 
    at com.sun.faces.facelets.tag.jsf.core.AjaxBehaviorListenerImpl.processAjaxBehavior(AjaxHandler.java:447) 
    at javax.faces.event.AjaxBehaviorEvent.processListener(AjaxBehaviorEvent.java:113) 
    at javax.faces.component.behavior.BehaviorBase.broadcast(BehaviorBase.java:102) 
    at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:760) 
    at javax.faces.component.UICommand.broadcast(UICommand.java:300) 
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794) 
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259) 
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81) 
    ... 28 more 

<cc:attribute name="ajaxEventListener" method-signature="void listener(javax.faces.event.AjaxBehaviorEvent)" /> 

しかし、次のように+クロサギ科2.1.1 GF 3.1に

<f:ajax listener="#{cc.attrs.ajaxEventListener}" /> 

と予想されるように)、あなたは、これはここで働いていない、属性を再指定する必要があります

これはバグかどうかわかりません。そのためには、それを解決するためにもう少し時間を費やす必要があります。しかし、それは属性からMethodExpressionを取得し、適切な数の引数で起動するバッキングコンポーネントを作成することで回避できました。 )

;かかわらず、私はバッキングコンポーネントはとにかく心に持っていた機能要件を実現するための新しい方法のためのオープンドアを置くことを信じ

package com.example; 

import javax.el.MethodExpression; 
import javax.faces.component.FacesComponent; 
import javax.faces.component.UINamingContainer; 
import javax.faces.context.FacesContext; 
import javax.faces.event.AjaxBehaviorEvent; 

@FacesComponent(value="testCC") 
public class TestCC extends UINamingContainer { 

    public void ajaxEventListener(AjaxBehaviorEvent event) { 
     FacesContext context = FacesContext.getCurrentInstance(); 
     MethodExpression ajaxEventListener = (MethodExpression) getAttributes().get("ajaxEventListener"); 
     ajaxEventListener.invoke(context.getELContext(), new Object[] { event }); 
    } 

} 

<ui:component 
    xmlns:f="http://java.sun.com/jsf/core" 
    xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:cc="http://java.sun.com/jsf/composite" 
    xmlns:ui="http://java.sun.com/jsf/facelets" 
> 
    <cc:interface componentType="testCC"> 
     <cc:attribute name="ajaxEventListener" method-signature="void listener(javax.faces.event.AjaxBehaviorEvent)" /> 
    </cc:interface> 
    <cc:implementation> 
     <h:commandButton value="Submit"> 
      <f:ajax listener="#{cc.ajaxEventListener}" /> 
     </h:commandButton> 
    </cc:implementation> 
</ui:component> 

:ここでは完全なキックオフの例です

+1

ありがとうございます。私は、CCインタフェースでアクションメソッドを宣言する例をたくさん見つけましたが、リスナメソッドを宣言するためのものはありませんでした。 'method-signature'の' listener() '部分はJSFが理解できる特別な値ですか? –

+4

メソッド名は関係ありません。 'xyz()'の名前を付けることさえできます。それは単なる自己記述の例でした。最も重要なのは、メソッドの戻り値およびパラメータ型の完全修飾クラス名です。 – BalusC

+0

正確に私が探していた;) – boblemar

1

ここでは、インターフェイスを使用して属性を設定し、実装内で参照する方法の例を示します。呼び出されるメソッドのメソッド署名を定義する必要があります。これは、コンポジットコンポーネントハンドラに、#{cc.attrs.ajaxEventListener}式に含まれる値式ではなくメソッド値があることを通知します。

<cc:interface name="composite-comp" 
    <cc:attribute required="true" name="ajaxEventListener" 
        method-signature="void f1(javax.faces.event.AjaxBehaviorEvent)" /> 
    <cc:attribute required="true" name="ajaxRenderTargets" /> 
</cc:interface> 

<cc:implementation> 
    . 
    . 
    . 
    <f:ajax event="valueChange" execute="@this" 
     listener="#{cc.attrs.ajaxEventListener}" 
     render="#{cc.attrs.ajaxRenderTargets}" /> 
</cc:implementation> 
+0

あなたはどの環境でそれをテスト/使用しましたか?これはMojarra 2.1.1のGF 3.1とTomcat 7で私にとっては失敗します。 – BalusC

関連する問題