JSF复合:嵌套复合组件中的actionSource

时间:2012-11-30 18:06:46

标签: java jsf-2 nested composite-component

根据<composite:interface>的{​​{3}}:

  

嵌套复合组件

     

实现必须支持复合组件的嵌套。   具体来说,它必须是可能的   复合组件的一部分,用作另一个组件的使用页面   复合材料。当复合组件暴露行为时   使用页面的界面,例如a,   , 或其他   行为界面,必须有可能“传播”暴露   在嵌套复合组件的情况下,这样的接口。该   复合组件作者必须确保名称的值   属性在嵌套的所有级别完全匹配以启用此功能   接触工作。实施不需要支持   “重新映射”嵌套复合组件中的名称。

它继续显示嵌套<composite:actionSource>的示例,但是,我一直在测试一个几乎完全相同的示例,但它不起作用。这是我的代码:

内部复合组件:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
  xmlns:composite="http://java.sun.com/jsf/composite">

<composite:interface>
  <composite:attribute name="actionText" 
    type="java.lang.String" default="nestedastest action" />
  <composite:actionSource name="someaction" />
</composite:interface>

<composite:implementation>
  <h:commandLink id="someaction">#{cc.attrs.actionText}</h:commandLink>
</composite:implementation>
</html>

外部复合材料组件:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
  xmlns:composite="http://java.sun.com/jsf/composite"
  xmlns:test="http://java.sun.com/jsf/composite/components/test">

<composite:interface name="nestedActionTester"
  displayName="A test composite component for nested actions">
  <composite:attribute name="actionText" 
    type="java.lang.String" default="astest action" />
  <composite:actionSource name="someaction" />
</composite:interface>

<composite:implementation>
  <test:nestedastest actionText="#{cc.attrs.actionText}" />
</composite:implementation>
</html>

的facelet:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
  xmlns:test="http://java.sun.com/jsf/composite/components/test">

<h:head />
<h:body>
  <ui:composition template="template.xhtml">
    <ui:define name="content">
      <h:form id="communityMembersForm">
        <div>
          <test:astest>
            <f:actionListener for="someaction"
              binding="#{testController.someActionActionListener}" />
          </test:astest>
        </div>
        <div>
          <test:nestedastest>
            <f:actionListener for="someaction"
              binding="#{testController.someActionActionListener}" />
          </test:nestedastest>
        </div>
      </h:form>
    </ui:define>
  </ui:composition>
</h:body>
</html>

托管Bean:

package test.controller;


import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


@ManagedBean
@ViewScoped
public class TestController {
    private static Logger logger = 
            LoggerFactory.getLogger( TestController.class );

    public ActionListener getSomeActionActionListener() {
        return new ActionListener() {
            @Override
            public void processAction( ActionEvent event ) 
                    throws AbortProcessingException {
                logger.debug( "someaction occurred..." );
            }

        };
    }
}

我正在使用Mojarra 2.1.13:

<dependency>
  <groupId>com.sun.faces</groupId>
  <artifactId>jsf-api</artifactId>
  <version>2.1.13</version>
  <type>jar</type>
  <scope>compile</scope>
</dependency>
<dependency>
  <groupId>com.sun.faces</groupId>
  <artifactId>jsf-impl</artifactId>
  <version>2.1.13</version>
  <type>jar</type>
  <scope>runtime</scope>
</dependency>

在tomcat 6.0.32上:

<dependency>
  <groupId>org.apache.tomcat</groupId>
  <artifactId>el-api</artifactId>
  <version>6.0.32</version>
  <type>jar</type>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>org.apache.tomcat</groupId>
  <artifactId>servlet-api</artifactId>
  <version>6.0.32</version>
  <type>jar</type>
  <scope>provided</scope>
</dependency>

当我运行此应用程序时,nestedastest action的链接(直接使用内部复合组件的链接)会导致操作侦听器运行并打印日志消息。但是,当单击astest action(外部复合组件)时,没有任何反应。鉴于这几乎就是官方JSF javadoc中显示的示例,我希望这可行。知道为什么不是吗?

----------编辑---------

我发现如果我这样修改外部复合组件:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
  xmlns:composite="http://java.sun.com/jsf/composite"
  xmlns:test="http://java.sun.com/jsf/composite/components/test">

<composite:interface name="nestedActionTester"
  displayName="A test composite component for nested actions">
  <composite:attribute name="actionText" 
    type="java.lang.String" default="astest action" />
  <composite:actionSource name="someaction" targets="inner" />
</composite:interface>

<composite:implementation>
  <test:nestedastest id="inner" actionText="#{cc.attrs.actionText}" />
</composite:implementation>
</html>

请注意,我为actionSource添加了一个targets属性,并为嵌套的复合组件添加了匹配的id

现在它将适当地链接行动。这确实有意义,但文档会让您相信这是不必要的。这是文档中的错误吗?或者在实现中(我在Mojarra 2.1.13和MyFaces 2.1.10上都试过了)?或者在我的理解中?

1 个答案:

答案 0 :(得分:0)

该算法默认尝试查找与每个嵌套级别中cc:actionSource名称定义的id相同的组件。在这种情况下,组件id仅在内层定义。如果您不想为每个组件一直使用相同的id,可以使用“targets”属性来指示组件正在讨论的算法,并通过所有级别传递actionListener。