Jakarta EE 10 - Jakarta Faces 4.0 変更内容まとめ

blog1.mammb.com


拡張子なしの自動マッピング

拡張子 .xhtml なしのリクエストに対して、 .xhtml が付いたものとして扱うことができるようになります。

これを有効化するには、ServletContext の初期化パラメータで jakarta.faces.AUTOMATIC_EXTENSIONLESS_MAPPING を有効化(true)する必要があります。


@ClientWindowScoped アノテーションの追加

@jakarta.faces.lifecycle.ClientWindowScoped アノテーションが追加されました。

@ViewScoped より長く、@SessionScoped より短いライフサイクルのスコープで、ウインドウ(タブ)別のスコープ管理が可能となります。

既に周辺ライブラリで実現可能ではありますが、Jakarta Faces でネイティブサポートされます。 実装は CDI Extension として提供されることになります。


JSF から Faces への変更

コード上の JSF という名称が、Jakarta Faces という仕様名に合わせて、Faces に置き換えられました。

メソッドやクラス名に含まれる JSF は全て Faces に変更されています。

また、jsf.js という JavaScript ファイルは faces.js に変更されていますし、jsf/FlashSecretKey という JNDI名 は faces/FlashSecretKey に変更されています。

パススルー・エレメントの xmlns:jsfxmlns:faces に変更されているため注意してください。


XML ネームスペースの変更

ネームスペースは URL ではなく URN を使用するようになりました。

以前は以下のように URL 指定していました。

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:jsf="http://xmlns.jcp.org/jsf"
      ...
>

以下の記載に変更されました。

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:faces="jakarta.faces"
    xmlns:ui="jakarta.faces.facelets"
    xmlns:f="jakarta.faces.core"
    xmlns:h="jakarta.faces.html"
    xmlns:pt="jakarta.faces.passthrough"
    xmlns:cc="jakarta.faces.composite"
    xmlns:my="jakarta.faces.component"
>

コンポジットコンポーネントでフォルダを掘る場合は xmlns:cc="jakarta.faces.composite/components" のように指定します。

JSP タグについても以下に変更となります。

  • http://xmlns.jcp.org/jsp/jstl/core から jakarta.tags.core
  • http://xmlns.jcp.org/jsp/jstl/functions から jakarta.tags.functions


Java で Facelet を作成するためのAPI追加

XML ではなく、Java で Facelet を定義するための機能です。 このために各種のAPIが追加されたというよりは、@View アノテーションの追加と、FaceletFactory から viewId を指定して Facelet を取得できるようにする変更で、その他は既存のインフラストラクチャを利用したものです。

以下のように Facelet を構築できるようになります。

@View("/hello.xhtml")
@ApplicationScoped
public class Hello extends Facelet {

    @Override
    public void apply(FacesContext facesContext, UIComponent root) throws IOException {
        if (!facesContext.getAttributes().containsKey(IS_BUILDING_INITIAL_STATE)) {
            return;
        }

        ComponentBuilder components = new ComponentBuilder(facesContext);

        List<UIComponent> rootChildren = root.getChildren();

        UIOutput output = new UIOutput();
        output.setValue("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
        rootChildren.add(output);

        HtmlBody body = components.create(HtmlBody.COMPONENT_TYPE);
        rootChildren.add(body);

        HtmlForm form = components.create(HtmlForm.COMPONENT_TYPE);
        form.setId("form");
        body.getChildren().add(form);

        HtmlOutputText message = components.create(HtmlOutputText.COMPONENT_TYPE);
        message.setId("message");
        form.getChildren().add(message);

        HtmlCommandButton actionButton = components.create(HtmlCommandButton.COMPONENT_TYPE);
        actionButton.setId("button");
        actionButton.addActionListener(e -> message.setValue("Hello, World"));
        actionButton.setValue("Do action");
        form.getChildren().add(actionButton);

        output = new UIOutput();
        output.setValue("</html>");
        rootChildren.add(output);
    }

    private static class ComponentBuilder {
        FacesContext facesContext;
        ComponentBuilder(FacesContext facesContext) {
            this.facesContext = facesContext;
        }
       @SuppressWarnings("unchecked")
       <T> T create(String componentType) {
           return (T) facesContext.getApplication().createComponent(facesContext, componentType, null);
       }
    }

}


その他のAPIの変更

  • ExternalContext#addResponseCookie() のプロパティで SameSite 属性をサポート

    • Jakarta Servlet 6.0 での Cookie の変更に順ずる形で変更
  • UIComponent#getListenersForEventClass() が null を返さなくなった(空リストを返す)

    • UIComponent#subscribeToEvent() を使いやすくする意図
  • FacesContext#getLifecycle() が追加され Lifecycl を取得可能となった

  • UIViewRoot#getDoctype() が追加され Doctype を取得可能となった

    • jakarta.faces.component.Doctype インターフェースが新規追加された
  • 全ての @Qualifiers にアノテーションリテラルの実装が追加された

    • インラインでのアノテーションインスタンス取得用


タグとタグ属性の変更

  • <f:selectItemGroups> タグ、 <f:selectItemGroup> タグが新しく追加された

  • <h:inputFile> タグへ multiple 属性と accept 属性が追加された

  • <h:selectManyCheckbox><h:selectOneRadio> タグのレイアウト属性値に layout="list" が追加された

  • <f:websocket> タグに onerror 属性が追加された

  • <h:inputText> タグに type 属性が追加された

  • doctype が HTML5 の場合、<link> and <script> タグ出力時に、type 属性の書き込みがスキップされるようになった


廃止された仕様

  • JSP サポート削除

    • Jakarta Faces の VDL(View Description Language) として、JSP のサポートは、JSF 2.0で非推奨であった
    • Jakarta Faces 4.0 ではこの JSP のサポートが削除された
  • JSF ネイティブ Managed Beans 削除

    • 非推奨であった JSF 独自の Managed Beans が削除された
    • CDI への統一
  • JSF ネイティブ EL式サポート 削除

    • JSF で独自サポートしていたEL式のための仕様が削除された(MethodBinding, ValueBinding などが削除された)
    • Jakarta Expression Language への統一
  • UIComponent の文字列定数削除

    • CURRENT_COMPONENT CURRENT_COMPOSITE_COMPONENT 及び HONOR_CURRENT_COMPONENT_ATTRIBUTES_PARAM_NAME
    • UIComponent#getCurrentComponent()getCurrentCompositeComponent() を代わりに使用可能
  • jakarta.faces.application.StateManager 削除

    • 非推奨のメソッドを含む jakarta.faces.application.StateManager クラス削除
  • jakarta.faces.view.facelets.ResourceResolver 削除

    • ResourceHandler を代わりに使用可能