4

Using Ejb3.0, Weblogic 11g, JDBC

I am invoking a method which is running remotely in another deployment EAR.

The method in the remote deployment being invoked but it's annotated with the @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)

the problem is that all the logic I do in the database before the remote method is being invoked wont commit till the remote method finished.

What I willing to do is a commit to let the "before" logic take place" and when I get back after the remote call to continue normally.

Any idea?

Some code to explain:

@CallByReference
@Stateless(mappedName = "ejb/OperatorProccessBean")
@Local({ OperatorProccessBeanLocal.class })
@Remote({ OperatorProccessBeanRemote.class })
public class OperatorProccessBean implements OperatorProccessBeanLocal,  
 OperatorProccessBeanRemote
{   

...

   SBNDispatchBeanRemote SBNDispatchBean = (SBNDispatchBeanRemote) context.lookup("ejb/SBNDispatchBean#com.mirs.sbn.dispatch.SBNDispatchBeanRemote");
    if (SBNDispatchBean == null)
    {
            logger.error(TAG + " SBNDispatchBean is null");

    }
    else
    {
         //until here I want all my data to be commited without waiting for the upcoming remote method to finish
         SBNDispatchBean.updateSubscriberInBlockingList(...);
    }
...
 }

Now the method updateSubscriberInBlockingList() is annotated with

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)

i want the data to be commited before that method being invoked.

Thanks in advance, ray.

oliholz
  • 7,447
  • 2
  • 43
  • 82
rayman
  • 20,786
  • 45
  • 148
  • 246

2 Answers2

3

Now the method updateSubscriberInBlockingList() is annotated with @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)

I want the data to be commited before that method being invoked.

Given that you are using container managed transactions, it is not possible. The rationale behind this, is that when the container is already performing a transaction, then starting a new transaction will result in the original being suspended. When the new transaction has committed, the original transaction will be resumed.

This behavior is not configurable, for the EJB container and the JTA Transaction Manager is expected adhere to the behavior specified in the JTA specification, which is derived from X/Open DTP transaction model. In the X/Open DTP model, if there is a new transaction is started, while another is in progress, the current one is suspended, and resumed at a later point in time. It should be noted that no transaction model, would possibly (I haven't studied all) allow for committing the current transaction and starting a new one. I have only seen nested transactions or suspended transactions being supported in the various transaction processing models.

If you want to have the work committed, you must have the existing transaction context terminated completely, so that the existing transaction will commit, and then start the new transaction.

Community
  • 1
  • 1
Vineet Reynolds
  • 76,006
  • 17
  • 150
  • 174
  • "If you want to have the work committed, you must have the existing transaction context terminated completely," how u do that? – rayman Jun 14 '11 at 12:44
  • You must call the `updateSubscriberInBlockingList` method only after the current transactional method has finished execution. Transactions are always associated with threads. If a JTA Transaction Manager (TM) finds that a transaction is associated with a thread, it will suspend the existing one, and start the new transaction. You must therefore not have a transaction associated with the current thread if you need to achieve that. – Vineet Reynolds Jun 14 '11 at 12:51
  • Yes.. but the problem that I must perform this method ()updateSubscriberInBlockingList) and only after it finish to continune with my code. how will I finish the current transactional method execution? – rayman Jun 14 '11 at 12:56
  • The short answer given that requirement is that you can't. The long answer is what I've stated above. X/Open DTP, JTA, JTS and the EJB will simply not allow for that programming model. Besides, why would suspension of transactions cause any problem in this case? – Vineet Reynolds Jun 14 '11 at 13:00
  • Coz I had case when the second transaction did lots of rollbacks and got transaction-timeout and commit wasnt performed. that leaded the calling transaction not to do "commit" . and I guess it's coz the "child" transaction didnt commit. – rayman Jun 14 '11 at 13:16
  • There's no concept of a child transaction in JTA, in other words, no nested transaction support exists. You would find it extremely useful to enable debugging of JTA to see how the transaction timeout is calculated for the original suspended transaction. My feeling is that the timeout will occur even if the transaction is suspended, which is the error that you are seeing. If that is the case, attempt to optimize the execution of the second transaction. – Vineet Reynolds Jun 14 '11 at 13:19
  • What do you think about the second answer from JB Nizet. if I will devide my logic to 3 transactions that will solve it? – rayman Jun 14 '11 at 13:23
  • I haven't understood how there would be three transactions. I would assume that there would be two - the one that the client invoked where you are doing the work, and the one that is required for `updateSubscriberInBlockingList`, which has to be called by the client (for the JTA TM would commit the first txn only after exiting the current method in OperatorProccessBean). It is essentially the same thing as what I've stated in the second comment. – Vineet Reynolds Jun 14 '11 at 13:27
  • Unless you want to do Bean Managed Transactions, there is no way you can commit the work done before invoking `updateSubscriberInBlockingList`. – Vineet Reynolds Jun 14 '11 at 13:28
  • Well, glad to be of help. In the future, you could refer [Java Transaction Design Strategies](http://www.infoq.com/minibooks/JTDS). Found the book to be useful. – Vineet Reynolds Jun 14 '11 at 13:52
1

Put the "before remote call" logic in a separate bean method annotated with REQUIRES_NEW as well. You will thus have three transactions :

  • one for the main method (but which won't do anything until th remote call is done);
  • one for the logic before the remote call;
  • one for the remote call.
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255