AIを使ってSpring-BootアプリケーションをWildFly 40 + Jakarta MVCに移行する

ということで、宿題となっていた件を実際にやってみました。

これはWildFlyの話なので、個人ブログの方で書いてます。

前回の記事はこちら:

rheb.hatenablog.com

rheb.hatenablog.com

Jakarta MVCとは!

まずは、【会場開催】Jakarta EE&MicroProfileセミナー「待望のJakarta EE 12最新動向!データアクセス新仕様&ついに標準化されるJakarta MVCを学ぶ」 6/22(月) 開催 - 日本 Jakarta EE & MicroProfile ユーザーグループ | Doorkeeper の多田さんの資料を読みましょう。

www.docswell.com

PetClinicを移植してみた!

前提条件が整ったところで、実際に移植してみました。

PetClinicは以前、JSFへ移行してみたことがありました。その際はJSFの都合上、URLのパスが変わってしまいましたが、 今回はほぼ変更せずに動作させることができました。 そういった点で、Spring BootとJakarta MVCのそれぞれで「どういう差が出るのか」を確認する、良いサンプルになったのではないかと思います。

Jakarta MVCの実装であるKrazoではThymeleafとのインテグレーションもサポートされており、「もしや、Viewは変更なしでもいけるのでは?」と淡い期待も抱いていました。しかし、多田さんの事前情報の通り、ちょっとした差でうまくいかないことも多く大変でした。結果的に、JSFへの移行に比べて2倍くらいの時間がかかっています。とは言っても1日かかっていないので、「思ったよりは簡単にできたな」という印象です。 今後Jakarta MVCに対する情報が増えてくるともっと簡単になるはず。そのためにも情報を出していかないと。

技術に対する直接的な感想としては、Servletベースではなく、背後にJAX-RSが介在している点が、直感的な理解の妨げになりました。JAX-RSの経験不足を痛感……

多田さんの資料でもいくつかハマりポイントが挙げられていたので、本記事ではそれ以外の部分にフォーカスして書いていきます。

御託はいいから移行前後のソースを出せ!

URLごとに同じ動作をするようにはできているので、細かい差についてはソースコードの差分を確認するのが手っ取り早いと思います。

移行前

github.com

移行後

github.com

また、今回はAIに自由気ままに移行させたうえで、どうしてもうまくいかないところだけ細かく指示をする、という形式で進めました。現時点では情報が少ないJakarta Data(Jakarta EE版のRepository仕様)についてはAIが選択しなかったため、自前でRepositoryを実装しています。実務でリプレイスするなら、Jakarta Dataを使用するのが良いでしょう。

国際化がそのままできない!

Spring Bootは、独自の国際化の仕組み(いわゆる messages.properties というメッセージリソース)を持っています。これはThymeleafデフォルトの仕組みではありません。Thymeleafのデフォルトは、ファイルと同名のプロパティファイルを読み込む仕様です。*1

Krazoでは(というか、おそらくJakarta MVCの仕様では)、この国際化の仕組みがJakarta EE側と統合されておらず、ファイルごとにメッセージリソースを配置する必要が出てきます。

Krazoの実装を調べた限り、ここのカスタマイズは行えないようでした。報告は上げたので、今後の改善が期待されます。

www.eclipse.org

今回は上記の事象があったため、国際化まわりについては移行を断念しました。

@ApplicationPathを使ってはいけない!

@ApplicationPathを使うことで、アノテーションベースで手軽にJakarta MVCを作り始めることができます。 しかし、これが大きな罠でした。

この形式で登録した場合、画像ファイルなどの静的リソースを透過的に扱うことができません。ベースであるJAX-RSが本来REST API(JSON/XML)を返すための仕様であり、静的リソースのハンドリングがあまり想定されていないからです。

そのため、解決策としてServletFilter形式でweb.xmlに登録します。

  <!-- JAX-RS/Jakarta MVC Filter -->
  <filter>
    <filter-name>JakartaMvcFilter</filter-name>
    <filter-class>org.jboss.resteasy.plugins.server.servlet.FilterDispatcher</filter-class>
    <init-param>
      <param-name>jakarta.ws.rs.Application</param-name>
      <param-value>org.springframework.samples.petclinic.PetClinicApplication</param-value>
    </init-param>
  </filter>

  <filter-mapping>
    <filter-name>JakartaMvcFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

こうすることで、画像ファイルも透過的に扱えるようになります。このままだと、間違いなくJakarta MVCを使う上での「一番のFAQ」になってしまうでしょう……

こちらも報告はしたので、改善してくれると嬉しいですね。

JAX-RSのロード順の実装は必須

現実のアプリケーションではURLが複雑になり、複数のControllerでPATH(URL)が競合することがあります*2。 本来なら、URLに応じて最適なPATHを自動的に選んでくれればいい*3のですが、Jakarta MVCではそこの解決がうまくいかないらしく、明示的に解決順序を登録する必要がありました。

public class PetClinicApplication extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> classes = new HashSet<>(); //LinkedHashSetのほうが良い気がする・・・?
        // MVC Controllers
        classes.add(WelcomeController.class);
        classes.add(OwnerController.class);
        classes.add(PetController.class);
        classes.add(VisitController.class);
        classes.add(VetController.class);
        classes.add(CrashController.class);
        // REST Resources
        classes.add(VetResource.class);
        // Converters
        classes.add(LocalDateParamConverter.class);
        return classes;
    }
}

ここらへんのURLの解決の仕方はうまくなってほしいところですねぇ。

ResponseとしてXMLを返す場合にはJAXBが必要

Jakarta MVCの問題ではなく、JAX-RSの問題ではあるのですが......

Spring Bootの場合は、特別なアノテーションを付けなくてもJacksonがいい感じに処理してくれましたが、JAX-RSでは次のようにJAXBアノテーションを明示する必要があります。

@XmlRootElement
public class Vets {
    private List<Vet> vets;
    
    @XmlElement
    public List<Vet> getVetList() {
        return vets;
    }
}

アノテーションを付け忘れた際のエラーが 「XML MessageBodyWriter not found」 と表示されるだけで非常に分かりにくいため、初見では確実にハマると思います*4。 実務でいちいちこれを対応するのは現実的ではないので、MessageBodyWriter あたりを自前でカスタマイズして、Jacksonで一括でレスポンスを返すようにしちゃったほうが良さそうですね。

ちなみにAIは、この原因をすぐに見つけ出してくれました。「こんなの知ってて当然でしょ?」くらいのトーンで出してきたので、おそらく定番のFAQなのだと思います。

その他

今回もAIに細かいノウハウについてまとめてもらいました。いくつか怪しい部分もありますが、現状のAIの限界を示すという意味も含めて、そのまま公開しています。

github.com

webjarsの解決をServletで実装する方法など、初めて知りました。AIの力は本当にすごいですね。

まとめ

早くJakarta MVCがもっと気軽に使えるようになってほしいものです。勉強会でも話題に上がっていましたが、各Jakarta EEサーバーベンダーは「フィーチャーリクエスト」という形でお客様の要望を受け付け、要望が多いものから実装・サポートを開始する仕組みを持っていたりします。

Jakarta EE 11でもOptional(任意)な仕様としてJakarta MVCは含まれているので、「早く使いたい!」という方は、ぜひ積極的にフィードバックやリクエストをあげていきましょう!

*1:15.2 Message Resolvers を参照してください

*2:foo と foo/bar の両方があった場合など

*3:最長一致したもの

*4:ちなみにJSONで返したい場合は、何もつけなくても大丈夫です

Jakarta EE&MicroProfileセミナー「待望のJakarta EE 12最新動向!データアクセス新仕様&ついに標準化されるJakarta MVCを学ぶ」 を開催してきた

ということで、6月22日に開催してきました。 参加していただけた皆様ありがとうございます。

4半期に1度やろうと思い、本来は5月にやりたかったですが、5月にはJJUG CCCがあったのでスライドして6月になりました。

前回よりも1割ぐらい参加者が増えていて、とてもありがたかったです。 次回はもっと増えてほしい。

(写真を撮るのを忘れた)

勉強会の内容

今回は、日本電気株式会社(NEC)の景井さんと、日本Javaユーザーグループの多田さんにご登壇いただきました。 内容としては、今月Jakarta EE 12がリリースされる はず だったので、Jakarta EE 12で新しく増える仕様の内容となります。 景井さんがこの内容で行こうと言ってくれて概要が決まり、多田さんも話してくれると言ってくれました。お二方ともありがとうございます。

Jakarta EE 12 が変えるデータアクセスの新仕様:Data, NoSQL, Query 解説 (景井 教天さん)

Jakarta EEではHibernateチームが非常にアクティブに働いており、DBに関わる仕様がどんどん策定されています。今回はJakarta NoSQLというRDB以外のDBの標準化が図られました。

もともとRDB用のJPAに対して無理やりNoSQL用の実装を作る場合もあったので、今回ここまでは実装されてるよと標準ができたのは安心面として大きいのではないかなと思います。 ここまでは確実に動くよってのが保証できたわけですし。

ただ、NoSQLは実装による差異が大きすぎるため、まあ、難しいよなーという印象でした。

ついにMVCがJakarta EEに。その歴史・機能・アーキテクチャを知ろう(多田真敏)

普通にググれば所属が出てくるのであまり隠す意味もないと思うんですが、きっと大人の事情があるんでしょう。 Jakarta MVCは私がずっと入れてほしいと思っている機能でJakarta EE 12でやっとはいりそうになっているので、そちらの説明をしていただけました。 私も最近ずっと触っているのですが、今までServletが中心となっていたのが、Jakarta MVCはJAX-RSベースでの実装になるので、こうなるはず!みたいな勘所が働きにくく、なかなか慣れるまでは苦労しそうです。ただ、これがはいってくれるとやっとJakarta EEだけでアクションベースのUIが作れるようになるので、とてもありがたいです。

Jakarta EE 10で入ってほしかった。。。。

こちらはいろいろな理由があって注力したほうがよさそうなので、私の方でも動作確認をして近日中にナレッジを共有したいと思います。

mvc-devのメーリングリスト を見ると、何をやろうとして何でハマってるかわかるかもしれない。

Jakarta EE 12近況 (数村 憲治さん)

最後に飛び入りで5分だけお話しいただけました。Jakarta EE 12の仕様策定は遅れており、少なくとも今月中に出ることはないとのこと(ギャー

みんなが使いたいと思ってくれると作る側もモチベーションが上がるので、ぜひ皆さま各ベンダーへのフィードバックの方をよろしくお願いします。

最後に

今回も色々な方々に運営を助けていただきました。 前回までに登壇いただいた、吉崎さん、長尾さん、景井さんには会場の準備をお手伝いいただきました。また、金子さんに最後まで片付けや、机を拭くのを手伝っていただきました。その他にもゴミの片づけをたくさんの方々に行っていただき、会場もとてもきれいに使う事ができました。

本当にありがとうございます。

また、今回まだ発見できていないのですが、ブログを書くまでが勉強会です。ブログを書かれたらぜひXにて #JakartaEE を付けて投稿をお願いします。

Jakarta EE 12から増えるJakarta Query

Jakarta EE 12からJakarta Queryというのが増えます。略称はJQもしくはJQLというらしい?

Jakarta EEではJakarta Persistence(JPA)の一部としてJPQLが定義されていましたが、それが外出しされたものになります。 なので、特に新しいものではありません。

で、終わってしまってもあれなので、どういう形で整理されたかというと、RDB向けとRDB以外のNoSQLでも使える二つの階層が定義されました。

  • コア言語(Core Language: JQLCore): Jakarta DataおよびJakarta NoSQLプロバイダーが実装可能な基本セット。SQL以外のデータストア上でも実装できるように設計された、拡張言語の厳密なサブセット。
  • 拡張言語(Extended Language: JQLFull): リレーショナルデータベースを基盤とするJakarta Persistenceプロバイダーやその他の永続化技術向けに調整された、高度な演算機能を含む言語 。

コア言語というのはJakarta Dataができたときに導入された Jakarta Data Query Language (JDQL) がベースとなっているようです。というか同じものの名前を即座に変更したようです。ややこしい。

JPA自体というか、Hibernateのシェアがとても大きいこともあり、RDB以外用でもJPAのAPIを無理やり使えるように実装する事がありました。今回Jakarta NoSQLと合わせてついに標準化されたことになります。

今までハックするような形で実装されていたNoSQL向けの実装がついに標準化されるのは素晴らしい。

とはいっても、NoSQLで使えるようにコア言語で定義されているのは基本的なselect / update / deleteおよびに from ~ where ~ order byで使えるような関数と、基本的な型(文字列、数値、真偽など)と、日付・時刻リテラル、UPPER/LOWERなどの一部の文字列や数値の操作関数程度のようで、これだけでポータビリティを持ったアプリケーションを作るというのはちょっと難しそうな印象ですが、ほとんどのユースケースであるKVSぐらいだったら十分か。

まだ検討中のようですが、select newを使ったJava Beansへの直接値を渡す方法の改善も図られてるみたいなので、期待です。

jakarta.ee

Jakarta EE&MicroProfileセミナー「Jakarta CDI特集(実践的活用方法とAI領域への拡張)」 を開催してきた

ということで、2月24日に開催してきました。 参加していただけた皆様ありがとうございます。

当日の状況

jakartaee.doorkeeper.jp

Java EEがJakarta EEに変わってもう10年近くたちますが、ほとんどの期間はJakarta EEのリリース手順の確認等、ユーザーから見れば停滞していたように見えます。

しかし、なんとか、停滞していた時期も終わり、Jakarta EE 10のリリースから新機能も入るようになってきました。

一時期、OracleからEclipse FoundationにJava EEが移管されたときは、もうJava EEは終わりかなと思っていましたし、実際にOracleが出しているJava EE準拠サーバーであるWebLogicは長らくJava EE*1で止まっていました。 しかし、去年にJakarta EE対応版を出しましたし、他のアプリケーションサーバーもおおよそJakarta EE対応版を出していますので、当面安泰なのかなと思いつつも、商用Jakarta EEサーバーベンダーに勤めてる身としては、ライバルも多く大変な状態です。

勉強会の内容

今回はアクセンチュアの吉崎 太清さんと、富士通/Jakarta EE仕様委員の数村 憲治さんに登壇いただきました。

CDIの誤解しがちな仕様とその対処TIPS(吉崎 太清さん)

吉崎さんは、JJUG CCC 2025 SpringのJakarta EE BoFで知り合い、CDIについて熱い思いがあったようなので、お声がけをしたところ、快く登壇を引き受けていただけました。

内容としては、CDIの深いところをお話しいただきました。内容が盛りだくさん過ぎて懇親会までずっとしゃべり続けていらっしゃいましたが、どうでしたでしょうか?

勉強会を開催するとどうしてもイツメンになりがちなので、こういった縁で登壇いただけたことは非常にありがたいです。今後ともよろしくお願いします。

LangChain4jとは一味違うLangChain4j-CDI(数村 憲治さん)

Jakarta EEは安定した仕様を提供していますが、AIまわりはとてもホットであることで、変更が早くなかなか仕様を固めるというのが難しそうです。AIはそれだけでベンダー間の駆け引きが始まってしまうので、いい感じに落ち着いてほしいと思いつつ・・・・

数村さんはEclipse FoundationでJakarta EEの仕様を決める立場でもあります。そういった方が普通に参加していただけて、また勉強会の運営もしていただけてるので非常にありがたいです。ユーザーとしての立場だとどうしても製品に対して文句を言うだけになりがちですが、数村さんがいることで、意見として吸い上げて、仕様の改善につなげることができるようになってます。(なってほしい)

運営お手伝いいただきありがとう

富士通の長尾さん(GlassFishのコミッター)、NECの景井さん(Javaの本を書いている)、Red Hatの能島さん(世界的に有名なOSSであるWebAuthn4Jの開発者)、と、登壇もいただいた数村さん、会場の設営等、お手伝いいただきありがとうございます。一言で紹介しようとしたらみんな肩書がすごいぞ?なんだこれ。

また、会場を貸していただいたRed Hatからは懇親会補助が出て、ピザとドリンク類を提供いただきました。食べ物の量が少なかったのは発注担当の私が日和ったからです。次回はもうちょっと量を増やしたい。

感想ブログありがとう

皆様ありがとうございます。ブログを書くまでが勉強会です。ブログを書かれたらぜひXにて #JakartaEE を付けて投稿をお願いします。

今後

ご存知の方は多いと思いますが、私はJJUGの幹事もしています。JJUGの中でJakarta EE&MicroProfileユーザグループの活動を行うという事もありえたのですが、JJUGがちょっと大きくなりすぎているので、今回は身軽な形でのスタートとしました。

出来る限り多くの人に運営から参加いただき、また、熱い思いがある人にはどんどん登壇してほしいと思っています。

次回は6月ごろに勉強会を開く予定です。登壇などに興味のある方はSlack: JJUG-membersの #ee にご参加ください。 そこで、一緒にコミュニティを運営していきましょう。

詳細な勉強会の告知についてはDoorKeeperで行っていきます。こちらにもぜひご参加ください。

jakartaee.doorkeeper.jp

*1:正確にはJava EE 8互換のJakarta EE 8

さよならMicroProfile

Jakarta EE / Java EE - Qiita Advent Calendar 2025 - Qiita の記事がまだ空いているので22日目という事で。

実はMicroProfileが無くなる方向で話が進んでいます。とは言っても、個別仕様が全部なくなってしまうのではなくて、仕様をJakarta EEに統合する方向で話が進んでいます。

MicroProfileはJava EEOracleが管理していたころにJava EEの進化の遅さなどを問題視した人たちによって生み出され、Eclipse Foundationで管理されるようになりました。しかし、MicroProfileが生まれてからOracleJava EEを管理するのを止め、現在はEclipse Fundationで管理されています。そう、現時点では両方ともEclipse Foundationで管理されています。また、両方に参加している人たちも多かったりします。

また、最近のJakarta EEはJava EEの頃に比べると互換性に対する意識が変わりつつあり、MicroProfileが掲げていたMicroProfileワーキンググループ憲章 と、Jakarta EEの実情があまり変わらなくなりつつあります。ということで、分けて運営していく意味もあまりないと考えてる人が多いのではないかと感じております。

今後起こる可能性のある事

ここから先は全部妄想です。そもそも本当に統合されるかから確定していない。

microprofileのパッケージがjakartaに変更される

ありえる・・・というか、実際にどうするべきか話し合われています。

Jakarta EEサーバーも原則としてMicroProfileに準拠するようになる

現在は、WildFly(JBoss EAP XP)とLiberty(Websphere Liberty)ぐらいしか対応していないのがGlassFishベースの物や他の物もMicroProfileに対応するかもしれません。

MicroProfileへのUI仕様(Jakarta MVC)の追加

jsonだけだとちょっとねぇ。。。

(旧)MicroProfile準拠サーバーの下位互換性の向上、(旧)Jakarta EE準拠サーバーの下位互換性の低下

どっちに寄せられることになるのか・・・・・

(旧)MicroProfile準拠サーバー・(旧)Jakarta EE準拠サーバーの統廃合

現時点でも両方とも最新仕様に準拠できているものは少ないため、さらに統廃合が進むかもしれない。

ちゃんとした情報が欲しい場合

メーリングリストに参加しましょう。

accounts.eclipse.org

Jakarta Persistence 3.2(Jakarta EE 11)からCalendar/Date/Timeなどが非推奨化されます!

これはJakarta EE / Java EE Advent Calendar 2025の7日目の記事です。

昨日は @kazumura によるJava系各種Landscape #AI - Qiita で、
明日はQuarkusの記事です。(雑)

そろそろ上にあるリンクを編集するのも面倒くさくなってきましたが、皆様いかがお過ごしでしょうか?

Jakarta EE 11仕様のJPAでは大きな機能が非推奨化されました。

なんと、昔ながらの日付APIが非推奨化されました。

Deprecates usage of Calendar, Date, Time, Timestamp, Temporal, MapKeyTemporal and TemporalType in new applications in favour of java.time API

今後は、Java 8から導入された Date and Time API を使用する事が推奨されます。LocalDateなどです。 なお、JPAではJava EE 8の頃からDate and Time APIをサポートしていますので、すでに使われている方も多いのではないかと思います。

古い日付APIが使われなくなると、java.util.Dateとjava.sql.Dateとjava.sql.Timestampの微妙な挙動の差に悩まされたりしなくなるのですが、多くのアプリケーションはいまだに古い日付APIを使い続けてると思いますので、対応を考える必要が出てきそうですね。

ただ、現実問題としては仕様としては将来的に削除されたとしても実装側では残り続けそうな気はします。さすがに今の使われ方を考えると消せない気がする・・・・・

ということで、簡単ですがここまでで。