• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Ron McLeod
  • paul wheaton
  • Jeanne Boyarsky
Sheriffs:
  • Paul Clapham
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
  • Himai Minh
Bartenders:

Stateless Session Beans Managing JDBC Transactions

 
Author
Posts: 39
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
We have several DAO objects that access our database. Each DAO performs reads/updates on a single table or small group of tables.

The application, depending on the particular business function being performed, uses various combinations of these DAOs to complete tasks. Because of this, it is important that we use transactions so that if an error occurs in a DAO, the work done by any previous DAOs in the transaction are rolled back.

Since the DAOs can be reused in various combinations, we're wondering may be the best way to manage the transactions. One option is to have a custom TransactionManager class that is passed to every DAO in a transaction. This TransactionManager class would provide the same Connection to each DAO, so that if something goes wrong, calling a rollback will rollback everything else that has been done. This approach is more work, as the custom TransactionManager class has to be maintained, and some sort of controller class has to create/coordinate the TransactionManager for all DAOs within a transaction.

Another option might be to use a stateless session bean and then use container managed transactions. For example, a session bean could have a doThis() method that calls three DAOs. The doThis() method would have a transaction attribute of Required, so that a new transaction is started if one doesn't exist but an existing one is used if it already exists. This way, each DAO can just get its own Connection using our custom connection factory, without having to rely on something that was passed in.

My question: Is this possible and will it work?

My concern is that if each DAO withing the transaction retrieves is own connection from the connection pool, will the container still be able to rollback the work done by two DAOs if, for example, an error occurs in the third DAO in a transaction? If not, what would I need to do to make it work?

I'm just not sure of how much "magic" the container can actually do behind-the-scenes.

Another question while I'm on the subject: What types of errors will cause a container managed transaction to rollback? If it must be some sort of system exception, what types of system exceptions will force the rollback? Can I subclass a certain type of Exception and throw that and still count on the transaction being rolled back?

Thanks!
 
Ranch Hand
Posts: 704
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Ryan,

Nice posting though. Sometimes people have a very specific way of asking questions that might take me an entire day and several posting in order to figure out the actual question :-)


Another option might be to use a stateless session bean and then use container managed transactions. For example, a session bean could have a doThis() method that calls three DAOs. The doThis() method would have a transaction attribute of Required, so that a new transaction is started if one doesn't exist but an existing one is used if it already exists. This way, each DAO can just get its own Connection using our custom connection factory, without having to rely on something that was passed in.

My question: Is this possible and will it work?


Absolutely; I�m pretty sure that most of the j2ee applications that use EJBs and DAO pattern, manage transaction using CMT (the container will provide you the best TransactionManager. No need to reinvent the wheel in this case).


My concern is that if each DAO withing the transaction retrieves is own connection from the connection pool, will the container still be able to rollback the work done by two DAOs if, for example, an error occurs in the third DAO in a transaction? If not, what would I need to do to make it work?


It will certainly do so. Moreover some containers will probably not return the connection to the pool before the transaction commits. Hence all your DAO will use the same connection. However the implementation the transaction integrity is guaranteed by the container.


I'm just not sure of how much "magic" the container can actually do behind-the-scenes.


The container will use the JTS/JTA api to implement the transaction management, which you�ll probably end up doing yourself if you decide to implement a TransactionManager (another option would be to use the JDBC transactions, which will leverage the entire transaction management at the database level). Besides it assures transaction propagation and can provide also support for global (remote) transactions using the 2PC protocol.


Another question while I'm on the subject: What types of errors will cause a container managed transaction to rollback? If it must be some sort of system exception, what types of system exceptions will force the rollback? Can I subclass a certain type of Exception and throw that and still count on the transaction being rolled back?


The container will rollback the transaction only when RuntimeExceptions are thrown (the container logs the error, discharges the bean instance and rolls back the transaction). In my opinion however, good design practice should enforce business methods to always throw application (checked) exceptions. Because the good practice and EJB specs (regarding transactions rollback) are quite opposite, j2ee come up with a way to overcome the issue. Hence you can use the EJBContext.setRollbackOnly() method to mark the transaction for rollback and throw an application exception instead.
Regards.
 
Ranch Hand
Posts: 1683
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Another option might be to use a stateless session bean and then use container managed transactions. For example, a session bean could have a doThis() method that calls three DAOs. The doThis() method would have a transaction attribute of Required, so that a new transaction is started if one doesn't exist but an existing one is used if it already exists. This way, each DAO can just get its own Connection using our custom connection factory, without having to rely on something that was passed in.

My question: Is this possible and will it work?


Yes, this is the best approach. One of the best features of EJBs is container-managed transactions.

My concern is that if each DAO withing the transaction retrieves is own connection from the connection pool, will the container still be able to rollback the work done by two DAOs if, for example, an error occurs in the third DAO in a transaction? If not, what would I need to do to make it work?

I'm just not sure of how much "magic" the container can actually do behind-the-scenes.


This is all part of the magic done by the EJB container! The rollback is done automatically in certain circumastances. The Connection has nothing to do with rollback as far as the Bean Provider is concerned.

Another question while I'm on the subject: What types of errors will cause a container managed transaction to rollback? If it must be some sort of system exception, what types of system exceptions will force the rollback? Can I subclass a certain type of Exception and throw that and still count on the transaction being rolled back?



Rollback is assured if your bean throws RuntimeException or any of its subclasses. This might be something unintentional like ArithmeticException or something intentional, ie you throw EJBException (which is often used to wrap low-level exceptions such as SQLException).

Or you can explicitly cause rollback by invoking setRollbackOnly (declared in EJBContext). This is often done where an application exception is thrown but you don't want the transaction to be committed by the container. So, you invoke setRollbackOnly and then throw the application exception.
 
Roger Chung-Wee
Ranch Hand
Posts: 1683
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

In my opinion however, good design practice should enforce business methods to always throw application (checked) exceptions.


So, presumably this means throwing system exceptions wrapped in a custom application exception. What happens at the client? For instance, would a business delegate inspect the root exception and decide whether to pass the exception to the client or to something which generates a system error page?
 
Valentin Tanase
Ranch Hand
Posts: 704
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Roger,


So, presumably this means throwing system exceptions wrapped in a custom application exception. What happens at the client? For instance, would a business delegate inspect the root exception and decide whether to pass the exception to the client or to something which generates a system error page?


System exceptions could be categorized as checked or unchecked exceptions and usually clients have no way to recover from such failures. It makes a lot of sense to catch the checked system exceptions and throw them as unchecked exceptions, eventually wrapping them within an EJBException. The point I tried to make is that the way the ejbs handles exceptions is little bit less intuitive: our intuition would tell us to always throw checked exceptions within the business methods, while ejbs says: that�s your business buddy, but don�t forget to rollback the transaction first... As for me, if you want me to rollback the transaction for you, then forget about other good practices and better throw an unchecked exception. I could never take this so easy :-)
Regards.
 
Ranch Hand
Posts: 318
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Ryan Asleson wrote: This way, each DAO can just get its own Connection using our custom connection factory, without having to rely on something that was passed in.



If you use datasources, jee server would "know" and manage transactions for you

if you use DriverManager api, the container wont know that you are creating a connection and it wont enlist/manage those connections

something lot of people forget and run into trouble
 
Don't get me started about those stupid light bulbs.
reply
    Bookmark Topic Watch Topic
  • New Topic