JakartaEE(JavaEE)

JavaEEのプロジェクトを作成しThymeleafを使って画面表示してみた

JavaEEでは、JSF(JavaServer Faces)というJavaベースのWebアプリケーションフレームワークを用いて画面表示を行うことが多いが、JSFの代わりにThymeleafというテンプレートエンジンを用いることもできる。

今回は、JavaEEのプロジェクトを作成し、Thymeleafによる画面表示を行ってみたので、その手順やサンプルプログラムを共有する。

前提条件

下記記事の環境構築が完了していること。

Eclipse上にJavaEEの開発環境を構築してみたJavaEEとは、正式名称を「Java Platform, Enterprise Edition」といい、企業向けのWebアプリケーショ...



やってみたこと

  1. 動的Webプロジェクトの作成
  2. JavaEEのプロジェクトで必要なライブラリの配置
  3. サンプルプログラムの作成
  4. サンプルプログラムの実行

動的Webプロジェクトの作成

JavaEEのプロジェクトの作成は、動的Webプロジェクトを作成後、必要なライブラリを追加することによって行う。その手順は以下の通り。

1) パッケージ・エクスプローラー上で右クリックし、「新規」メニューから「その他」を選択する。
動的Webプロジェクトの作成_1

2) Webメニューの「動的Webプロジェクト」を選択し、「次へ」ボタンを押下する。
動的Webプロジェクトの作成_2

3) プロジェクト名を入力し、ターゲット・ランタイムにGlassFishを選択した状態で、「次へ」ボタンを押下する。
動的Webプロジェクトの作成_3

4) そのまま、「次へ」ボタンを押下する。
動的Webプロジェクトの作成_4

5) 「web.xml デプロイメント記述子の生成」にチェックを入れ、「完了」ボタンを押下する。
動的Webプロジェクトの作成_5

6) 作成されたdemoプロジェクトの構成は、以下の通り。
動的Webプロジェクトの作成_6



JavaEEのプロジェクトで必要なライブラリの配置

作成した動的Webプロジェクトを、JavaEEプロジェクトとして動作させるには、以下のjarファイルが必要である。

  • disruptor-3.3.2.jar
  • javax.mvc-api-1.0-edr2.jar
  • log4j-api-2.4.jar
  • log4j-core-2.4.jar
  • log4j-slf4j-impl-2.4.jar
  • ognl-3.1.jar
  • ozark-1.0.0-m02.jar
  • ozark-thymeleaf-1.0.0-m02.jar
  • slf4j-api-1.7.12.jar
  • thymeleaf-2.1.4.RELEASE.jar
  • unbescape-1.1.0.RELEASE.jar

例えば、「distruptor-3.3.2.jar」は、以下のURLの「jar」リンクを押下することで取得できる。
https://mvnrepository.com/artifact/com.lmax/disruptor/3.3.2

JavaEEのプロジェクトで必要なライブラリの配置_1

また、取得したライブラリは全て、以下のように、WebContent/WEB-INF/lib下にコピーして貼り付ける。
JavaEEのプロジェクトで必要なライブラリの配置_2



サンプルプログラムの作成

作成したサンプルプログラムの構成は以下の通り。
サンプルプログラムの構成
なお、上記の赤枠は、今回追加・変更したプログラムである。

アプリケーション定義クラスの内容は以下の通りで、アプリケーションのルートパスを指定している。

package demo;

import javax.ws.rs.ApplicationPath;

/**
 * JAX-RSアプリケーションのルートパスを@ApplicationPathアノテーションで
 * 指定するためのクラス
 * なお、JAX-RSとは、JavaEEでREST(HTTPをベースとしたアーキテクチャスタイル)に
 * 準拠したWebサービスを作るための機能のことをいう
 */
@ApplicationPath("/app")
public class DemoApplication extends javax.ws.rs.core.Application {

}

また、コントローラクラスの内容は以下の通りで、indexメソッドでメッセージを設定し、初期表示画面に遷移するようになっている。

package demo;

import javax.inject.Inject;
import javax.mvc.Models;
import javax.mvc.annotation.Controller;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

/**
 * コントローラクラス
 */
@Path("/demo")
@Controller
public class DemoController {

    /**
     * Modelオブジェクト
     */
    @Inject
    Models models;

    /**
     * メッセージを設定し、初期表示画面に遷移する
     *
     * @return 初期表示画面
     */
    @GET
    @Path("/index")
    @Produces(MediaType.TEXT_HTML)
    public String index() {
        models.put("message", "これはテストです");
        return "index";
    }
}

さらに、Thymeleafをテンプレートエンジンに設定するクラスの内容は以下の通り。

package demo;

import java.io.IOException;

import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.mvc.engine.ViewEngineContext;
import javax.mvc.engine.ViewEngineException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.glassfish.ozark.engine.ViewEngineBase;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

/**
 * Thymeleafをテンプレートエンジンに利用するためのクラス
 */
@ApplicationScoped
public class ThymeleafViewEngine extends ViewEngineBase {

    /**
     * サーブレットコンテキスト
     */
    @Inject
    private ServletContext servletContext;

    /**
     * テンプレートエンジン
     */
    private TemplateEngine engine;

    /**
     * 指定したビュー名をサポートしているか判定
     * @param view ビュー名
     */
    public boolean supports(String view) {
        return !view.contains(".");
    }

    /**
     * オブジェクト生成後に行う処理
     */
    @PostConstruct
    public void postConstruct() {
        // ViewにThymeleafを使用することを指定する
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();

        resolver.setSuffix(".html"); // Viewファイルの拡張子
        resolver.setPrefix("/WEB-INF/templates/"); // Viewファイルの配置場所
        resolver.setTemplateMode("HTML5"); // Viewファイルのモード
        resolver.setCacheable(false); // Viewファイルをキャッシュするか
        resolver.setCharacterEncoding("UTF-8"); // Viewファイルの文字コード
                                                // (これを指定しないと日本語が文字化けする)

        // Viewのテンプレートエンジンに先ほどの設定内容を反映する
        engine = new TemplateEngine();
        engine.setTemplateResolver(resolver);
    }

    /**
     * 指定したビュー名に対応する画面を表示
     * @param ViewEngineContext ビューエンジンのコンテキスト
     */
    public void processView(ViewEngineContext context) throws ViewEngineException {
        try {
            HttpServletRequest request = context.getRequest();
            HttpServletResponse response = context.getResponse();
            WebContext ctx 
               = new WebContext(request, response, servletContext, request.getLocale());

            ctx.setVariables(context.getModels());
            request.setAttribute("view", context.getView());

            // 指定したビュー(HTMLファイル)名に対応するHTMLを解析し画面に表示する
            engine.process(context.getView(), ctx, response.getWriter());

         } catch (IOException e) {
             throw new ViewEngineException(e);
         }
     }
}

また、初期表示画面の内容は以下の通りで、Spring Bootのときと同じような内容を記載している。

<!DOCTYPE html>
<html lang="ja" xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8" />
	<title>初期表示画面</title>
</head>
<body>
	初期表示画面に遷移しました。<br/><br/>
	設定されたメッセージ: <span th:text="${message}">メッセージ</span>
</body>
</html>

さらに、beans.xmlの内容は以下の通りで、「bean-discovery-mode=”all”」の設定を追加している。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
	bean-discovery-mode="all">
	<!-- bean-discovery-mode="all"で、全てのクラスをCDIでインジェクションさせる対象としている -->
	<!-- なお、CDIとは、Java EEでDI(依存性の注入)やインスタンスのスコープの管理を行う機能のことをいう -->
</beans>

その他、動的Webプロジェクトを作成時と同じ内容であるが、glassfish-web.xml、web.xmlの内容はそれぞれ以下の通り。

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app>
    <context-root>/demo</context-root>
</glassfish-web-app>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         id="WebApp_ID"
         version="3.1">

  <!-- Webアプリケーションの表示名 -->
  <display-name>demo</display-name>

  <!-- URLがスラッシュ(/)で終わっていた場合に表示させるファイル名 -->
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>



サンプルプログラムの実行

サンプルプログラムの実行結果は、以下の通り。

1) demoプロジェクトをサーバーに追加するために、サーバービューのGlassFishサーバーを選択し右クリックし、「追加および除去」を選択する。
サンプルプログラムの実行結果_1

2) demoプロジェクトを選択した状態で「追加」ボタンを押下する。
サンプルプログラムの実行結果_2

3) 「構成済み」欄にdemoプロジェクトが移動するので、「完了」ボタンを押下する。
サンプルプログラムの実行結果_3

4) 以下のように、GlassFishサーバーにdemoプロジェクトが追加されていることが確認できる。
サンプルプログラムの実行結果_4

5) GlassFishサーバーを選択し右クリックし、「開始」を選択する。
サンプルプログラムの実行結果_5

6) GlassFishサーバーが起動すると、以下のように、サーバーのステータスが「始動済み、同期済み」に変更される。
サンプルプログラムの実行結果_6

7) Webブラウザ上で「http:// (ホスト名):(ポート番号)/(Webアプリケーションの表示名)/(アプリケーションのルートパス)/(コントローラクラスパス)/(コントローラメソッドパス)」とアクセスすると、下記画面(index.html)が表示されることが確認できる。
サンプルプログラムの実行結果_7
なお、(Webアプリケーションの表示名)はweb.xmlで、(アプリケーションのルートパス)はDemoApplication.javaで、それぞれ指定している。

要点まとめ

  • JavaEEのプロジェクトの作成は、動的Webプロジェクトを作成後、必要なライブラリを追加することによって行う。
  • アプリケーションのルートパスは、「javax.ws.rs.core.Application」クラスのサブクラスで定義する。
  • コントローラクラスで、画面遷移に必要なパス指定等を行う。
  • Thymeleafをテンプレートエンジンに利用する定義は、ViewEngineBaseクラスのサブクラスで行う。
  • 全てのクラスをCDIでインジェクションさせる対象とするには、beans.xmlで「bean-discovery-mode=”all”」を指定する。