Java EE6がApacheTomcatをApacheTomEEとして認定することを目標に着手したとき、Java EE6TCKを最終的に通過させるために埋めなければならなかったギャップのいくつかを以下に示します。
完全なリストではありませんが、既存の回答でも明らかではない可能性のあるいくつかのハイライト。
TransactionManagerなし
認定されたサーバーには、トランザクション管理が絶対に必要です。UserTransaction
どのWebコンポーネント(servlet、filter、listener、jsfマネージドBean)でも、次のように注入できるはずです。
@Resource UserTransaction transaction;
javax.transaction.UserTransaction
を使用してトランザクションを作成できるはずです。そのトランザクションの範囲内で触れるすべてのリソースは、すべてそのトランザクションに登録されている必要があります。これには、次のオブジェクトが含まれますが、これらに限定されません。
javax.sql.DataSource
javax.persistence.EntityManager
javax.jms.ConnectionFactory
javax.jms.QueueConnectionFactory
javax.jms.TopicConnectionFactory
javax.ejb.TimerService
たとえば、サーブレットでトランザクションを開始する場合、次のようになります。
- データベースを更新します
- トピックまたはキューにJMSメッセージを送信します
- 後で作業を行うためのタイマーを作成します
..そして、それらのいずれかが失敗するか、単にを呼び出すことを選択するとrollback()
、UserTransaction
それらのすべてが元に戻されます。
接続プールなし
非常に明確にするために、2種類の接続プールがあります。
- トランザクション対応の接続プール
- 非トランザクション対応の接続プール
Java EE仕様では、接続プールは厳密には必要ありませんが、接続プールがある場合は、トランザクションを認識する必要があります。そうしないと、トランザクション管理が失われます。
これが意味するのは基本的に:
- 同じトランザクションの全員がプールから同じ接続を持っている必要があります
- 誰かが呼び出し
close()
た、または上の他のメソッドに関係なく、トランザクションが完了する(コミットまたはロールバック)まで、接続をプールに戻さないでくださいDataSource
。
接続プールのためにTomcatで使用される一般的なライブラリはcommons-dbcpです。これをTomEEでも使用したかったのですが、トランザクション対応の接続プールをサポートしていなかったため、実際にその機能をcommons-dbcp(yay、Apache)に追加し、commons-dbcバージョン1.4の時点で存在しています。
commons-dbcpをTomcatに追加するだけでは、トランザクション接続プールを取得するにはまだ十分ではないことに注意してください。トランザクションマネージャーが必要であり、TransactionManager
viaSynchronization
オブジェクトとの接続を登録するための配管を行うためのコンテナーが必要です。
Java EE 7では、DBパスワードを暗号化し、それらをアプリケーションと一緒に安全なファイルまたは外部ストレージにパッケージ化する標準的な方法を追加するという話があります。これは、Tomcatがサポートしないもう1つの機能になります。
セキュリティ統合なし
WebServicesセキュリティ、JAX-RS SecurityContext、EJBセキュリティ、JAASログイン、およびJAACはすべてセキュリティの概念であり、CXF、OpenEJBなどのライブラリを個別に追加しても、デフォルトではTomcatに「接続」されません。
もちろん、これらのAPIはすべて、JavaEEサーバーで連携して動作することを前提としています。Realm
これらすべてを連携させ、Tomcat API上で実行して、既存のすべてのTomcatRealm
実装を使用して「JavaEE」セキュリティを推進できるようにするために、かなりの作業が必要でした。それは本当にまだTomcatのセキュリティであり、非常によく統合されています。
JPA統合
はい、JPAプロバイダーを.warファイルにドロップして、Tomcatの助けなしに使用できます。このアプローチでは、次のことはできません。
@PersistenceUnit EntityManagerFactory
インジェクション/ルックアップ
@PersistenceContext EntityManager
インジェクション/ルックアップ
- トランザクション対応の
EntityManager
接続プールに接続
- JTA-マネージド
EntityManager
サポート
- 拡張永続コンテキスト
JTA-ManagedEntityManager
とは、基本的に、を使用したい同じトランザクション内の2つのオブジェクトEntityManager
が両方とも同じように見え、EntityManager
明示的に渡す必要がないことを意味しますEntityManager
。このすべての「通過」は、コンテナによって行われます。
これはどのように達成されますか?簡単です、EntityManager
あなたがコンテナから得たものは偽物です。ラッパーです。これを使用すると、現在のトランザクションで実際のトランザクションが検索され、そのトランザクションにEntityManager
呼び出しが委任されEntityManager
ます。EntityManager.getDelegate()
これが不思議な方法の理由であるため、ユーザーは必要に応じて実際のEntityManagerを取得し、非標準のAPIを利用できます。もちろん、細心の注意を払ってこれを行い、デリゲートへの参照を保持しないでください。そうしないとEntityManager
、深刻なメモリリークが発生します。デリゲートEntityManager
は通常、トランザクションの完了時にフラッシュ、クローズ、クリーンアップ、および破棄されます。参照を保持している場合は、その参照と、EntityManager
場合によってはそれが保持するすべてのデータのガベージコレクションを防ぐことができます。
EntityManager
コンテナから取得したaへの参照を保持することは常に安全です
- への参照を保持することは安全ではありません
EntityManager.getDelegate()
EntityManager
あなたが自分で作成したものへの参照を保持するように非常に注意してくださいEntityManagerFactory
-あなたはその管理に100%責任があります。
CDI統合
CDIを単純化しすぎたくないのですが、少し大きすぎて、多くの人が真剣に検討していないことがわかりました。多くの人にとって「いつか」のリストに載っています:) 「ウェブガイ」が知りたいと思う。
あなたは典型的なウェブアプリであなたがすることすべてを知っていますか?HttpSession
一日中物事を出し入れしますか?キーに使用String
し、から取得したオブジェクトを継続的にキャストしますHttpSession
。あなたはおそらくあなたのためにそれをするためにユーティリティコードに行きました。
CDIにもこのユーティリティコードがあり、これはと呼ばれ@SessionScoped
ます。注釈@SessionScoped
が付けられたオブジェクトはすべて、あなたに代わって配置および追跡されHttpSession
ます。を介してオブジェクトをサーブレットに挿入するように要求するだけ@Inject FooObject
で、CDIコンテナは、のトランザクション追跡について説明したのと同じ方法で「実際の」FooObjectインスタンスを追跡しEntitityManager
ます。Abracadabra、今あなたはたくさんのコードを削除することができます:)
何かgetAttribute
をsetAttribute
しているHttpServletRequest
?さて、あなたも@RequestScoped
同じ方法でそれを削除することができます。
そしてもちろん、あなたがしているかもしれないとの呼び出し@ApplicationScoped
を排除することがありますgetAttribute
setAttribute
ServletContext
さらにクールにするために、このように追跡されるオブジェクト@PostConstruct
は、Beanが作成されたときに呼び出されるオブジェクトと、@PreDestroy
「スコープ」が終了したときに通知されるメソッドを実装できます(セッションが完了し、リクエストが終了し、アプリがシャットダウンします)下)。
CDIはもっと多くのことができますが、それだけで誰もが古いWebアプリを書き直したくなるでしょう。
いくつかの厄介なもの
Java EE 6に追加されたもののうち、Tomcatの操舵室に追加されていないものがいくつかあります。それらは大きな説明を必要としませんが、「ギャップを埋める」の大部分を占めました。
- へのサポート
@DataSourceDefinition
- グローバルJNDIのサポート(
java:global
、、)java:app
java:module
@Resource MyEnum myEnum
およびを介した列挙型インジェクション
@Resource Class myPluggableClass
およびを介したクラスインジェクション
- へのサポート
@Resource(lookup="foo")
マイナーなポイントですが、ポータブルな方法でアプリで定義DataSource
し、Webアプリ間でJNDIエントリを共有し、「これを調べて注入する」と言う簡単な力を持っていると非常に便利です。
結論
前述のように、完全なリストではありません。EJB、JMS、JAX-RS、JAX-WS、JSF、BeanValidationおよびその他の有用なものについては言及されていません。しかし、Tomcatが何であるか、そうでないかについて人々が話すときに見落とされがちなことについての少なくともいくつかの考え。
また、「Java EE」と考えていたものが、実際の定義と一致しない場合があることにも注意してください。Webプロファイルにより、JavaEEは縮小しました。これは、「Java EEが重すぎて、それがすべて必要ない」という問題に対処するためのものです。
WebプロファイルからEJBを切り取った場合、残っているものは次のとおりです。
- Javaサーブレット
- Java ServerPages(JSP)
- Java ServerFaces(JSF)
- Java Transaction API(JTA)
- Java Persistence API(JPA)
- Javaコンテキストと依存性注入(CDI)
- Bean Validation
これはかなり便利なスタックです。