最新の安定バージョンについては、Spring LDAP 4.1.1 を使用してください!

トランザクションサポート

リレーショナルデータベースの扱いに慣れているプログラマーが LDAP の世界に足を踏み入れると、トランザクションという概念がないことに驚くことがよくあります。プロトコルにはトランザクションに関する規定がなく、どの LDAP サーバーもそれをサポートしていません。Spring LDAP は、これが大きな問題になり得ることを認識し、LDAP リソース上でクライアント側でカバレッジトランザクションをサポートする機能を提供しています。

LDAP トランザクションサポートは、LDAP 操作の Spring トランザクションサポートを管理する PlatformTransactionManager 実装である ContextSourceTransactionManager によって提供されます。コラボレーターとともに、トランザクションで実行された LDAP 操作を追跡し、各操作の前に状態を記録し、トランザクションをロールバックする必要がある場合に初期状態を復元するための手順を実行します。

Spring LDAP トランザクションサポートは、実際のトランザクション管理に加えて、同一のトランザクション全体を通して同じ DirContext インスタンスが使用されることを保証します。つまり、トランザクションが完了するまで DirContext は実際には閉じられないため、より効率的なリソース利用が可能になります。

Spring LDAP が採用しているトランザクションサポートの手法は多くのケースで十分ですが、従来の意味での「真の」トランザクションとは全く異なります。サーバーはトランザクションを全く認識しないため、(たとえば)接続が切断された場合、トランザクションをロールバックする方法はありません。この点は慎重に検討する必要がありますが、代替案としてトランザクションサポートを一切行わないという選択肢もあることを忘れてはなりません。Spring LDAP のトランザクションサポートは、現状でほぼ最高レベルと言えるでしょう。
クライアント側のトランザクションサポートにより、元の操作で必要な作業に加えて、いくらかのオーバーヘッドが追加されます。ほとんどの場合、このオーバーヘッドは心配する必要はありませんが、アプリケーションが同じトランザクション内で複数の LDAP 操作を実行しない場合 (たとえば、modifyAttributes に続いて rebind)、または JDBC データソースとのトランザクション同期が不要な場合 ( JDBC トランザクションの統合を参照してください)、LDAP トランザクションサポートを使用しても得られるものはほとんどありません。

構成

Spring トランザクションの設定に慣れている方であれば、Spring LDAP トランザクションの設定方法は非常に馴染み深いものに感じられるでしょう。トランザクション対象クラスに @Transactional アノテーションを付け、TransactionManager インスタンスを作成し、Bean 設定に <tx:annotation-driven> 要素を含めることができます。以下の例は、その方法を示しています。

<ldap:context-source
       url="ldap://localhost:389"
       base="dc=example,dc=com"
       username="cn=Manager"
       password="secret" />

<ldap:ldap-template id="ldapTemplate" />
<ldap:transaction-manager>
    <!--
    Note this default configuration will not work for more complex scenarios;
    see below for more information on RenamingStrategies.
    -->
   <ldap:default-renaming-strategy />
</ldap:transaction-manager>

<!--
   The MyDataAccessObject class is annotated with @Transactional.
-->
<bean id="myDataAccessObject" class="com.example.MyRepository">
  <property name="ldapTemplate" ref="ldapTemplate" />
</bean>

<tx:annotation-driven />
...
このセットアップはほとんどの単純なユースケースでうまく機能しますが、一部のより複雑なシナリオでは追加の構成が必要になります。特に、トランザクション内でサブツリーを作成または削除する必要がある場合は、名前の変更戦略に従って、代わりの TempEntryRenamingStrategy を使用する必要があります。

実際の状況では、リポジトリレベルではなく、サービスオブジェクトレベルでトランザクションを適用することになるでしょう。前の例は、一般的な考え方を示しています。

JDBC トランザクションの統合

このサポートは Spring LDAP 4.0 で削除されました。

LDAP 補正トランザクションの説明

Spring LDAP は、各変更操作(bind、unbind、rebind、modifyAttributes、rename)の前に LDAP ツリーに状態を記録することで、カバレッジトランザクションを管理します。これにより、トランザクションをロールバックする必要が生じた場合でも、システムはカバレッジ操作を実行できます。

多くの場合、補正操作は非常に簡単です。例: bind 操作の補正ロールバック操作は、エントリのバインドを解除することです。ただし、その他の操作では、LDAP データベースの特定の特性により、別のより複雑なアプローチが必要になります。具体的には、エントリのすべての Attributes の値を常に取得できるとは限らないため、前述の戦略は (たとえば) unbind 操作には不十分です。

そのため、Spring LDAP 管理トランザクション内で実行される各変更操作は、内部的に記録操作、準備操作、コミット操作、ロールバック操作の 4 つの異なる操作に分割されます。次の表は、各 LDAP 操作について説明しています。

LDAP 操作 記録 準備 コミット ロールバック

bind

バインドするエントリの DN を記録します。

エントリをバインドします。

操作なし。

記録された DN を使用して、エントリのバインドを解除します。

rename

元の DN とターゲット DN を記録します。

エントリの名前を変更します。

操作なし。

エントリの名前を元の DN に戻します。

unbind

元の DN を記録し、一時的な DN を計算します。

エントリの名前を一時的な場所に変更します。

一時エントリのバインドを解除します。

エントリの名前を一時的な場所から元の DN に戻します。

rebind

元の DN と新しい Attributes を記録し、一時的な DN を計算します。

エントリの名前を一時的な場所に変更します。

新しい Attributes を元の DN でバインドし、元のエントリを一時的な場所からバインド解除します。

エントリの名前を一時的な場所から元の DN に戻します。

modifyAttributes

変更するエントリの DN を記録し、変更を行うための補正 ModificationItem インスタンスを計算します。

modifyAttributes 操作を実行します。

操作なし。

計算された補正 ModificationItem インスタンスを使用して、modifyAttributes 操作を実行します。

Spring LDAP トランザクションサポートの内部動作に関するより詳細な説明は、Javadoc に記載されています。

名前の変更戦略

前のセクションの表で説明したように、一部の操作のトランザクション管理では、コミットで実際の変更を行う前に、操作の影響を受ける元のエントリを一時的に名前変更する必要があります。エントリの一時的な DN の計算方法は、構成内の <ldap:transaction-manager > 宣言の子要素で指定される TempEntryRenamingStrategy によって管理されます。Spring LDAP には 2 つの実装があります。

  • DefaultTempEntryRenamingStrategy (デフォルト): <ldap:default-renaming-strategy /> 要素を使用して指定します。エントリ DN の最下位部分にサフィックスを追加します。例: cn=john doe, ou=users の DN の場合、この戦略は cn=john doe_temp, ou=users の一時的な DN を返します。temp-suffix 属性を設定することにより、サフィックスを構成できます。

  • DifferentSubtreeTempEntryRenamingStrategy: <ldap:different-subtree-renaming-strategy /> 要素を使用して指定します。サブツリー DN を DN の最下位部分に追加します。これにより、すべての一時エントリが LDAP ツリーの特定の場所に配置されます。一時サブツリー DN は、subtree-node 属性を設定することによって構成されます。例: subtree-node が ou=tempEntries で、エントリの元の DN が cn=john doe, ou=users の場合、一時的な DN は cn=john doe, ou=tempEntries です。構成されたサブツリーノードが LDAP ツリーに存在する必要があることに注意してください。

DefaultTempEntryRenamingStrategy は、状況によっては機能しません。例: 再帰的な削除を行う場合は、DifferentSubtreeTempEntryRenamingStrategy を使用する必要があります。これは、再帰的な削除操作が、実際にはサブツリー内の各ノードの深さ優先の削除で構成されているためです。子を持つエントリの名前を変更することはできず、DefaultTempEntryRenamingStrategy は各ノードを実際に削除するのではなく、同じサブツリーに (別の名前で) 残すため、この操作は失敗します。疑わしい場合は、DifferentSubtreeTempEntryRenamingStrategy を使用してください。