Announcement Announcement Module
Collapse
No announcement yet.
EJB tranaction to propage to LDAP Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • EJB tranaction to propage to LDAP

    Hi,
    I am using Spring LDAP transaction manager(org.springframework.ldap.transaction.compe nsating.manager.ContextSourceTransactionManager) to manager LDAP inserts and updates, this part is working as expected, if I try to insert duplicates in the same transactional insert, first insert is rolled back upon second failing.
    However I want LDAP transaction to participate in an EJB transaction. That is, these LDAP operations are invoked by a Stateless session bean with @TransactionAttribute(TransactionAttributeType.REQ UIRED), and I expected any failure in the EJB transaction to roll back the LDAP as well, but it is not to be. LDAP does not seem to hook into EJB transaction. Is this something that can be achieved provided that LDAP is non-XA?.
    Any ideas really appreciated!
    springldap.xml:
    Code:
    <bean id="contextSourceTarget" class="org.springframework.ldap.core.support.LdapContextSource">
          <property name="url" value="ldap://localhost:389" />
          <property name="base" value="dc=maxcrc,dc=com" />
          <property name="userDn" value="cn=Manager,dc=maxcrc,dc=com" />
          <property name="password" value="secret" />
       </bean>
    
       <bean id="contextSource" 
        class="org.springframework.ldap.transaction.compensating.manager.TransactionAwareContextSourceProxy">
          <constructor-arg ref="contextSourceTarget" />
       </bean>
       
       <bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
          <constructor-arg ref="contextSource" />
       </bean>
       
       <bean id="transactionManager" 
        class="org.springframework.ldap.transaction.compensating.manager.ContextSourceTransactionManager">
          <property name="contextSource" ref="contextSource" />
       </bean>
    
       <bean id="myDataAccessObjectTarget" class="model.LDAPContactDAO">
          <property name="ldapTemplate" ref="ldapTemplate" />
       </bean>
       
       <bean id="myDataAccessObject" 
                class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
          <property name="transactionManager" ref="transactionManager" />
          <property name="target" ref="myDataAccessObjectTarget" />
          <property name="transactionAttributes">
             <props>
                <prop key="*">PROPAGATION_REQUIRED</prop>
             </props>
          </property>
       </bean>
    
    EJB method
        @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
        public String getResult() {
            ApplicationContext ctx  = new FileSystemXmlApplicationContext("C:\\springldap.xml");
            ContactDAO dao = (ContactDAO)ctx.getBean("myDataAccessObject");
            dao.insertContact(new ContactDTO("User3","V2"));
            dao.insertContact(new ContactDTO("User3","V2"));
            return "OK";
        }
    If the duplication happens inside ContactDAOImpl.insertContact() ldap is properly rolled back
    Last edited by Chifer; Dec 8th, 2011, 06:22 AM.

  • #2
    Please use [ code][/code ] tags when posting code, that way it remains readable.

    You cannot have a non-XA resource participate in a distributed transaction. Next to that LDAP isn't even transactional, there is some trickery inside the ContextSourceTransactionManager to emulate transactions (the compensating part that is).

    Code:
    @TransactionAttribute(TransactionAttributeType.REQ UIRES_NEW)
    public String getResult() {
      ApplicationContext ctx = new FileSystemXmlApplicationContext("C:\\springldap.xm l");
      ContactDAO dao = (ContactDAO)ctx.getBean("myDataAccessObject");
      dao.insertContact(new ContactDTO("User3","V2"));
      dao.insertContact(new ContactDTO("User3","V2"));
      return "OK";
    }
    I really hope that this isn't production code. NEVER create an application context inside a method just for the purpose of getting a bean, UNLESS you want to have memory and performance issues.

    You might get something hacked together but for that you need spring to manage/drive your transactions and not your container.

    Comment


    • #3
      Hi

      Thanks for your explanation, this is what I suspected as well after reading few documents. I guess one way out of this would be to use
      Code:
      org.springframework.ldap.transaction.compensating.manager.ContextSourceAndDataSourceTransactionManager
      and tie the db and ldap transactions together. Unfortunately I don't have that liberty.

      Regarding, creating app context in EJB method, this is not production code,but test code written just to POC the LDAP transaction behavior.

      Comment

      Working...
      X