Announcement Announcement Module
Collapse
No announcement yet.
Question about transactions spanning across different components Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Question about transactions spanning across different components

    Hi,

    I have a question about Transactions in Spring integration.

    Let's assume the following case.


    <integrationublish-subscribe-channel id="exportChannel"
    task-executor="pool2"/>
    <task:executor id="pool2" pool-size="5"/>


    <!-- #######################EXPORT TRANSFORMER L########################################### -->
    <integration:chain input-channel="exportChannel" output-channel="transformedChannel">

    <integration:service-activator
    ref="exportService"
    method="process"/>

    <!-- #######################EXPORT TRANSFORMER L########################################### -->
    <integration:transformer ref="exportTransformer"
    method="transform"/>

    </integration:chain>

    ..................



    both method process and transform are mark as
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false, rollbackFor = Throwable.class)

    The object returned by method process is the parameter in the method transform.
    I need that object to be attached to persisten context/session (to avoid lazy loading exceptions in the method transform).
    I want to know if Spring integration creates internally a transaction when the message is dispatched asynchronously by the executor, therefore the transactions in both methods join the main one or on the other hand I need to define someting else in the application context.


    Cheers

  • #2
    Alvaro

    All you need is configure a MessagingGateway with TX configuration as you entry point to 'exportChannel'
    For example:
    Code:
    <int:gateway id="myGateway" service-interface="foo.bar.MyGateway" default-request-channel="exportChannel"/>
    and the actual interface:
    Code:
    public interface MyGateway {
           @Transactional(...)
           public TheReturnType foo(Object whatever);
    }
    then simply invoke the gateway method

    Here is more info:http://static.springsource.org/sprin...#gateway-proxy

    Comment


    • #3
      I have a gateway that sends a message to the channel exportChannel. This channel has a task executor that dispatches the message asynchronously (in other thread).
      can the TX be used in the other thread ?

      I am a bit confused.

      Comment


      • #4
        No.
        Spring transactions are bound to Thread Local. Could you please explain the use case, there might be a better solution.

        Comment


        • #5
          Well here is the configuration,


          <!-- ####################### START POINT - GATEWAY########################################### ########### -->
          <integration:gateway id="exportGateway"
          default-request-channel="exportChannel"
          service-interface="IExportFacade"/>


          <!-- #######################EXPORT CHANNEL########################################### -->
          <integrationublish-subscribe-channel id="exportChannel"
          datatype="java.lang.Integer"
          task-executor="pool2"/>
          <task:executor id="pool2" pool-size="5"/>


          <!-- #######################CHAIN ########################################### -->
          <integration:chain input-channel="exportOrderChannel" output-channel="transformedChannel">

          <!-- ####################### SERVICE ########################################### -->
          <integration:service-activator
          ref="exportService"
          method="findOrderById"/>


          <!-- ####################### TRANSFORMER ########################################### -->
          <integration:transformer ref="exportTransformer"
          method="transformToExternalOrder"/>

          </integration:chain>

          <!-- #######################DIRECT CHANNEL ########################################### -->
          <integration:channel id="transformedChannel"
          datatype="ExternalOrder"/>

          ..............

          We have a chain (dispatched in other thread by the executor) made up with
          1. Service activator finds and Order in a repository by Id.
          2. Transformer uses the Order loaded in the previous step to transform it to another data model.

          Bothe method are defined as follows:

          @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = true, rollbackFor = Throwable.class)
          public Order findOrderById(Integer OrderId)

          @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = true, rollbackFor = Throwable.class)
          public ExternalOrder transformToExternalOrder(Order order)

          If the transformer executes transformToExternalOrder in a transaction different form the transaction used in findOrderById then I will have Lazy loading exceptions as soon as I start get information from relationships, because the object is detached.
          I should be forced to do a merge to load the Order again.

          I dont know if Spring integration has a way to create a transaction in the new Thread therefore both methods declared as REQUIRED will join this one so I will not have lazy loading exception.

          Regards

          I hope to be more concrete.

          Comment


          • #6
            Spring Integration delegates to Spring Transaction support. We are not doing anything extra, so perhaps you can get more info here http://static.springsource.org/sprin...ansaction.html
            I guess the question I have is based on the concept of Transaction in general as a 'single unit of work' but in your case you are splitting it in multiple independent units thus multiple independent transctions. Is there a reason why two processes needs to happen concurrently? I mean what would you expect to happen if Thread 1 fails while Thread 2 still running?

            Comment


            • #7
              Hi Oleg,

              I get your point but in my case I have a new Thread where I execute two independent tasks sequentially and for that reason I thought that maybe I could join both to the same transaction.
              Whatever happens in other Threads, I dont care.

              I guess that I will have to apply a template method with two steps and bound both to the same transaction instead of having two independent components.

              Tx for everything.

              Cheers.

              Comment


              • #8
                If the two tasks are executing *sequentially* then they can be part of the same transaction that is initiated by a <gateway>. Everything downstream from that gateway will be in that transaction as long as the thread boundary is not broken from that point onward. As long as the gateway follows that publish-subscribe-channel where the task executor does delegate to a thread, everything should work as intended.

                Hope that helps.
                -Mark

                Comment


                • #9
                  Hi Mark,

                  Tx so much, I really appreciate your explanation.

                  Dont you think that it could be interesting to have some kind of mechanism that creates a new transaction for each thread created by a task executor linked with a pub sub channel?. In such case we could have in the same thread different spring integration components that can join that transaction.
                  Make that sense to you?

                  Cheers

                  Alvaro

                  Comment

                  Working...
                  X