当前位置: 首页 > 面试题库 >

JSF 2-如何向复合组件接口添加Ajax侦听器方法?

法兴德
2023-03-14
问题内容

我有一个采用某些Ajax行为的JSF
2复合组件。我想添加一个listener方法到<f:ajax>标签我复合组件内部,但listener方法应为提供<composite:attribute><composite:interface>

目前<f:ajax>,我的复合组件内部的标签已被硬编码为这样的侦听器:

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

Bean上的listener方法具有以下签名:

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

我希望复合组件是这样的,以便页面可以提供自己的事件方法,但是我无法弄清楚接口的正确语法。

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

我怎样才能做到这一点?

解决方案更新:

我采用了BalusC建议的方法,效果很好。相关的片段是:

复合组件中的接口声明

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

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

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

我的页面中使用复合组件的位置

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

还有我的后备豆上的方法

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

问题答案:

如果您 可以 摆脱AjaxBehaviorEvent争论,

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

那么你可以使用

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

如果参数是强制性的(用于日志记录?),则需要重新指定属性,如下所示

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

但是,这在这里无法正常工作

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

在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

我不确定这是否是错误。为此,我需要花费更多时间来确定它。但是,通过创建一个支持组件可以解决该问题MethodExpression,该组件从属性获取并使用正确数量的参数进行调用。这是一个完整的启动示例:

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

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

}

无论如何,我相信支持组件为实现您已经想到的功能要求的新方法打开了大门;)



 类似资料:
  • 我用JavaFx制作了两个简单的JMS应用程序(一个是发送者,另一个是接收者)。 但是,我不能用来自发送方的新消息刷新接收方的GUI。 我使用onMessage事件在internet上查找,并重写了它(向那里的ObservableList添加一个项),但它不起作用。引发事件后,没有向ObservableList添加任何元素。 这是我的听筒: 我的发件人:

  • 是否有办法将AWT侦听器添加到SWT组件? 我以前制作了一个主要在AWT和Swing组件中运行的应用程序。现在,我有热键功能,它依赖于一个定制的库,该库监听全局键事件并返回相应的AWT键代码。 当我改变整个应用程序并使用SWT组件时,我的问题就出现了。正如我们所知,一些键现在返回一个不同的键代码,这扰乱了整个热键功能。 我想到的最初解决方案是: A.使用javax。摆动jtextfield作为my

  • 我的代码使用jQuery。我有一个密码输入框,我想要得到输入的密码任何时候。 下面是我的代码: 我确信这是一个正确的代码,因为当我在浏览器的控制台中输入它时,它可以工作,但当我重新加载页面时,它就不工作了 我能做什么?

  • 我可以在下面的代码中为添加事件侦听器,但不能添加到。 是不是因为twitter做了一些事情不让我这么做?有办法绕过它吗?

  • 我已经创建了一个数组列表,当使用鼠标按下事件选择列表项时,必须为其添加一个侦听器,以便如何做到这一点。我为其创建了数组列表ia的代码,如下所示 现在我需要为它添加鼠标向下事件监听器。之前我编写了SWT的鼠标事件监听器,但现在必须更改。早期的SWT监听器如下所示 因此,请帮助我如何将侦听器添加到java.util.list的数组列表中

  • 问题内容: 我试图在控制器的initialize()方法中将TextArea的textProperty绑定到StringProperty。 值更改时,侦听器会监听这两个对象,以执行某些行为。 但是有些奇怪的事情发生了。 我建立了一个简单的模型来重现这种情况。 Main.java sample.fxml 我认为以上代码与该问题无关。但以防万一,我把它放在这里。 这是控制器。 Controller.j