Announcement Announcement Module
Collapse
No announcement yet.
Launching multi-threaded job by JMS Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    My configuration:

    data-source-context.xml
    Code:
    	......
    	<bean id="wasTransactionManager" class="org.springframework.transaction.jta.WebSphereTransactionManagerFactoryBean" />
                   
    	<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">       
    		<property name="transactionManager" ref="wasTransactionManager" />
    		<property name="allowCustomIsolationLevels" value="true" />
    	</bean>
    	......
    simple-job-launcher-context.xml
    Code:
    	......
    	<aop:config>
    		<aop:advisor pointcut="execution(* org.springframework.batch.core..*Repository+.*(..))"
    			advice-ref="txAdvice" />
    	</aop:config>
    
    	<tx:advice id="txAdvice" transaction-manager="transactionManager">
    		<tx:attributes>
    			<tx:method name="create*" propagation="REQUIRES_NEW" isolation="SERIALIZABLE" />
    			<tx:method name="*" />
    		</tx:attributes>
    	</tx:advice>
    	......

    Comment


    • #17
      Originally posted by charmchuan View Post
      running the multi-threaded job (inner transaction) within outer transaction
      Can you elaborate on that a bit? It sounds fishy, but I don't really know what you mean. I don't see the "outer transaction" in your configuration below (or in the stack trace). What do you mean by that exactly?

      Can you run a unit test just from com.test.batch.sample.JobLauncherService.launchJob and check that it works from there on down? (Ditch the MDB, as I suggested originally.)

      Comment


      • #18
        What I mean 'outer transaction' is the J2EE container's transaction(UserTransaction), the following code will cause the same exception above, I am not using MDB in the following scenario:
        Originally posted by charmchuan View Post
        Also, I tried to retrieve the container's Transaction directly from the Web:
        Code:
            public void testMultiTreadsParallelJob() throws Exception{
                Context initContext = new InitialContext();
                UserTransaction tran = (UserTransaction) initContext.lookup("java:comp/UserTransaction");
        
                tran.begin();
                
                // Launch the multi-threaded job.
        
                tran.commit();
            }
        Then it threw the same exception too.

        So, my conclusion is : The transaction belongs to multi-threaded job can't be embedded in the application server's transaction. But why? Is there any conflict with application server's transaction.

        Comment


        • #19
          There certainly is a conflict and the error is easy to understand now. The outer transaction hasn't committed yet when the first step processing thread starts and tries to update the StepExecution.

          Your outer transaction will not commit until after the whole job is complete. This is unnecessary, and kind of an abuse of the UserTransaction - it could be held open for many hours. If you need a transaction for your trigger message you would be better off launching the job in a new thread (using a threaded task executor for the job launcher as well as the step), then the launcher will return immediately with an incomplete JobExecution and the transaction can commit and acknowledge the message back to the caller.

          Comment


          • #20
            Two points I don't understand:

            1. When I set propagation="REQUIRES_NEW", doesn't it mean that batch job will create its own transaction for managing itself and BATCH_% tables' data update?
            What my understanding is that it is seperated from outer transaction(UserTransaction). It suspends the outer transaction till it ends, manages its own transaction which is independent of the outer transaction no matter outer transaction commit() or rollback(), persists update of StepExecution without impact of outer transaction(e.g. outer rollback). Maybe what I think is not right, please correct me if so.

            2. It is strange that I could run the single threaded job in this scenario:
            Code:
                public void test() throws Exception{
                    Context initContext = new InitialContext();
                    UserTransaction tran = (UserTransaction) initContext.lookup("java:comp/UserTransaction");
            
                    tran.begin();
                    
                    // Launch the single threaded job.
            
                    tran.commit();
                }

            Comment


            • #21
              The propagation="REQUIRES_NEW" setting was only for the create* methods in the repository. And, no, you can't just set all the methods to REQUIRES_NEW and hope it will just work - the step implementations rely on the business transaction to co-ordinate with the meta-data transaction.

              The single threaded case works because you only ever have one transaction, so there is no chance that the updates to the step execution are not visible to the repository. For a long-running job this is going to be *really* expensive (especially on rollback).

              Comment

              Working...
              X