10

I have a problem with database transactions in mule flow. This is the flow that i have defined:

<flow name="createPortinCaseServiceFlow">
    <vm:inbound-endpoint path="createPortinCase" exchange-pattern="request-response">
        <custom-transaction action="ALWAYS_BEGIN" factory-ref="muleTransactionFactory"/>
    </vm:inbound-endpoint>

    <component>
        <spring-object bean="checkIfExists"/>
    </component>
    <component>
        <spring-object bean="createNewOne"/>
    </component>

</flow>

The idea is that in checkIfExists we verify if some data exists (in the database) if it does we throw an exception. If it does not we go to createNewOne and create a new data.

The problem

is that if we run the flow concurrently new objects will be created multiple times in createNewOne and they should not be as we invoke checkIfExists just before it. This means that the transaction is not working properly.

More info:

both createNewOne and checkIfExists have following annotation:

@Transactional(propagation = Propagation.MANDATORY)

Definition of muleTransactionFactory looks as follows

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="dataSource" ref="teleportNpDataSource"/>
    <property name="entityManagerFactory" ref="npEntityManagerFactory"/>
    <property name="nestedTransactionAllowed" value="true"/>
    <property name="defaultTimeout" value="${teleport.np.tm.transactionTimeout}"/>
</bean>

<bean id="muleTransactionFactory" class="org.mule.module.spring.transaction.SpringTransactionFactory">
    <property name="manager" ref="transactionManager"/>
</bean>

I have set the TRACE log level (as @Shailendra suggested) and i have discovered that transaction is reused in all of the spring beans:

00:26:32.751 [pool-75-thread-1] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Participating in existing transaction

In the logs transaction is commited at the same time which means that those transactions are created properly but there are executed concurrently which causes an issue.

Community
  • 1
  • 1
Klapsa2503
  • 829
  • 10
  • 33

1 Answers1

4

Issue may be because multi-threading. When you post multiple objects to VM, they will be dispatched to multiple receiving threads and if multi-threading is not properly handled in your components then you might run into the issue you mentioned.

Test making these change - Add VM connector reference and turn off the dispatcher threading profile. That way, VM will process messages one at a time as there is just one dispatcher thread.

<vm:connector name="VM" validateConnections="true" doc:name="VM"    >
        <dispatcher-threading-profile doThreading="false"/>
    </vm:connector>
    <flow name="testFlow8">
        <vm:inbound-endpoint exchange-pattern="one-way"  doc:name="VM" connector-ref="VM">
            <custom-transaction action="NONE"/>
        </vm:inbound-endpoint>
    </flow>

Be aware of the fact that, if the number of incoming messages on VM are very high and time taken to process each message is more, then you may run into SEDA-QUEUE errors due to no thread availability.

If without threading, your flow is behaving correctly then you may need to look how your components should behave in multi-threading.

Hope That helps!

Manik Magar
  • 1,403
  • 2
  • 10
  • 20
  • This will not help because the problem is with transactions, not threads. If all the changes would be commited in single transaction, multiple threads would not cause an issue as transaction would make all the changes thread safe. Here the issue rather that each **spring-object** have different transaction and is not using the same one. – Klapsa2503 Aug 23 '17 at 19:43
  • I tried this but with no success, the issue still occurs event with that config. In the logs there are still many concurrent threads. – Klapsa2503 Aug 29 '17 at 23:08
  • Do you see your flow processing more than one record at a time? With transactions on inbound VM, flow should use synchronous strategy and the thread that received message should also process it. What are other threads? – Manik Magar Aug 30 '17 at 00:38
  • If there are more than one thread processing transaction , then it's worth looking into the transaction isolation you are using while interacting with database. Different transaction isolation have different semantics of when a transaction can view changes made by other. Maybe you need different isolation level depending upon the use of multithreading. – Shailendra Aug 30 '17 at 02:58
  • I send multiple messages at a time to the flow and those messages are processed asynchronously **pool-75-thread-2**, **pool-75-thread-4**. I need to check transaction isolation then. – Klapsa2503 Aug 30 '17 at 08:55
  • Does that happen even if you disable dispatcher threading? It should not. – Manik Magar Aug 30 '17 at 18:14