參考 官網 transaction 的設定
Transaction Settings
xml:
<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>
這裡的 ldap:default-renaming-strategy
其實就是 DefaultTempEntryRenamingStrategy
這隻 class。
LDAP Operation | Recording | Preparation | Commit | Rollback |
---|---|---|---|---|
bind | Make record of the DN of the entry to bind. | Bind the entry. | No operation. | Unbind the entry using the recorded DN. |
unbind | Make record of the original DN and calculate a temporary DN. | Rename the entry to the temporary location. | Unbind the temporary entry. | Rename the entry from the temporary location back to its original DN. |
遇到的問題:
之前遇到的情況是當我 unbind
DN 時,我發現我要刪除的 DN (假設為 ou=test
)變成 ou=test_temp
。
結果就發現上面這個表格,當使用 unbind
這個操作時,DefaultTempEntryRenamingStrategy
會先幫我加上 _temp
,
如果最後這個 transaction 是 commit
的話,就會正常刪除。但是如果有 Exception
的話,有可能會看到 ou=test_temp
這個出現在 Ldap Server 中。
理由:
因為我們使用的 transaction manager
是 ContextSourceTransactionManager
這隻 class,而這隻 extends
AbstractPlatformTransactionManager
。
我們可以看到在 AbstractPlatformTransactionManager
裡面的 rollbackOnCommitFailure
是設定 false
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable { ... private boolean rollbackOnCommitFailure = false; ... }
所以當我們存取 Ldap Server 有遇到錯誤時,預設是沒有 rollback
的,然後 transactionManager
還來不及 commit
就把 Exception
丟出來,導致我們看到 ou=test_temp
。
解決方式:
將 ContextSourceTransactionManager
的 rollbackOnCommitFailure
設為 true
。
java:
@Configuration public class MyConfiguration { @Bean public ContextSourceTransactionManager contextSourceTransactionManager(ContextSource contextSource) { ContextSourceTransactionManager contextSourceTransactionManager = new ContextSourceTransactionManager(); contextSourceTransactionManager.setContextSource(contextSource); contextSourceTransactionManager.setRenamingStrategy(new DefaultTempEntryRenamingStrategy()); contextSourceTransactionManager.setRollbackOnCommitFailure(true); return contextSourceTransactionManager; } }
目前是用這種方式解決。