---
title: ついにMVCがJakarta EEに。その歴史・機能・アーキテクチャを知ろう
tags:  #jakartaee  
author: [tada](https://image.docswell.com/user/MasatoshiTada)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/PEXQLMP4JX.jpg?width=480
description: 日本 Jakarta EE &amp; MicroProfile ユーザーグループのイベントでの資料です。
published: June 21, 26
canonical: https://image.docswell.com/s/MasatoshiTada/53J7RY-jakarta-mvc
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/PEXQLMP4JX.jpg)

ついにMVCがJakarta EEに。
その歴史・機能・アーキテクチャを知ろ
う
Jakarta EE &amp; Microprofileセミナー
2026年6月22日
多田真敏
1


# Page. 2

![Page Image](https://bcdn.docswell.com/page/3EK9LGDPED.jpg)

このセッションについて
◆Jakarta MVCは、今までJakarta EEに無かった
「アクションベース」のWebフレームワークです。
◆実はJakarta MVCの原型は、2015年にJava EE 8の計画が
始まったころから存在しました。そこから10年以上経ち、
今回ようやくJakarta EEに正式に含まれました。
◆このセッションでは、その歴史的背景から、Jakarta MVCの
基本的機能、JAX-RSベースのアーキテクチャまでお話します。
2


# Page. 3

![Page Image](https://bcdn.docswell.com/page/L73W3NR475.jpg)

前提知識
◆本セッションは以下の知識・経験があることを前提とします
◆Jakarta REST （旧JAX-RS）
3


# Page. 4

![Page Image](https://bcdn.docswell.com/page/87DK4WY5JG.jpg)

自己紹介
◆多田真敏（@suke_masa）
◆JJUG・JSUGスタッフ
◆クレジットカード会社で
社内システムの内製化＋AWS化
◆OSSドキュメントの和訳
◆Thymeleaf・Resilience4j
◆櫻坂46、北海道日本ハムファイターズ、
DB.スターマン、ゴジラ、英語学習
4


# Page. 5

![Page Image](https://bcdn.docswell.com/page/VJPKM96DE8.jpg)

多田とJava EE
◆前職・前々職ではJava研修講師
理由は後ほど説明
◆前々職で2014年からJava EE 7の研修を担当
◆前職でもJava EE 7の研修を担当（2017年くらいまで）
◆2016年くらいからSpringの研修も担当
◆現職の開発ではSpring＋AWSが中心
5


# Page. 6

![Page Image](https://bcdn.docswell.com/page/2EVV9M3GEQ.jpg)

[宣伝] 頑張って書いたので買ってください
ハッシュタグ
#つくまなBoot
書きました！
6


# Page. 7

![Page Image](https://bcdn.docswell.com/page/57GLZGYDEL.jpg)

環境
◆Wildfly 40.0.0.Final
◆Jakarta MVC 3.0
◆Thymeleaf 3.1
◆JDK 25
7


# Page. 8

![Page Image](https://bcdn.docswell.com/page/4EQYLXMXJP.jpg)

もくじ
① Jakarta MVC導入の背景
② Jakarta MVCの機能
③ Jakarta MVCのアーキテクチャ
8


# Page. 9

![Page Image](https://bcdn.docswell.com/page/KJ4WD6V271.jpg)

もくじ
① Jakarta MVC導入の背景
② Jakarta MVCの機能
③ Jakarta MVCのアーキテクチャ
9


# Page. 10

![Page Image](https://bcdn.docswell.com/page/LE1YZV3K7G.jpg)

Webフレームワークの種類
① アクションベースフレームワーク
◆HTTPリクエストを主眼に置く
◆Jakarta REST、Spring MVC、Strutsなど
② コンポーネントベースフレームワーク
◆画面の部品や、クリックなどのイベントを主眼に置く
◆Jakarta Faces、Apache Wicketなど
10


# Page. 11

![Page Image](https://bcdn.docswell.com/page/GEWG9LPPJ2.jpg)

フレームワークの分類
HTML
を返す
アクション
ベース
コンポーネント
ベース
JSONなど
を返す
Jakarta REST
Jakarta Faces
ー
アクションベースかつHTMLを返す
フレームワークが無かった
11


# Page. 12

![Page Image](https://bcdn.docswell.com/page/47ZL9MK6J3.jpg)

レガシーフレームワークからの移行コス
ト
◆Struts 1やサーブレットベースの独自フレームワークなどの
レガシーフレームワークはアクションベースが多い
◆これらからコンポーネントベースのJakarta Facesへの移行は
アーキテクチャが完全に異なるため高コスト（ほぼ作り直し）
◆それゆえ、アクションベースでHTMLを返すフレームワークが
求められてきた
12


# Page. 13

![Page Image](https://bcdn.docswell.com/page/YJ6WKNQLJV.jpg)

そこでMVC 1.0登場
◆Java EE 8での導入を目指してMVC 1.0の開発がスタート
◆参照実装はOzark
◆https://github.com/mvc-spec/ozark （既にアーカイブ済み）
◆最初のコミットは2014年11月
13


# Page. 14

![Page Image](https://bcdn.docswell.com/page/GJ5MP5RMJ4.jpg)

当初の開発は活発だった
◆当時のスペックリードであるOracle社の2名を中心に、
メーリングリストでの議論が活発
◆この2名は、JSFのスペックリードとJAX-RSのスペックリードを兼務
◆Ozarkのコミットも活発
14


# Page. 15

![Page Image](https://bcdn.docswell.com/page/LE3W3NP9E5.jpg)

開発の停滞
◆2016年前後から、Oracle社のスペックリード2名の活動が
目に見えて停滞
◆メーリングリストに返信が無い
◆コミットが無い
◆MVC 1.0のみならず、Java EE 8に向けた開発全体が停滞
◆Java EE Guardiansが発足したのもこの頃
◆参考記事: Java EEを救うためにJava EEガーディアンズは結束した
15


# Page. 16

![Page Image](https://bcdn.docswell.com/page/8EDK4WL87G.jpg)

Java EEからJakarta EEへ
◆2017年9月: Java EE 8リリース
◆2019年9月: Jakarta EE 8リリース
◆2020年12月: Jakarta EE 9リリース
◆javax.* → jakarta.*
◆2022年9月: Jakarta EE 10リリース
◆2025年6月: Jakarta EE 11リリース
◆2026年？月: Jakarta EE 12リリース？
16


# Page. 17

![Page Image](https://bcdn.docswell.com/page/V7PKM92WJ8.jpg)

この間、MVCはどうしてたの？
◆コミッターの一人だった
このお二人は
MVCの救世主
Christian Kaltepoth氏が
中心となって開発を継続
→ 新たなスペックリードに
◆EE4Jの設立に尽力した
Ivar Grimstad氏が
(写真はお二人の
GitHubから拝借)
共同スペックリードに
→ 近年の開発を主導
17


# Page. 18

![Page Image](https://bcdn.docswell.com/page/2JVV9MD9JQ.jpg)

OzarkからKrazoへ
◆MVC 1.0の参照実装Ozarkから、
Jakarta MVCの互換実装Krazoに変更
◆https://github.com/eclipse-ee4j/krazo
◆「Ozark」を逆から読むと「Krazo」
18


# Page. 19

![Page Image](https://bcdn.docswell.com/page/5EGLZGY4JL.jpg)

Jakarta MVCの苦労
◆なかなかJakarta EEに含まれない
◆しかしChristianさん・Ivarさんを中心に、開発は続いた
◆そしてようやっと、Jakarta EE 12に含まれる予定
19


# Page. 20

![Page Image](https://bcdn.docswell.com/page/4JQYLXMR7P.jpg)

まとめ
◆Jakarta MVCはHTMLを返すアクションベースフレームワーク
◆当初はJava EE 8でMVC 1.0として導入予定だったが停滞
◆Christian Kaltepoth氏とIvar Grimstad氏の尽力で
開発が継続
◆Jakarta EE 12でようやっと導入予定
◆互換実装はKrazo
20


# Page. 21

![Page Image](https://bcdn.docswell.com/page/K74WD6VQE1.jpg)

もくじ
① Jakarta MVC導入の背景
② Jakarta MVCの機能
③ Jakarta MVCのアーキテクチャ
21


# Page. 22

![Page Image](https://bcdn.docswell.com/page/LJ1YZV3LEG.jpg)

機能説明の前に
◆Jakarta MVCはJakarta RESTベースの薄いフレームワーク
◆ほとんどはJakarta RESTの機能
22


# Page. 23

![Page Image](https://bcdn.docswell.com/page/GJWG9LPQ72.jpg)

依存関係
&lt;dependencies&gt;
&lt;dependency&gt;
&lt;groupId&gt;jakarta.platform&lt;/groupId&gt;
&lt;artifactId&gt;jakarta.jakartaee-api&lt;/artifactId&gt;
&lt;version&gt;11.0.0&lt;/version&gt;
&lt;scope&gt;provided&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;jakarta.mvc&lt;/groupId&gt;
&lt;artifactId&gt;jakarta.mvc-api&lt;/artifactId&gt;
&lt;version&gt;3.0.0&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.eclipse.krazo&lt;/groupId&gt;
&lt;artifactId&gt;krazo-resteasy&lt;/artifactId&gt;
&lt;version&gt;4.0.2&lt;/version&gt;
&lt;/dependency&gt;
23


# Page. 24

![Page Image](https://bcdn.docswell.com/page/4EZL9MK373.jpg)

依存関係（続き）
&lt;dependency&gt;
&lt;groupId&gt;org.eclipse.krazo.ext&lt;/groupId&gt;
&lt;artifactId&gt;krazo-thymeleaf&lt;/artifactId&gt;
&lt;version&gt;3.0.0&lt;/version&gt;
&lt;exclusions&gt;
&lt;exclusion&gt; &lt;!-- 古いバージョンのThymeleafを除外 --&gt;
&lt;groupId&gt;org.thymeleaf&lt;/groupId&gt;
&lt;artifactId&gt;thymeleaf&lt;/artifactId&gt;
&lt;/exclusion&gt;
&lt;/exclusions&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.thymeleaf&lt;/groupId&gt;
&lt;artifactId&gt;thymeleaf&lt;/artifactId&gt;
&lt;version&gt;3.1.5.RELEASE&lt;/version&gt;
&lt;/dependency&gt;
&lt;/dependencies&gt;
24


# Page. 25

![Page Image](https://bcdn.docswell.com/page/Y76WKNQZ7V.jpg)

準備
◆Applicationのサブクラスを作る
◆これは完全にJakarta RESTと同じ
@ApplicationPath(&quot;/web&quot;)
public class WebApplication extends Application {
}
25


# Page. 26

![Page Image](https://bcdn.docswell.com/page/G75MP5R974.jpg)

コントローラーの作成
◆リソースクラスまたはリソースメソッドに@Controllerを付加
◆ビューに値を渡すModelsをDI
◆バリデーション結果を保持するBindingResultをDI
@Controller
@Path(&quot;/idol&quot;)
public class IdolController {
@Inject private IdolService idolService;
@Inject private Models models;
@Inject private BindingResult bindingResult;
26


# Page. 27

![Page Image](https://bcdn.docswell.com/page/9J296ND5ER.jpg)

検索してビューに遷移
◆検索結果はmodels.put()する
◆遷移先のビューはWEB-INF/views配下のパスを指定
@GET
@Path(&quot;/&quot;)
public String searchByName(
@QueryParam(&quot;keyword&quot;) @DefaultValue(&quot;&quot;) String keyword) {
List&lt;Idol&gt; idolList = idolService.findByNameOrderById(keyword);
models.put(&quot;idolList&quot;, idolList);
return &quot;idol/index.html&quot;;
}
WEB-INF/views/idol/index.html
に遷移
27


# Page. 28

![Page Image](https://bcdn.docswell.com/page/DEY49P26JM.jpg)

利用できるビュー
◆Krazo本体にはJSP連携機能のみ
◆krazo-thymeleaf: Thymeleaf連携
◆krazo-freemarker: Freemarker連携
◆他にもいろいろ
◆https://github.com/eclipse-ee4j/krazo-extensions 参照
28


# Page. 29

![Page Image](https://bcdn.docswell.com/page/VJNYL5W178.jpg)

フォームクラス
◆各フィールドに@FormParam＋@MvcBindingを付加
◆@MvcBindingにより、バリデーションエラー時でも例外にならない
public class IdolForm {
@MvcBinding @FormParam(&quot;name&quot;) @NotBlank(...) @Size(...)
private String name;
@MvcBinding @FormParam(&quot;birthday&quot;) @NotBlank(...) @Pattern(...)
private String birthday;
@MvcBinding @FormParam(&quot;bloodType&quot;) @NotBlank(...) @Pattern(...)
private String bloodType;
29


# Page. 30

![Page Image](https://bcdn.docswell.com/page/YE9P4YXYJ3.jpg)

登録とバリデーション
◆引数に@Validを付加することでバリデーションを有効化
◆バリデーションエラーはBindingResultが保持
@POST @Path(&quot;/join&quot;)
public String join(@Valid @BeanParam IdolForm idolForm) {
if (bindingResult.isFailed()) { // エラーが1つでもあればtrue
models.put(&quot;bindingResult&quot;, bindingResult);
models.put(&quot;idolForm&quot;, idolForm);
return &quot;idol/join.html&quot;;
}
Idol idol = idolForm.toEntity();
idolService.join(idol);
return &quot;redirect:/idol&quot;; // /idolにリダイレクト
}
30


# Page. 31

![Page Image](https://bcdn.docswell.com/page/GE8DQ62KED.jpg)

バリデーションエラーメッセージの表示
◆BindingResult#getErrors()で
各項目のエラーメッセージを取得（戻り値はSet）
&lt;th&gt;名前&lt;/th&gt;
&lt;td&gt;
&lt;input type=&quot;text&quot; name=&quot;name&quot; th:value=&quot;*{name}&quot;&gt;
&lt;ul class=&quot;error&quot;
th:unless=&quot;${#sets.isEmpty(bindingResult.getErrors(&#039;name&#039;))}&quot;&gt;
&lt;li th:each=&quot;err : ${bindingResult.getErrors(&#039;name&#039;)}&quot;
th:text=&quot;${err.message}&quot;&gt;エラー&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
31


# Page. 32

![Page Image](https://bcdn.docswell.com/page/LELMX92P7R.jpg)

MvcContext
◆アプリケーション情報を保持するインタフェース
◆ビューからは常に${mvc}で参照可能
32


# Page. 33

![Page Image](https://bcdn.docswell.com/page/4JMYLZ82JW.jpg)

CSRF対策
◆POSTの際にCSRFトークンを埋め込む
◆CSRFトークンのチェックは自動でやってくれる
→ トークンが不正な場合は例外発生
&lt;form method=&quot;post&quot; ...&gt;
&lt;input type=&quot;hidden&quot;
th:name=&quot;${mvc.csrf.name}&quot;
th:value=&quot;${mvc.csrf.token}&quot;&gt;
...
&lt;/form&gt;
33


# Page. 34

![Page Image](https://bcdn.docswell.com/page/PJR9K65579.jpg)

パスの指定
◆MvcContext#getBasePath()で
コンテキストルート＋アプリケーションパスが取得できる
&lt;form method=&quot;post&quot;
th:action=&quot;@{${mvc.basePath} + &#039;/idol/join&#039;}&quot;
th:object=&quot;${idolForm}&quot;&gt;
&lt;input type=&quot;hidden&quot;
th:name=&quot;${mvc.csrf.name}&quot;
th:value=&quot;${mvc.csrf.token}&quot;&gt;
...
&lt;/form&gt;
34


# Page. 35

![Page Image](https://bcdn.docswell.com/page/PEXQLMKXJX.jpg)

その他の機能
◆@RedirectScoped
◆Cross-Site Scripting対策
◆国際化
◆フォームメソッドオーバーライド
◆ぜひ仕様書を読んでみてください（短いです）
◆https://jakarta.ee/specifications/mvc/3.0/jakarta-mvc-spec-3.0
35


# Page. 36

![Page Image](https://bcdn.docswell.com/page/3EK9LG59ED.jpg)

まとめ
◆リソースクラスまたはリソースメソッドに@Controllerを付加
◆Modelsで値を保持
◆BindingResultでバリデーション結果を保持
◆ビューはWEB-INF/viewsに置く
◆その他、そんなに機能は多くない
→ Jakarta RESTの機能を活用する
36


# Page. 37

![Page Image](https://bcdn.docswell.com/page/L73W3NK975.jpg)

もくじ
① Jakarta MVC導入の背景
② Jakarta MVCの機能
③ Jakarta MVCのアーキテクチャ
37


# Page. 38

![Page Image](https://bcdn.docswell.com/page/87DK4W38JG.jpg)

Jakarta MVCのアーキテクチャ
◆Jakarta MVCはJakarta RESTベースの薄いフレームワーク
◆Jakarta MVCのアーキテクチャ ≒ Jakarta RESTのアーキテクチャ
◆特にJakarta RESTのProcessing Pipelineが重要
38


# Page. 39

![Page Image](https://bcdn.docswell.com/page/VJPKM94WE8.jpg)

各コンポーネントの説明
◆MessageBodyReader: リクエストボディをリソースメソッドの引数に変
換。
引数の型やリクエストボディの種類などで適切なものが1つ選ばれる
◆MessageBodyWriter: リソースメソッドの戻り値をレスポンスボディに
変換。
戻り値の型やレスポンスボディの種類などで適切なものが1つ選ばれる
◆ContainerRequestFilter: リクエストの前処理
◆ContainerResponseFilter: リソースメソッドの後処理
◆ReaderInterceptor: MessageBodyReaderの前処理＋後処理
39


# Page. 40

![Page Image](https://bcdn.docswell.com/page/2EVV9MX9EQ.jpg)

Jakarta RESTのProcessing Pipeline
リクエス
ト
PreMatch
PreMatch
Container
Container
Container
Request
Request
Request
Filter
Filter
Filter
PreMatch
PreMatch
Container
Reader
Container
Request
Inter
Request
Filter
ceptor
Filter
(前処理)
Message
Body
Reader
PreMatch
PreMatch
Container
Reader
Container
Request
Inter
Request
Filter
ceptor
Filter
(後処理)
リソース
メソッド
レスポン
ス
PreMatch
PreMatch
Container
Writer
Container
Request
Inter
Request
Filter
ceptor
Filter
（後処理）
Message
Body
Writer
PreMatch
PreMatch
Container
Writer
Container
Request
Inter
Request
Filter
ceptor
Filter
（前処理）
PreMatch
PreMatch
Container
Container
Container
Request
Request
Response
Filter
Filter
Filter
40


# Page. 41

![Page Image](https://bcdn.docswell.com/page/57GLZGV4EL.jpg)

@NameBinding
◆特定のリソースメソッドにだけFilter・Interceptorを
ここにだけ
フィルターが
実行される
適用する目印
@NameBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface Sample {}
@Sample
@Provider
public class SampleResponseFilter
implements ContainerResponseFilter {
...
}
@Path(&quot;/...&quot;)
public class MyResource {
@GET @Path(&quot;/...&quot;) @Sample
public Response get1() { ... }
@GET @Path(&quot;/...&quot;)
public Response get2() { ... }
}
41


# Page. 42

![Page Image](https://bcdn.docswell.com/page/4EQYLX6RJP.jpg)

Jakarta MVCの処理の流れ
① @Controllerを付加した
リソースメソッドの後処理に
ViewResponseFilterが動く
// @Controllerのソースコード
@NameBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface Controller {}
② ViewResponseFilterが
リソースメソッドの戻り値を
@Controllerの正体は
@NameBinding
Viewableに変換
③ Viewableに対応した
MessageBodyWriter実装である
ViwableWriterが動く
42


# Page. 43

![Page Image](https://bcdn.docswell.com/page/KJ4WD64Q71.jpg)

Jakarta MVCの処理の流れ
④ ViewableWriter内で、
ビューの拡張子などから
&lt;&lt;interface&gt;&gt;
ViewEngine
適切なViewEngine実装を選ぶ
JspViewEngine
⑤ ViewEngine実装が
ビューをレスポンスに書き出す
Thymeleaf
ViewEngine
Freemarker
ViewEngine
43


# Page. 44

![Page Image](https://bcdn.docswell.com/page/LE1YZV4L7G.jpg)

まとめ
◆Jakarta MVCはJakarta RESTベースの薄いフレームワーク
◆特にJakarta RESTのProcessing Pipelineが重要
◆@Controllerを付加することで
MesageBodyWriter実装が動き、その中でViewEngineが動く
44


# Page. 45

![Page Image](https://bcdn.docswell.com/page/GEWG9LXQJ2.jpg)

最後のまとめ
◆Christianさん・Ivarさんに感謝して使いましょう
◆Jakarta RESTのProcessing Pipelineは
しっかり理解しましょう
45


