JSFのドキュメントによると<composite:interface>
:
複合コンポーネントのネスト
実装は、複合コンポーネントのネストをサポートする必要があります。具体的には、複合コンポーネントのセクションが別の複合コンポーネントの使用ページとして機能できる必要があります。複合コンポーネントが、、、または他の動作インターフェイスなどの動作インターフェイスを使用ページに公開する場合、ネストされた複合コンポーネントの場合、そのようなインターフェイスの公開を「伝播」できる必要があります。複合コンポーネントの作成者は、この公開を機能させるために、名前属性の値がネストのすべてのレベルで正確に一致することを確認する必要があります。ネストされた複合コンポーネントでの名前の「再マッピング」をサポートするために、実装は必要ありません。
ネスティングの例を示します<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>
フェイスレット:
<!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..." );
}
};
}
}
私はMojarra2.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
(外側の複合コンポーネント)をクリックしても何も起こりません。これが公式のJSFjavadocに示されている例とほぼ同じであることを考えると、これが機能することを期待しています。なぜそうではないのか分かりますか?
- - - - - 編集 - - - - -
このように外側の複合コンポーネントを変更すると、次のことがわかりました。
<!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を追加したことに注意してください
これで、アクションが適切にチェーンされます。これは理にかなっていますが、ドキュメントでは、これは不要であると信じています。これはドキュメントのエラーですか?または、実装で(Mojarra2.1.13とMyFaces2.1.10の両方で試しました)?または私の理解では?