システム開発で思うところ

Javaで主にシステム開発をしながら思うところをツラツラを綴る。主に自分向けのメモ。EE関連の情報が少なく自分自身がそういう情報があったら良いなぁということで他の人の参考になれば幸い

JakartaEE&MicroProfile(JakartaCDI特集)

はじめに

久しぶりの勉強会の備忘です。
自分向けのメモを書いていたりはしていたのですが、スライドを見ればわかることしか書いていないし、最近はブログに書くまではしなくなっていました。
今回は、Jakarta EEの勉強会(1回目)ということと、参加者として貢献できるところもあるのかな?と思い直して今に至ります。

jakartaee.doorkeeper.jp

CDIの誤解しがちな仕様とその対処TIPS

speakerdeck.com

https://github.com/jjugnsjeecditips202602

WELD-000075で困った話

デフォルトのスコープが違うところは、Springの挙動とCDIの挙動の違いとしては顕著なところかもしれないですね。

EEを触っていたのが随分と前だったこともあって、Managed Beanのスコープ設定の扱いとかすっかり忘れていました&SpringはAppicationScopeがデフォルトというのに始めは戸惑ったことを逆に思い出しました。

記憶としては曖昧ですけど、この辺のスコープ絡みでトランザクションとかで、ハマったというか困ったことがあって、最終的にサービスを Request Scopedにして「ま、これでいいか」としたことがあったような無かったような……

今回の話を踏まえて考え直したら、実はそんなことはしなくても良いみたいなことになるのかもしれないけど、それは未来の宿題にしておこうと思います。

そういえば、どうしてEEは状態を持つ前提なんだったっけ?と思ったら、そうだった JSF*1があったからか……
こちらもむかーし Conversation Scopedで色々と思考実験(?)みたいなのをしたこともあったなぁ。
JSFは嫌いじゃないけど、リソースの活用とか考えたり、Spring MVC(アクション指向)になれると状態を持つというのがなれないというか、気が抜けないというか、そんな感覚に最近はなっているかもしれない。
まぁ、常識の範囲の使い方であれば特に問題もないし、結局は慣れみたいなところだとは思いますけど。

いずれにしても、CDIは状態管理が Springと違うから、気を付けないといけないポイントだな!というのを頭の片隅に置いておくことは大事そう。

Dependentスコープのインスタンスがメモリ解放されない

対策は、CDI.current().destroy() でちゃんと開放しないといけないよ、とのこと。
Quarkus のCDI Liteの実装である ArC だと発生しないとか、AOPアノテーションが付いていなかったら発生しないとか、Weldの実装によるものとのこと。
EE(Full)は、EEサーバ自体にマシンパワーを求めて、そこで中央集権的に処理をするという思想だったりするのかな?
勝手なイメージとしては、アノテーションが付いているフィールドは状態を保持する可能性があるから、能動的に破棄はしないで、EEサーバのメモリ上にキャッシュ的に持っておくみたいな発想があるのかなぁ。
CDI Liteは仕様わからないけど、EE(Full)と違って、マイクロサービス向けで、キャッシュをもって高速化するというよりも、小さく持ってすぐ捨てる、みたいな実装しそうがあるから、とかあったりするのかぁ。

あと、CDIのコンポーネントをコンテナから直接取得するというのは、基盤的なところを実装したらやりたくなるのかな?
積極的に採用することはなさそうだということと、横断的関心毎であればAOPで制御をするかなぁと思っているので、正直なところ具体的なユースケースがわからなかったかも。
あえて思ったのは、エクセルでクラスパスのコンテナ管理の定義をつくって、それを読み込ませることでソースコードを触らなくてもいろいろできますよ系とかかなぁ?
Map<String(識別子), String(クラスパス)>な構造体にして、何でもできますよみたいな*2

大量のInjectをすることの忌避感自体は理解はするし、実際、Springでもユースケース的につかうサービスは、そうなりがち。
仕方ないのかなぁと正直思っているし、アクション単位でクラスを分けるとか、そんな感じでクラス分割をするとか、そっちの方向で僕はどうにかしようとしている気がするかも。
あとは、状態管理(コンテナ管理)をしないといけないオブジェクトなのか?っていうのは再考したいところかもしれない。
CDIはManeged Bean的な文化(?)があるので、引数で渡せばいいものを、そうしないでRequest Scopedにして Injectして使用するとかしがちかもしれない*3
そのあたりを見直しするだけでも変わってくるのかもしれない。
とはいえ、JSFを使い始めたら「あぁ、、そうだったそうだった」っていうことに直面はしそう*4

LangChain4jとは一味違うLangChain4j-CDI

speakerdeck.com

https://github.com/fujitsu/app_blog/tree/master/lc4j-cdi-samples

EEといえば、数村さん。
EE関連の情報の中で、EEサーバの商品説明(?)ではなく、標準化として今何をやっていて、こういうこともできるようになっているよという情報収取をしたい場合は、やっぱり数村さんのセッションという感じ*5

そして、話を聞くことが優先されてしまってメモを取っていないというのも毎度の話……
資料メインのときは、資料がわかりやすいのでメモを取る必要がなく、デモ中心のときはデモがスムーズすぎてメモを取る暇がない……

AIの変遷

AIといえば、LLMという感じだけど、そうそう元々(?)は、こんな感じだったこんな感じだった、というのを再認識。

LangChain4j

使いやすそう。
RAGを駆使したら、プロダクト専用のプロンプトフォームのバックエンドとか作れるのかもしれない。
バックエンドをクローズドなローカルLLMにしておいて社内QAとか、クローズドな環境用のプロンプトに使うとか、そういうときの実装イメージを感じられて面白かったです。

LangChain4j-CDI

名前は似ているけど、全く別物とのこと。
個人的には、単体仕様のときは それでいいとして、標準仕様になるときにはネームスペースの問題も含めて、製品に偏った表現はやめたほうが良さそう、、と素人ながらに思いました。
AI-CDI(Spring AIに近い命名イメージ)とか、AIもMLとかもあるので、LLM-CDIにするとか。
jakartaにするのか、 io.opentelemetryみたいな感じで もっと標準的にいくのか、org.eclipse.microprofileにしてしまってConfigみたいにいつまでもEEに入らないようになってしまうのか*6
名前付けは本当に難しい……

さいごに

後で疲れてしまうので最近は不参加なことが多かったのですが*7、今回はEEだし 似たような技術背景の人が多いだろうと思って参加しました。
@yusuke さんと色々なお話をさせていただき考えるヒントを持ち帰れたのはよかったです!*8
僕は文系プログラマですが20年以上かけて積み上げたものがあるのでどうにかなっている(?)ところはありますけど、AIによる実装の加速度的な変化とか、そもそも知っておくべきことの多さとか、本当に今の若い人は大変だなぁと。
とりあえず、僕は、若い人たちの よき踏み石になって、明日から頑張ろうと ちょっとだけ思いました。

*1:Jakarta Faces

*2:結構、昔のSIerさんが好きな独自自動生成フレームワーク的なのでありがちが方式

*3:少なくとも以前の僕はそういう実装をしていた気がする

*4:もう、昔過ぎて、作法を忘れてしまっている……

*5:Springといえば、@making さん、みたいな感じ

*6:それだけは、やめてほしいということであえて……

*7:JJUG CCCの懇親会で、あるとき人酔いみたいになって、それから懇親会全般の参加は躊躇しがちになっていました……

*8:占有状態になってしまいまして…ありがとうございました!