Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mule / Spring transaction is not propagated

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.

like image 275
Klapsa2503 Avatar asked Aug 08 '17 07:08

Klapsa2503


People also ask

What is propagation required in Spring transaction?

Propagation. REQUIRED is the default setting of a @Transactional annotation. The REQUIRED propagation can be interpreted as follows: If there is no existing physical transaction, then the Spring container will create one.

What is @transactional propagation propagation Requires_new?

REQUIRES_NEW. The main difference between them is if a method in Spring Business Activity/DAO class is annotated with Propagation. REQUIRES_NEW, then when the execution comes to this method, it will create a new transaction irrespective of the existing transaction whereas if the method is annotated with Propagation.

What type of transactions are supported by mule?

Mule supports three different types of transactions: single resource, multiple resource, and extended architecture (XA).


1 Answers

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!

like image 104
Manik Magar Avatar answered Sep 19 '22 09:09

Manik Magar