Announcement Announcement Module
Collapse
No announcement yet.
Declarative transaction management Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Declarative transaction management

    Hi all,

    I'm using Spring 1.1.5 with Hibernate 2.1.8.

    I have a business service class that does two db calls and sends a mail. I have declared a transaction manager with declarative transaction management. I only want to send mail if both db calls are successfull, and I want to rollback the two db calls if sending of the mail fails.

    Bean declarations:
    Code:
    <bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
        <property name="transactionManager">
            <ref bean="hibernateTransactionManager" />
        </property>
        <property name="transactionAttributes">
            <props>
                <prop key="save*">PROPAGATION_REQUIRED</prop>
                <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
            </props>
        </property>
    </bean>
    
    <bean id="myServiceManager" parent="baseTransactionProxy">
        <property name="target">
            <bean id="myTarget" class="com.mycomp.myapp.service.impl.MyManagerImpl">
                <property name="dao1"><ref bean="dao1"/></property>
                <property name="dao2"><ref bean="dao2"/></property>
                <property name="mailSender"><ref bean="mailSender"/></property>
            </bean>
        </property>
    </bean>
    Java code:
    Code:
    public void saveData&#40;Data d&#41; &#123;
        dao1.save&#40;d.getSomething&#40;&#41;&#41;;
        logger.debug&#40;"dao1"&#41;;
        dao2.save&#40;d.getSomethingElse&#40;&#41;&#41;;
        logger.debug&#40;"dao2"&#41;;
        mailSender.send&#40;createMessage&#40;d&#41;&#41;;
        logger.debug&#40;"mail"&#41;;
    &#125;
    dao1 and dao2 are classes extending HibernateDaoSupport and use HibernateTemplate to save objects.

    This works as intended when the db calls are ok and mailsending fails, but mails are sent even if the db calls fail.

    I can see in my logs that all three calls in the saveData method is called even if the first one fails.

    - How can I make the transaction manager return from the method if the first call fails?
    - Is it possible with declarative transaction management, or do I need to look more into programmatic management?
    - Any tips to change my code to make this happen?

    Thanks in advance

    Trond

  • #2
    but mails are sent even if the db calls fail..Is it possible with declarative transaction management, or do I need to look more into programmatic management?
    Mail is generally not a transactional resource - so you'll hve to detect if the transaction is marked for rollback.

    Comment


    • #3
      Originally posted by katentim
      Mail is generally not a transactional resource - so you'll hve to detect if the transaction is marked for rollback.
      Anyone have an idea to how I might do this?

      Comment


      • #4
        You have to apply probably a programatic transaction demarcation and fire the email after the transaction has ended succesfully. Basically you'll send the email only if everything went okay because you can't roll back a sent email.
        You can for example put the emails into a pool of jobs for a scheduler (see Quartz) this way taking advantage of the asynchronous nature of messages in general.

        Comment


        • #5
          We store our outgoing mails in a database table as part of the transaction.
          A background task retrieves these mails one by one from the database,
          sends them and then deletes them from the database.

          Advantages:
          a) transactional: if something fails, everything is rolled back
          b) faster, main transaction does not wait for smtp server
          c) if background task can't send email (eg. smtp server down) the mail
          stays in the database, and sending is retried later

          Maarten

          Comment


          • #6
            Very good solution, I should write this down. What latenzy in email sending is added by the seperated worker threads?

            You have to apply probably a programatic transaction demarcation
            That is not always necessary. You can fetch the status of the current transaction (even if the transaction is declarative). But I would go for the programatic solution, too - just to avoid using an advice and to make things explicit.

            Comment

            Working...
            X