• 静思
  • 吴言片语
    • 吴言
    • 片语
    • 杂七杂八
  • 死于青春
    • 一路走好
  • 乌合麒麟
  • 纪念
    • 5.12
    • 3.23
  • GitHub
    • A List of Post-mortems
    • The Art of Command Line
  • 关于
    • Privacy Policy

程序员的信仰

金鳞岂是池中物,一遇风云便化龙

HOME » 技术生活 » Spring LDAP Transaction – Unofficial yet Working Config Manual

Spring LDAP Transaction – Unofficial yet Working Config Manual

2012 年 4 月 17 日 @ 上午 1:45 by Jay | 被踩了 11,016 脚

TOC

Toggle
  • Environment
  • Goal
  • IMPORTANT
  • Spring configuration

之前的一篇文章介绍了Spring的LDAP子项目和ODM框架,其中提到了LDAP事务,但没有深入,而且那个配置中的事务也是不work的。上个周末在和JTA斗智斗勇的同时把项目中的LDAP事务也搞定了,现在可以做到将LDAP和Hibernate的session factory放在同一个事务上下文中进行ACID管理,即LDAP和数据库操作实现“all or none”(虽然是伪事务,具体下文会提到)。当然,对于Spring LDAP事务配置官方和Google上同样没有任何可参考或操作的文档说明,不然我也不用连着两个晚上码字造福大众了。另外,为了造福资本主义国家的程序猿们,同时向他们展示社会主义国家的制度优越性,以下将切换至英文

Spring LDAP is a amazing framework esp. for its LdapTemplate and ODM, providing a consistent point of view of developing LDAP code with the well-known and document-friendly techniques – JdbcTemplate and ORM. Unfortunately, Spring LDAP is not that widely-used, for its sluggish development progress (1.3.1 so far) and lacking of document/samples. This post will focus on a even rare yet important topic of Spring LDAP – transaction. For other information like O-D mapping or LDAP context source, pls refer to the official document, and some tips here if you can read Chinese.

Environment

  • Spring LDAP 1.3.1
  • Spring * 3.1.1
  • Hibernate 4.1.1

Goal

  • Implement a method annotated with @Transactional, which demonstrates a business service
  • The service invokes two persist DAOs, one uses Hibernate’s session factory and the other uses Spring’s ODM
  • The two persist actions should follow “all or none” rule, that is, if JDBC action fails after LDAP action, LDAP action should rollback, vice versa

IMPORTANT

As described in the official document, TX in Spring LDAP is “not real”

it should be noted that the provided support is all client side. The wrapped transaction is not an XA transaction. No two-phase as such commit is performed, as the LDAP server will be unable to vote on its outcome. Once again, however, for the majority of cases the supplied support will be sufficient.

Show time!

Spring configuration

<bean id="contextSourceTarget" class="org.springframework.ldap.core.support.LdapContextSource">
	<property name="url" value="..." />
	<property name="base" value="dc=jayxu,dc=com" />
	<property name="userDn" value="cn=admin,dc=jayxu,dc=com" />
	<property name="password" value="..." />
</bean>

<bean id="pooledContextSource" class="org.springframework.ldap.pool.factory.PoolingContextSource">
	<property name="contextSource" ref="contextSourceTarget" />
	<property name="testOnBorrow" value="true" />
	<property name="dirContextValidator" ref="dirContextValidator" />
</bean>

<bean id="dirContextValidator" class="org.springframework.ldap.pool.validation.DefaultDirContextValidator" />

<bean class="org.springframework.ldap.core.LdapTemplate">
	<property name="contextSource" ref="contextSource" />
</bean>

<bean id="contextSource" class="org.springframework.ldap.transaction.compensating.manager.TransactionAwareContextSourceProxy">
	<constructor -arg ref="pooledContextSource" />
</bean>

<bean id="ldapTransactionManager" class="com.jayxu.common.ldap.ContextSourceAndHibernate4TransactionManager">
	<property name="contextSource" ref="contextSource" />
	<property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="odmManager" class="org.springframework.ldap.odm.core.impl.OdmManagerImplFactoryBean">
	<property name="contextSource" ref="contextSource" />
	<property name="managedClasses">
		<set>
			<value>...</value>
		</set>
	</property>
	...
</bean>

<bean class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
	<property name="transactionManager" ref="ldapTransactionManager" />
	<property name="target" ref="myService" />
	<property name="transactionAttributes">
		<props>
			<prop key="*">PROPAGATION_REQUIRES_NEW</prop>
		</props>
	</property>
</bean>
<bean id="myService" class="com.jayxu.service.MyService" />

<tx:annotation-driven />

This diagram gives a overview of the beans’ references

In your service class, you should annotate your transactional methods or the whole class with

@Transactional(value = "ldapTransactionManager")

here “value” refers to the tx manager name above. My test code looks like

@Transactional(value = "ldapTransactionManager")
public void ldapTx() {
	odm.create(...);
	sessionFactory.getCurrentSession().persist(...);

	throw new RuntimeException();
}

then config logger level of org.springframework.ldap and org.springframework.transaction to DEBUG, if everything works well, you can find something in the output like

[raw]
[DEBUG] org.springframework.ldap.transaction.compensating.LdapCompensatingTransactionOperationFactory:59 – Bind operation recorded
[DEBUG] org.springframework.ldap.transaction.compensating.BindOperationExecutor:97 – Performing bind operation
[DEBUG] org.springframework.transaction.support.TransactionSynchronizationManager:140 – Retrieved value [org.springframework.ldap.transaction.compensating.manager.DirContextHolder@3ed024df] for key [org.springframework.ldap.pool.factory.PoolingContextSource@165b3858] bound to thread [main]
[DEBUG] org.springframework.ldap.transaction.compensating.manager.TransactionAwareDirContextInvocationHandler:120 – Leaving transactional context open
[DEBUG] org.springframework.transaction.support.TransactionSynchronizationManager:140 – Retrieved value [org.springframework.orm.hibernate4.SessionHolder@55661f7b] for key [org.hibernate.internal.SessionFactoryImpl@7fb5438d] bound to thread [main]
[DEBUG] org.springframework.transaction.interceptor.TransactionInterceptor:406 – Completing transaction for [com.jayxu.service.UserLdapService.addUserTx] after exception: java.lang.RuntimeException
[DEBUG] org.springframework.transaction.interceptor.RuleBasedTransactionAttribute:130 – Applying rules to determine whether transaction should rollback on java.lang.RuntimeException
[DEBUG] org.springframework.transaction.interceptor.RuleBasedTransactionAttribute:147 – Winning rollback rule is: null
[DEBUG] org.springframework.transaction.interceptor.RuleBasedTransactionAttribute:152 – No relevant rollback rule found: applying default rules
[DEBUG] org.springframework.transaction.compensating.support.DefaultCompensatingTransactionOperationManager:79 – Performing rollback
[DEBUG] org.springframework.transaction.support.TransactionSynchronizationManager:331 – Clearing transaction synchronization
[DEBUG] org.springframework.transaction.support.TransactionSynchronizationManager:243 – Removed value [org.springframework.orm.hibernate4.SessionHolder@55661f7b] for key [org.hibernate.internal.SessionFactoryImpl@7fb5438d] from thread [main]
[DEBUG] org.springframework.transaction.support.TransactionSynchronizationManager:243 – Removed value [org.springframework.jdbc.datasource.ConnectionHolder@22013e9b] for key [org.springframework.jdbc.datasource.DriverManagerDataSource@c20e54a] from thread [main]
[DEBUG] org.springframework.transaction.compensating.support.AbstractCompensatingTransactionManagerDelegate:121 – Cleaning stored transaction synchronization
[DEBUG] org.springframework.transaction.support.TransactionSynchronizationManager:243 – Removed value [org.springframework.ldap.transaction.compensating.manager.DirContextHolder@3ed024df] for key [org.springframework.ldap.pool.factory.PoolingContextSource@165b3858] from thread [main]
[DEBUG] org.springframework.ldap.transaction.compensating.manager.ContextSourceTransactionManagerDelegate:103 – Closing target context
[/raw]

Line 1 indicates save point being created while line 10 indicates the rollback



-- EOF --
除非注明(如“转载”、“[zz]”等),本博文章皆为原创内容,转载时请注明: 「转载自程序员的信仰©」
本文链接地址:Spring LDAP Transaction – Unofficial yet Working Config Manual

分享

  • 点击分享到 Facebook (在新窗口中打开) Facebook
  • 点击以分享到 X(在新窗口中打开) X
  • 更多
  • 点击分享到Reddit(在新窗口中打开) Reddit
  • 点击分享到Telegram(在新窗口中打开) Telegram
  • 点击以在 Mastodon 上共享(在新窗口中打开) Mastodon

赞过:

赞 正在加载……

相关

Today on history:

【2006】又见好车
Posted in: 技术生活 Tagged: hibernate, jta, ldap, odm, spring, tips, transaction
← 走自己的路,让别人写博客去吧
珍爱生命,远离天朝论坛 →

android (9) apple (20) augmentum (9) Beijing (21) bt (8) career (28) coding (38) firefox (10) google (36) hibernate (11) ibm (11) iphone (10) java (93) linux (16) m$ (26) mac (58) macos (27) nazca (9) olympics (8) oo (8) playstation (10) rip (8) Shanghai (39) spring (9) tips (45) tommy emmanuel (8) ubuntu (12) usa (23) windows (9) 北航 (17) 博客 (29) 吐槽 (8) 周末 (9) 和谐社会 (26) 小资 (11) 愤青 (40) 方言 (10) 朋友 (77) 歌词 (8) 烟酒不分家 (18) 爱国 (19) 爱情 (8) 犯二 (15) 破解 (8) 足球 (11)

烫手山芋

  • 再谈苹果的输入法:这一次是靠OS X自带的输入法来翻身的~ - 被踩了 27,866 脚
  • 生活,就是一个期待跟着一个期待 - 被踩了 21,411 脚
  • 星巴克饮品缩写大全(Starbucks Drink ID Codes)[zz] - 被踩了 18,546 脚
  • 从一个全角冒号说一下我为什么不感冒iOS - 被踩了 14,494 脚
  • 有关Character.isLetter()和Character.isLetterOrDigit() - 被踩了 13,650 脚

刚拍的砖

  • leo 发表在《再谈苹果的输入法:这一次是靠OS X自带的输入法来翻身的~》
  • 花 发表在《再谈苹果的输入法:这一次是靠OS X自带的输入法来翻身的~》
  • 无名氏 发表在《从一个全角冒号说一下我为什么不感冒iOS》
  • Jay 发表在《Mac OS geek级问题》
  • Wei Wang 发表在《再谈苹果的输入法:这一次是靠OS X自带的输入法来翻身的~》

随便看看

  • Greek Letters – xkcd3 年 ago
  • 常用非标准库9 年 ago
  • 老四,六岁了 [zz]10 年 ago
  • Reasons Why People Who Work With Computers Seem to Have a Lot of Spare Time10 年 ago
  • Hyper Chord -Tommy Emmanuel 20099 年 ago

文以类聚

光阴似箭

其他操作

  • 登录
  • 条目 feed
  • 评论 feed
  • WordPress.org

Copyright © 2025 程序员的信仰.

Jay's Omega WordPress Theme by Jay

 

正在加载评论...
 

    %d