Discussions

EJB programming & troubleshooting: Transactional attribute issue with stateless bean...

  1. Transactional attribute issue with stateless bean... (10 messages)

    Let's say I have a stateless session bean with the following two methods:

    public void createGoal(){
      Connection c = datasource.getConnection()
      //do some work
      connection.executeUpdate();
      addObjectives();
    }
    public void addObjectives(){
      Connection c = datasource.getConnection()
      //do some work
      connection.executeUpdate()
    }

    So essentially, createGoal() calls addObjectives() once it finishes performing its jdbc work. This calling scheme represents a single transaction, so, if anything in addObjectives() fails, then all work performed in createGoal() must be rolled back. I'm not handling transactions explicitly because I want to use transactional attributes at the method-level to handle them for me. My question is this: If the transactional attribute for both methods is specified as REQUIRED, does addObjectives() become part of the transaction from createGoal() even though both methods are using different connection objects from the same data source?

    SAF

  2. Yes. If you don't want them in the same transaction, you should set the transaction type of addObjective to RequiresNew.
  3. That's actually what I dont want. Both methods must be part of the same transaction, so therefore using a transactional attribute of REQUIRES works fine. I'm concerned about the fact that since each method gets and uses a *different* connection from the same datasource. Will the EJB container be able to rollback the changes to the database made by createGoal() in the event that an exception is raised in addObjectives()? I guess the only way to find out is to test it!

    SAF
  4. I have a doubt on similar lines.

    Suppose, updates in addObjectives() depends on update done in createGoal() method. To make updates of createGoal() method visible to addObjectives() method, I have to pass the connection Object as parameter to addObjectives(Connection con) method from createGoal() method.

    This basically bloats the whole code.

    In my opinion, if two methods are in same transaction context, the container should return the same connection object even if we are calling datasource.getConnection() to get a new connection in different methods.

    Any pointers to the problem are welcome.

    Thanks
    Nishchit
  5. Hey Nishchit, I was thinking about passing a Connection object to addObjectives() myself, but I didn't want to expost a public method on the EJB that required a Connection argument because it doesn't seem correct to require the user to pass a Connection to an EJB! However, you can still use this approach by simply having a protected addObjectives(Connection) method and a public one, like this:

    public void createGoal(){
      Connection c = datasource.getConnection()
      //do some work
      connection.executeUpdate();
      addObjectives();
    }

    public void addObjectives(){
      addObjectives( null}
    }

    protected void addObjectives( Connection c){
      Connection connection = c
      if( connection == null)
        connection = datasource.getConnection()
      //do some work
      connection.executeUpdate()
    }

    Using this approach, you can hide the implementation details from the user of the EJB.

    This is another method, of course, but I still need to test all this out.

    SAF
      
  6. The probelm is if you use Entity Bean in createGoal() method like,

    public void createGoal(){
     // lookup entity home
     // home.create()
     addObjectives();
    }

    public void addObjectives(){
      Connection con = datasource.getConnection()
      // Is the record created above using home.create() visible here to this connection.

    }
    Is the newly created record visible inside addObjectives() method. Here you can't even pass a connection object to addObjectives() method becuase you don't have a reference of connection Object used by the container for the create call.

    Since, there are two different connection object involved in these two methods, I think the record created in first method is not yet visible in second method.That in turn forces me to use a SQL for first create and then pass that connection object reference to second method.


    That's why I feel the container should somehow use same connection object across one transaction context, even if it spans multiple method.

    -Nishchit
  7. I'm not using any Entity beans at the moment, but the concept is essentially the same because I'm inserting a row into the database from the createGoal() method that needs to be visible from the addObjectives() method.

    I'll find out if all this works in a few hours after I run my tests. I'll let you know as soon as possible.

    Thanks for all the great replies! This message board is usually not this active! ;-D

    SAF
  8. To Nishchit--
    It does not matter which connection you use as long as the connection is acuqired from the DataSource. In EJB, the transaction attributes are associated with bean methods, not with connections. What I am trying to say is, when you want to use a Connection object, just call DataSource.getConnection(). Of course, this applies only to container managed transactions.

    To SAF--
    No it's not an active forum. In fact there are only 3 persons in this thread :)

    I guess that you are trying to use only stateless session beans, including the persistence service, right? You will only have to get the connection from the DataSource. You do not need to pass the connection around. Get it, close it, get it again, and close it again. Do it as many times as you want, and all the requests will be in one transaction.

    That was what I did in the last project. What I did was just to propose an architecture to meet the requirements, and all the object oriented design are left to the SAs and SDs. That project ended up in a mess :) So if you need any opinion, I'd say, design, design, and design... You may solve techinical difficulties like this easily. However design is a totally different story. It really hurts to see how an fine architectural design to be wrecked with bad implementations...
  9. To Dright Ho -

    I know that transaction attributes are associated with bean methods.

    My question was, how should I see a updated or newly created record(but not committed) in another bean method if I am not passing connection object used for the update or creation. I am assuming that two bean methods are in same transaction context.

    If I do a datasource.getConnection() in another bean method, I will get a different connection object other than used for creation or updation and hence the updated record is not visible.

    I hope my question is much clearer now.

    Thanks
    Nishchit
  10. To Nischit
    <That's why I feel the container should somehow use same connection object across one transaction context, even if it spans multiple method.
    >>
    If addObjectives() fails then the entire transaction is rolled back.So the container does use a single transaction Context if the attribute is set to required(as it is associated to methods).

    To SAF
    I think you can not achieve this in a single transactional scope(ie to get updated data(createGoal ) in addObjectives())

    To Dright Ho -- One more USER added to thread :-)
    -----------------------------
    Feel free to comment.

  11. Surely tests will find out the answer. However I've tested it some time ago in WLS, and let me tell you the result.

    I used 2 Oracle8i database servers, and I tried to make a transaction across the 2 servers fail. The whole transaction got rolled back properly as I had guessed. I even tried a transaction across 2 WL Servers, each has a Oracle8i to serve the back-end store. It worked as well. After all, we call these application servers "transaction monitors", right? And that's what 2PC is for, isn't it?

    However I did not try a transaction across different database servers, for example Oracle and SQL Server. Maybe you'd like to try it.