JMSのConnection, Session, Consumerをキャッシュすべきかどうか

アプリケーションサーバー内からデータベースにアクセスする際にはJDBCの接続オブジェクトがプールされているということはJava EEでは常識です。したがって、アプリケーションロジックでConnectionオブジェクトを保持せず、接続を利用するたびに新規に接続を作成して使い終わったらクローズするというのがベストです。(クローズしても実際のDB接続が閉じられるわけではない。)Spring FrameworkのJdbcTemplateを使えばこのような典型的な処理が自動化されます。
JMSのConnectionとかSessionに対しても同じ発想をしてよいのでしょうか?実際、JmsTemplateをそのまま利用すると、JDBCの場合と同様に毎回接続を作り直す動作となります。実はここが意外に難しいところで、適切な構成にすることが難しく間違った設定をしているケースが多く見受けられます。間違った設定をしても、通常は何となくメッセージの送受信ができてしまうため、後々性能が劣化したり、時々メッセージがロストしたり、トランザクションに参加できなかったりと検出が難しいバグを生むことになります。
以下の記事を参考に、以下に私の理解している範囲であるべき設定方法をまとめます。
http://community.jboss.org/wiki/ShouldIcacheJMSconnectionsandJMSsessions

1.サーバーの外部にあるJMSのキューに直接アクセスする場合

ActiveMQとかSwiftMQのようにアプリケーションサーバーとは独立したJMSサーバーに直接アクセスする場合、JMSの接続はもちろんキャッシュされません。これは、JBoss MessagingやWeblgoic JMSのようなアプリサーバー内蔵型のJMSでも(クラスタ外の)別サーバーインスタンス上のキューに対して直接送受信する場合は同様です。したがって、このようなケースではJMSのConnectionをキャッシュすることは必須となります。また、SessionやConsumerもキャッシュすることが望ましいです。これらのオブジェクトを作り直すのは性能が悪いだけでなく、特にトピックからメッセージを受信するサブスクライバーの場合は、durableでない限り切断中のメッセージを受信できなくなってしまうということであり、絶対に避けなくてはなりません。Springの場合JNDIからルックアップしたConnectionFactoryを直接JmsTemplateに設定するのではなく、CachingConnectionFactoryでデコレートした接続オブジェクトを渡すようにすべきです。以下の記事も参考になります。
http://activemq.apache.org/jmstemplate-gotchas.html
http://www.swiftmq.com/products/router/swiftlets/sys_jms/clients/spring/pooling/index.html
http://community.jboss.org/wiki/CanIusetheSpringJMSTemplatewithHornetQ

2.サーバー上でJCAのリソースとして管理されたJMSのキューにアクセスする場合

アプリサーバー内蔵のJMSとか、rarファイルでJCAリソースとしてサーバーに統合されたJMSプロバイダーの場合は、ConnectionとSessionについてはJCAのレイヤーでプールされるため送信に関しては直接JmsTemplateを使えます。サーバーの実装によってよくわからないのがConsumerがキャッシュされるかどうかです。Weblogicなど一般的なアプリサーバーの場合は、などを使ってリソース参照を定義しておくと、きちんとキャッシュしてくれますが、少なくともJBossの場合Consumerはキャッシュされないため、受信についてはDefaultMessageListenerContainerを使ったMDP(Message Driven Pojo)を使うのであれば、Consumerを別途キャッシュする必要があると考えられます。そうしないと先ほど述べたような理由でdurableでないトピックで受信漏れが発生します。このようにConsumerをキャッシュするとXAのトランザクションにきちんと参加できるかどうかちょっと不安なところです。Weblogicだと大丈夫なようですが、JBossだとだめといううわさもありますので実際はサーバーごとに検証が必要です。MDPとJBossは相性がよくないようですし(http://community.jboss.org/wiki/JBMSpringJMSTemplateNotes)、どうしてもXAが必要ならメッセージ駆動型EJBMDB)を使わなくてはならないかもしれません。