5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Jakarta EE の移植性を支える Technology Compatibility Kit (TCK) のソースコードを覗いてみる

5
Last updated at Posted at 2025-12-10

この記事は, Jakarta EE / Java EE Advent Calendar 2025 の 11 日目の記事です.

先日,Jakarta EE 仕様の最新版である Jakarta EE 11 がリリースされました.
Jakarta EE 11 リリースのアナウンス “The Eclipse Foundation’s Jakarta EE Working Group Announces Jakarta EE 11 Release” では,Jakarta EE 11 の主要な変更点として次の点が挙げられています.

  • Jakarta Data (new specification)
  • Streamlined Specifications
  • Modernised TCK Framework

このうち 3 点目で言及されている “TCK” は,Jakarta EE アプリケーションの開発者が意識することは普段ありませんが,Jakarta EE アプリケーションの移植性を支えている重要な技術です.
本記事では,TCK とは何かをおさらいしつつ,Jakarta EE 11 で刷新された最新の TCK のソースコードを覗いてみたいと思います.

Jakarta EE の WORA と TCK

“Write Once, Run Anywhere” (WORA) は, Java が掲げるクロスプラットフォームの理念を表すフレーズです.
一度 Java プログラムを書けば,動作環境 (ハードウェアや OS) に左右されずにそのプログラムを実行できるという考え方は,多くの人に支持され,Java の普及に貢献しました.

この考え方は,Java SE だけのものではなく,Java EE および Jakarta EE にも共通しています.
Jakarta EE における “Write Once, Run Anywhere” は,一度 Jakarta EE アプリケーションを書けば,その動作環境である Jakarta EE 実装 (アプリケーションサーバー) に左右されずにそのアプリケーションを実行できるということを意味します.

そして,この “Write Once, Run Anywhere” を実現するために TCK が重要な役割を果たしています.

Technology Compatibility Kit (TCK) とは,実装が Jakarta EE などの仕様に準拠していることを確認するために使われるテストスイートです.
Jakarta EE の仕様は,Jakarta EE の TCK と一緒に提供されます.
Java EE の時代には,TCK のことは Compatibility Test Suite (CTS) とも呼ばれていました.

TCK and Compatible Implementations

Jakarta EE TCK Process では, TCK の役割は次のように説明されています.

It is the role of the TCK to ensure both compatability of implementations and portability of applications.

(日本語訳: 実装の互換性とアプリケーションの移植性の両方を確保することが,TCK の役割です.)

Jakarta EE 仕様の互換実装は,仕様との互換性を確認するために,必ずその仕様の TCK テストに合格して互換認証を受けています (TCK テストに合格しなければ互換実装を名乗ることができません).
これによって,少なくとも TCK によって確認された範囲では,どの互換実装を使っても仕様通りに Jakarta EE アプリケーションを実行できます.
この仕組みのおかげで,Jakarta EE 実装に左右されずに Jakarta EE アプリケーションを実行できるという,Jakarta EE 実装間のアプリケーションの移植性が担保されているというわけです.

Jakarta EE TCK の構成

Jakarta EE の TCK には,Jakarta EE Platform,Jakarta EE Web Profile のような Platform/Profile の互換性をテストする TCK と,Jakarta Servlet,Jakarta Enterprise Beans のようなコンポーネント仕様の互換性をテストする TCK があります.

Jakarta EE Platform の TCK は,Jakarta EE Platform の各バージョンのページ (Jakarta EE Platform 11 のページ など) の “Jakarta EE Platform version TCK” のリンクで提供されています.
また,Jakarta EE Platform の TCK のソースコードは,GitHub の jakartaee/platform-tck リポジトリ で公開されています.

Jakarta Servlet や Jakarta Enterprise Beans などの個別の仕様にも,それぞれ TCK があります.
例えば Jakarta Servlet の場合,TCK は Jakarta Servlet の各バージョンのページ (Jakarta Servlet 6.1 のページ など) の “Jakarta Servlet version TCK” のリンクで提供されています.
また, Jakarta Servlet の TCK のソースコードは,GitHub の jakartaee/servlet リポジトリ の中に見つけることができます.

なお,Platform/Profle のTCK には,それらを構成するコンポーネント仕様の TCK が一部含まれていますが,Platform/Profile の TCK の実行だけでは十分でなく,追加でコンポーネント仕様 TCK の実行が必要となる場合があります.
例えば Platform TCK の場合,Jakarta Enterprise Beans は Platform TCK に含まれるため別途 Jakarta Enterprise Beans の TCK を実行する必要がありませんが,Jakarta Batch は Platform TCK に含まれないため別途 Jakarta Batch の TCK を実行する必要があります.
具体的にどの TCK を実行する必要があるかは,Platform/Profile TCK のユーザーガイドに記載されています.

Jakarta EE 各実装の実際の TCK 実行結果は, Certification Results のページ から見ることができます.

次の表は,Jakarta EE Platform 11 向けの Eclipse GlassFish 8.0.0-M12 の TCK 実行結果 からまとめた TCK のテスト件数です.
この表からわかるように,実装の仕様との互換性を確認するために,かなりの数のテストが実行されていることがわかります.

TCK 種別 件数
Jakarta EE Platform TCK 27,613
Jakarta Activation TCK 91
Jakarta Authentication TCK 130
Jakarta Authorization TCK 53
Jakarta Batch TCK 384
Jakarta Contexts and Dependency Injection TCK 1,335
Jakarta Concurrency TCK 295
Jakarta Data TCK 99
Jakarta Dependency Injection TCK 50
Jakarta Debugging Support for Other Languages TCK 3
Jakarta Faces TCK 5,705
Jakarta JSON Binding TCK 295
Jakarta JSON Processing TCK 197
Jakarta Mail TCK 56
Jakarta Pages TCK 682
Jakarta REST TCK 2,796
Jakarta Security TCK 216
Jakarta Servlet TCK 1,716
Jakarta Validation TCK 1,049
Jakarta WebSocket TCK 737
合計 43,502

Jakarta EE TCK で使われる技術

Jakarta EE 10 までは,TCK の大部分は次のような技術を利用して実装されていました.

JavaTest Harness は,Sun Microsystems 社によって開発され JDK 開発でも使われてきた歴史のあるフレームワークですが,現在 Java コミュニティにおいて JUnit のようなフレームワークほど広く使われなくなっており,JavaTest Harness ベースの Jakarta EE TCK をレガシーな遺産とみなす人もいました.

そこで,Jakarta EE 11 では TCK の構造に大きく手が入り,次のような技術を利用するようになりました.

これにより,JUnit のようにコミュニティで現在広く使われているフレームワークに刷新され,これらのフレームワークの最新技術を利用できるようになりました.
また,これらのフレームワークに馴染みのある開発者が Jakarta EE TCK の開発に参加しやすくなりました.

なお,部分的に例外があって,Jakarta EE 11 の TCK の一部でこれらの技術を利用していないものもあります.
例えば CDI TCK は JUnit でなく TestNG ベースだったり,今後積極的にエンハンスされないコンポーネントの TCK は JavaTest Harness ベースのままだったりします.

Jakarta EE TCK のソースコードを覗いてみる

それでは,Jakarta EE の TCK のソースコードを読んでみて,Jakarta EE の仕様の検証が TCK でどのように実装されているかを確認してみたいと思います.
Jakarta EE 10 から Jakarta EE 11 にかけて TCK の使用技術が変更されたということで,Jakarta EE 10 と Jakarta EE 11 の両方の TCK のソースコードを見てみます.

ここでは例として,Jakarta Servlet 仕様の以下の一節のテストがどのように TCK で実装されているかを追ってみることにします.

Jakarta Servlet Specification 6.1 の “5.2. Headers” より:

To be successfully transmitted back to the client, headers (not trailer) must be set before the response is committed. Headers (not trailer) set after the response is committed will be ignored by the servlet container.

(日本語訳: クライアントに正常に返送するには,レスポンスがコミットされる前にヘッダー (トレーラーではない) を設定する必要があります.レスポンスがコミットされた後に設定されたヘッダー (トレーラーではない) は,Servlet コンテナによって無視されます.)

Jakarta EE 10 の TCK のソースコード

Jakarta EE 10 の TCK のうち,Jakarta Servlet 6.0 の TCK は,Jakarta Servlet 6.0 のページ にあります.
TCK のソースコードも TCK バンドルに含まれています.

この頃の TCK は Ant ベースとなっていて,次のコードで com.sun.javatest.tool.Main が呼ばれていることからもわかるように,テストフレームワークとして JavaTest Haness が使われています.
(ソース: https://github.com/jakartaee/platform-tck/blob/10.0.0.Final/bin/xml/ts.top.import.xml)

    <presetdef name="javatest">

        <!-- 
          The javatest task is a presetdef that sets many of the common 
          attributes and elements used by both the GUI and batch mode 
          invocations of javatest with the spider workspace.  To see the preset 
          values, refer to the included XML below that shows the content of
          the javatest presetdef.
        -->

        <java classname="com.sun.javatest.tool.Main" 
              failonerror="${failOnError}" fork="yes" >

TCK 実行時に Jakarta EE 実装 (アプリケーションサーバー) に配備される Servlet アプリケーションのコードは次の通りです.
(ソース: https://github.com/jakartaee/platform-tck/blob/10.0.0.Final/src/com/sun/ts/tests/servlet/spec/httpservletresponse/HttpTestServlet.java)

public class HttpTestServlet extends HttpTCKServlet {

  public void intHeaderTest(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException {
    response.addIntHeader("header1", 12345);
    response.flushBuffer();
    response.addIntHeader("header2", 56789);
  }

この Servlet アプリケーションをビルドする処理も,次のように Ant で書かれています.
(ソース: https://github.com/jakartaee/platform-tck/blob/10.0.0.Final/src/com/sun/ts/tests/servlet/spec/httpservletresponse/build.xml)

  <property name="app.name"  value="servlet_spec_httpservletresponse" />
  <property name="web.war.classes"
            value="com/sun/ts/tests/servlet/common/servlets/HttpTCKServlet.class,
                   com/sun/ts/tests/servlet/common/util/ServletTestUtil.class,
                   com/sun/ts/tests/servlet/common/util/Data.class"/>
  <target name="package">
    <ts.war archivename="${app.name}" descriptor="${app.name}_web.xml">
      <zipfileset dir="${class.dir}"
                  prefix="WEB-INF/classes"
                  includes="${web.war.classes}"/>
    </ts.war>
    <ts.ear archivename="${app.name}"/>
  </target>

また,こうしたアプリケーションの配備処理をはじめとする Jakarta EE 実装 (アプリケーションサーバー) の運用操作も,Ant によって実現されます.

JavaTest Harness 上で実行されるテストケースは,次のように実装されています.
(ソース: https://github.com/jakartaee/platform-tck/blob/10.0.0.Final/src/com/sun/ts/tests/servlet/spec/httpservletresponse/URLClient.java)

  /*
   * @testName: intHeaderTest
   *
   * @assertion_ids: Servlet:SPEC:33;
   *
   * @test_Strategy: 1. Call setIntHeader to set header; 2. Commit it and set
   * the header again; 3. Verify that only the first header value is set, the
   * second set is ignored
   */

  public void intHeaderTest() throws Fault {
    TEST_PROPS.setProperty(EXPECTED_HEADERS, "header1: 12345");
    TEST_PROPS.setProperty(UNEXPECTED_HEADERS, "header2: 56789");
    TEST_PROPS.setProperty(REQUEST, "GET " + getContextRoot() + "/"
        + getServletName() + "?testname=" + "intHeaderTest" + " HTTP/1.1");
    invoke();
  }

このテストケースで,Servlet の仕様文書の記載事項が検証されています.
Servlet アプリケーションへのリクエストを発行する処理と,期待するレスポンスが実際に得られること (ここでは,ヘッダフィールド header1: 12345 が含まれ header2: 56789 が含まれないこと) を確認する処理が, invoke() 内に実装されています.
もし期待と異なる結果が得られた場合には,例外が投げられてテストが失敗するつくりとなっています.

Jakarta EE 11 の TCK のソースコード

次に,Jakarta EE 11 の TCK のソースコードを見てみます.

Jakarta EE 11 の TCK のうち,Jakarta Servlet 6.1 の TCK は,Jakarta Servlet 6.1 のページ にあります.
TCK のソースコードは,GitHub の jakartaee/servlet リポジトリ にあります.

TCK は Maven ベースとなっていて,次のコードの dependency 要素からも見て取れるように,JUnit と Arquillian が使われています.
(ソース https://github.com/jakartaee/servlet/blob/6.1.0-RELEASE-tck/tck/tck-runtime/pom.xml)

        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.junit5</groupId>
            <artifactId>arquillian-junit5-container</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jboss.arquillian.junit</groupId>
            <artifactId>arquillian-junit-core</artifactId>
        </dependency>

TCK 実行時に Jakarta EE 実装 (アプリケーションサーバー) に配備される Servlet アプリケーションのコードは次の通りです.
(ソース: https://github.com/jakartaee/servlet/blob/6.1.0-RELEASE-tck/tck/tck-runtime/src/main/java/servlet/tck/spec/httpservletresponse/HttpTestServlet.java)

public class HttpTestServlet extends HttpTCKServlet {

  public void intHeaderTest(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, IOException {
    response.addIntHeader("header1", 12345);
    response.flushBuffer();
    response.addIntHeader("header2", 56789);
  }

この Servlet アプリケーションをビルドする処理には,従来は Ant が使われていましたが,現在は次のように Arquillian/ShrinkWrap が使われるようになっています.
(ソース: https://github.com/jakartaee/servlet/blob/6.1.0-RELEASE-tck/tck/tck-runtime/src/main/java/servlet/tck/spec/httpservletresponse/HttpServletResponseTests.java)

  @Deployment(testable = false)
  public static WebArchive getTestArchive() throws Exception {
    return ShrinkWrap.create(WebArchive.class, "servlet_spec_httpservletresponse_web.war")
            .addAsLibraries(CommonServlets.getCommonServletsArchive())
            .addClasses(HttpTestServlet.class, RedirectedTestServlet.class)
            .setWebXML(HttpServletResponseTests.class.getResource("servlet_spec_httpservletresponse_web.xml"));
  }

また,こうしたアプリケーションの配備処理をはじめとする Jakarta EE 実装 (アプリケーションサーバー) の運用操作も,Arquillian (のコンテナアダプタ) によって実現されます.

JUnit 上で実行されるテストケースは,次のように実装されています.
(ソース: https://github.com/jakartaee/servlet/blob/6.1.0-RELEASE-tck/tck/tck-runtime/src/main/java/servlet/tck/spec/httpservletresponse/HttpServletResponseTests.java)

  /*
   * @testName: intHeaderTest
   *
   * @assertion_ids: Servlet:SPEC:33;
   *
   * @test_Strategy: 1. Call setIntHeader to set header; 2. Commit it and set
   * the header again; 3. Verify that only the first header value is set, the
   * second set is ignored
   */
  @Test
  public void intHeaderTest() throws Exception {
    TEST_PROPS.get().setProperty(EXPECTED_HEADERS, "header1: 12345");
    TEST_PROPS.get().setProperty(UNEXPECTED_HEADERS, "header2: 56789");
    TEST_PROPS.get().setProperty(REQUEST, "GET " + getContextRoot() + "/"
        + getServletName() + "?testname=" + "intHeaderTest" + " HTTP/1.1");
    invoke();
  }

この部分のコードの見た目は JavaTest Harness のときとそれほど変わっていませんが,従来なかった @Test (@org.junit.jupiter.api.Test) アノテーションが使われていることはわかるかと思います.
実際,JavaTest Harness の代わりに JUnit フレームワークでこのテストケースが実行されるようになっています.

ということで,Maven,JUnit,Arquillian といった技術を利用して Jakarta EE 11 の TCK が作られていることが確認できました.

まとめ

この記事では,Jakarta EE において “Write Once, Run Anywhere” のために TCK が重要な役割を果たしていることを確認しました.
また,Jakarta EE 11 で刷新された TCK のソースコードを覗いてみることで,Jakarta EE 仕様の検証が JUnit などの技術を利用して TCK として実装されていることを確認しました.

そういえば余談ですが,先日 JJUG CCC 2025 Fall の Jakarta EE BoF に参加したとき,Jakarta EE アプリケーションのテストってどうすればいいんだっけという話が出てきました.
一口にテストといってもいろいろあるので,どの方法を使えばいいと一概に言えるものではないですが,たとえばインテグレーションテストでは,TCK でも現役で使われている JUnit や Arquillian といった技術を一つの選択肢として考えてみるのはよいかもしれないと思いました.

Jakarta EE 11 で TCK がモダナイズされたことで,TCK も Jakarta EE 自身も,若返って息を吹き返したような気がしています.
これからも,TCK を活用することで Jakarta EE アプリケーションの移植性を確保し,安心して Jakarat EE を利用できる環境を作っていけたらと思います.

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?