JSF 2 - 我如何添加一个Ajax侦听器方法复合分量接口? [英] JSF 2 - How can I add an Ajax listener method to composite component interface?

查看:146
本文介绍了JSF 2 - 我如何添加一个Ajax侦听器方法复合分量接口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用一些Ajax行为JSF 2复合组件。我想补充一个监听器方法将< F:AJAX> 标签我的复合成分在里面,但监听器方法应被设置为<复合:属性> <复合:接口>

< F:AJAX> 我的复合组件内部的标签是目前硬coded到这样的监听器:

< F:AJAX     事件=valueChange     执行=@这个     听众=#{controller.genericAjaxEventLogger}     渲染=#{cc.attrs.ajaxRenderTargets}/>

在bean的侦听器方法有此签名:

 公共无效genericAjaxEventLogger(AjaxBehaviorEvent事件)
        抛出AbortProcessingException {
    //执行code ...
}
 

我要复合组件是这样这样的页面可以提供自己的事件的方法,但我想不通的正确语法的接口。

< F:AJAX     事件=valueChange     执行=@这个     听众=#{cc.attrs.ajaxEventListener}     渲染=#{cc.attrs.ajaxRenderTargets}/>

我怎样才能做到这一点?

更新解决方案:

我把由BalusC建议的方法和它的伟大工程。有关片段是:

在复合组件的接口声明

<复合:接口>     <复合:属性         NAME =myattributeUpdatedEventListener         方法签名=无效监听器()         所需=真/>     ... < /复合材料:接口>

在我的复合组件中使用Ajax的标签

< F:AJAX     事件=valueChange     执行=@这个     听众=#{cc.attrs.myattributeUpdatedEventListener}     渲染=#{cc.attrs.ajaxRenderTargets}/>

在这里我用的是复合材料零件在我的页面中的位置

< H:形式GT;     < compcomp:myCompositeComponent         myattributeUpdatedEventListener =#{myBackingBean.updatedEventListenerXYZ}/> < /小时:形式GT;

和对我的支持bean的方法

 公共无效updatedEventListenerXYZ(){
    //做的东西在这里...
}
 

解决方案

如果您的可以的摆脱了 AjaxBehaviorEvent 的说法,

 公共无效genericAjaxEventLogger(){
    // ...
}
 

那么你可以使用

< CC:属性名=ajaxEventListener方法签名=无效监听器()/>

如果该参数是强制性的(用于记录?),那么你需要重新指定属性如下:

< CC:属性名=ajaxEventListener方法签名=无效监听器(javax.faces.event.AjaxBehaviorEvent )/>

不过,这并没有在此预期与合作

< F:AJAX监听=#{cc.attrs.ajaxEventListener}/>

在GF 3.1 + Mojarra 2.1.1:

 重度:javax.faces.FacesException:错误的参数数量
    在com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:89)
    在com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    在com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    在javax.faces.w​​ebapp.FacesServlet.service(FacesServlet.java:409)
    在org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1534)
    在org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
    在org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    在org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    在org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    在com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98)
    在com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91)
    在org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162)
    在org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:326)
    在org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:227)
    在com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:170)
    在com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:822)
    在com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:719)
    在com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1013)
    在com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
    在com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    在com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    在com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    在com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    在com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    在com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    在com.sun.grizzly.ContextTask.run(ContextTask.java:71)
    在com.sun.grizzly.util.AbstractThreadPool $ Worker.doWork(AbstractThreadPool.java:532)
    在com.sun.grizzly.util.AbstractThreadPool $ Worker.run(AbstractThreadPool.java:513)
    在java.lang.Thread.run(来源不明)
致:java.lang.IllegalArgumentException:如果错误的参数数量
    在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)
    在sun.reflect.NativeMethodAccessorImpl.invoke(来源不明)
    在sun.reflect.DelegatingMethodAccessorImpl.invoke(来源不明)
    在java.lang.reflect.Method.invoke(来源不明)
    在com.sun.el.parser.AstValue.invoke(AstValue.java:234)
    在com.sun.el.MethodEx pressionImpl.invoke(MethodEx pressionImpl.java:297)
    在com.sun.faces.facelets.el.ContextualCompositeMethodEx$p$pssion.invoke(ContextualCompositeMethodEx$p$pssion.java:177)
    在com.sun.faces.facelets.tag.TagAttributeImpl$AttributeLookupMethodEx$p$pssion.invoke(TagAttributeImpl.java:450)
    在com.sun.faces.facelets.tag.jsf.core.AjaxBehaviorListenerImpl.processAjaxBehavior(AjaxHandler.java:447)
    在javax.faces.event.AjaxBehaviorEvent.processListener(AjaxBehaviorEvent.java:113)
    在javax.faces.component.behavior.BehaviorBase.broadcast(BehaviorBase.java:102)
    在javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:760)
    在javax.faces.component.UICommand.broadcast(UICommand.java:300)
    在javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
    在javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
    在com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    ... 28更多
 

我不知道这是否是一个错误或没有。为此我需要投入更多的时间来naildown它。然而,这是workaroundable通过创建后盾组件,它获得了 MethodEx pression 从属性和调用与参数的权数。下面是一个完整的开球例如:

<用户界面:组件     的xmlns:F =htt​​p://java.sun.com/jsf/core     的xmlns:H =htt​​p://java.sun.com/jsf/html     的xmlns:CC =htt​​p://java.sun.com/jsf/composite     的xmlns:UI =htt​​p://java.sun.com/jsf/facelets >     < CC:界面组件类型=testCC>         < CC:属性名=ajaxEventListener方法签名=无效监听器(javax.faces.event.AjaxBehaviorEvent)/>     < / CC:接口>     < CC:实施>         < H:的commandButton值=提交>             < F:AJAX监听=#{cc.ajaxEventListener}/>         < / H:的commandButton>     < / CC:实施> < / UI:成分>

 包com.example;

进口javax.el.MethodEx pression;
进口javax.faces.component.FacesComponent;
进口javax.faces.component.UINamingContainer;
进口javax.faces.context.FacesContext;
进口javax.faces.event.AjaxBehaviorEvent;

@FacesComponent(值=testCC)
公共类TestCC扩展UINamingContainer {

    公共无效ajaxEventListener(AjaxBehaviorEvent事件){
        FacesContext的上下文= FacesContext.getCurrentInstance();
        MethodEx pression ajaxEventListener =(MethodEx pression)的getAttributes()获得(ajaxEventListener)。
        ajaxEventListener.invoke(context.getELContext(),新的对象[] {事件});
    }

}
 

无论如何,我相信,依托组件把车门打开新的方式来达到你所想到的功能需求呢;)

I have a JSF 2 composite component that employs some Ajax behavior. I want to add a listener method to the <f:ajax> tag inside my composite component, but the listener method should be provided as a <composite:attribute> in the <composite:interface>.

The <f:ajax> tag inside my composite component is currently hard-coded to a listener like this:

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

The listener method on the bean has this signature:

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

I want the composite component to be something like this so the page can supply its own event method, but I can't figure out the correct syntax for the interface.

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

How can I do this?

UPDATED WITH SOLUTION:

I took the approach suggested by BalusC and it works great. The relevant snippets are:

The interface declaration in the composite component

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

The Ajax tag used in my composite component

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

The place in my page where I use the composite component

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

And the method on my backing bean

public void updatedEventListenerXYZ() {
    // do something here...
}

解决方案

If you can get rid of the AjaxBehaviorEvent argument,

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

then you can use

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

If the argument is mandatory (for logging?), then you need to re-specify the attribute as follows

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

However, this does here not work as expected with

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

on GF 3.1 + Mojarra 2.1.1:

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

I'm not sure if this is a bug or not. For that I'd need to invest some more time to naildown it. However, it was workaroundable by creating a backing component which gets the MethodExpression from the attributes and invokes with the right number of arguments. Here's a complete kickoff example:

<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>

with

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 });
    }

}

Regardless, I believe that the backing component puts doors open for new ways to achieve the functional requirement you have had in mind anyway ;)

这篇关于JSF 2 - 我如何添加一个Ajax侦听器方法复合分量接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆