You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by keithBacon <ke...@yahoo.com> on 2002/02/26 10:11:51 UTC

RE: Code To Update DB With Transactions (was RE: EJB = bad = MS.n et)

Hi James,
that's excellent & informative - thanks - Keith.

--- "Cakalic, James" <Ja...@heybridge.com> wrote:
> In short, I think the catch is that this style of dealing with transactions
> distributes knowledge and responsibility throughout the application, relying
> on a coding convention to implement a system policy. Better to encapsulate
> that policy so that it can be globally enforced.
> 
> An EJB container brings three benefits that immediately come to mind. First
> is that it provides that global implementation of transaction management.
> All calls to enterprise beans can be performed in the context of a
> transaction which the container ensures is either committed or rolledback as
> appropriate. Regardless of how convoluted the path might get through code
> contributed by any number of developers, the transaction management is
> applied globally and consistently. Second, the transaction management is
> declarative. I could write all day about it but it's one of those things
> that, until you've experienced it, you really don't appreciate it. Sort of
> like the first time you use a configurable logging package instead of
> System.out. Third, the container can bring resources beyond simply database
> connections into the scope of the transaction. For example, JMS-compliant
> messaging systems like MQSeries and SwiftMQ can now be incorporated in a
> transaction along with database activities.
> 
> Even if you don't use EJBs, I would think that you would want to seriously
> consider the encapsulation of your transaction management. For example,
> suppose you had something like this:
> 
> abstract public class TransactionalCommand implements Serializable {
>     protected Connection _conn;
>     public void setConnection(Connection conn) {
>         _conn = conn;
>     }
>     protected Connection getConnection() {
>         return _conn;
>     }
> 
>     abstract void performExecute() throws Exception;
>     abstract public boolean isReadyToExecute();
> 
>     public void execute() throws Exception {
>         if (isReadyToExecute() == false) {
>             // subclass determined not ready to execute
>             throw new Exception("Not ready to execute!");
>         }
>         new TransactionExecutive().executeCommand(this);
>     }
> }
> 
> public class TransactionExecutive {
>     public void executeCommand(TransactionalCommand cmd) throws Exception {
>         Connection conn = null;
>         try {
>             conn = DbUtils.getConnectionWithTransaction(...);
>             cmd.setConnection(conn);
>             cmd.execute();
>             DBUtils.commit(conn);
>         } catch (Exception e) {
>             // some command failure
>             DBUtils.backout(conn);
>             // maybe provide some global logging?
>             throw e;
>         } finally {
>             DBUtils.releaseConnection(conn);
>         }
>     }
> }
> 
> Then you could encapsulate your update logic like this:
> 
> public class AddUserCmd extends TransactionalCommand {
>     // could have setters for input properties
>     // could have getters for output properties
> 
>     public void performExecute() throws Exception {
>         DBUserValidator.saveToDb(getConnection());
>         DBAuthorisationValidator.saveToDb(getConnection());
>     }
> }
> 
> And you'd invoke it, perhaps even from your Action like this:
> 
>     AddUserCmd cmd = new AddUserCmd();
>     // some input parameters?
>     try {
>         cmd.execute();
>     } catch (Exception e) {
>         // something went wrong so handle it
>     }
> 
> Note that the "simpler" part is really the implementation of the AddUserCmd
> class and the usage pattern for executing the business logic. Now that
> you've encapsulated the transaction management within the
> TransactionExecutive and provided an infrastructure for wrapping your
> transaction business logic so that it can be handed in to the executive, you
> don't have to think about getting connections, commit and rollback, or
> disposing of connections. That code exists in one place providing a global
> policy implementation. You are now free to think about how to implement the
> business logic of what you are trying to accomplish without being distracted
> by the mechanics of low level details like transaction handling.
> 
> By the way, did you notice that TransactionalCommand implements
> Serializable? Now, if you wanted, you could serialize your commands, maybe
> queueing them for asynchronous or batched execution. Maybe you find that you
> _would_ like to distribute your system physically. Perhaps putting the web
> server on one system and the database on another. Perhaps, not saying
> definitely so, but perhaps there might be benefit then, performance,
> administrative, or otherwise, to having a separate process running on the
> database system that is the target for your commands. You could change the
> TransactionalCommand.execute method to say, open a socket to your server
> process and serialize the command to it. The server process could
> deserialize it and use the TransactionExecutive to execute the command. All
> without changing any of the rest of the implementation of your application.
> 
> This design is really quite similar to what my team is currently doing. But
> instead of our own command framework, we're using one provided by IBM with
> WebSphere. And instead of writing our own TransactionExecutive, we're using
> a stateless session bean with container managed transactions that catches
> exceptions and calls setRollbackOnly on the EJBContext so the container does
> the right thing. Of course, because the container also provides a connection
> pooling mechanism (DataSource) that is integrated with the transaction
> manager, we don't have to get a Connection and pass it around. Instead, we
> can ask the DataSource for a Connection from anywhere and it is
> automatically enlisted in the global transaction on our behalf. All requests
> for a Connection from the thread of execution that use the same connection
> parameters (userid and password) return the same actual database connection,
> thus reducing the number of physical resources being used without any
> additional programming effort on our part.
> 
> And in the end, for me, that's what it really is all about. I want to be
> robust, secure, reliable, performant, and scalable systems as rapidly as
> possible. It just so happens that using EJBs -- actually just one EJB -- and
> an EJB container solves a huge part of the equation for me. When a better
> solution comes along -- and I hope it leverages Java for all the positives
> that the language, environment, and community have to offer -- then I'll be
> there.
> 
> Best regards,
> Jim Cakalic
> 
> 
> 
> > -----Original Message-----
> > From: keithBacon [mailto:keithbaconstruts@yahoo.com]
> > Sent: Thursday, February 21, 2002 10:43 AM
> > To: Struts Users Mailing List
> > Subject: Code To Update DB With Transactions (was RE: EJB = bad =
> > MS.net)
> > 
> > 
> > Ah ha - I thought you'd imply that you only do it this way
> > if you are doing updates! Catch me out some other way!
> > There's got to be some other catch.......
> > Keith.
> > PS. No being frivolous on the list tomorrow
> >  - I'm not around to appreciate it!
> >  
> > --- "Galbreath, Mark" <Ga...@tessco.com> wrote:
> > > Yes.  If the query is a simple read, you don't need the 
> > transactions checks.
> > > 
> > > :-)
> > > 
> > > Mark
> > > 
> > > -----Original Message-----
> > > From: keithBacon [mailto:keithbaconstruts@yahoo.com]
> > > Sent: Thursday, February 21, 2002 9:54 AM
> > > 
> > > Is there anything wrong with the design below?
> > > Is there anything simpler? (Are EJB's simpler?).
> > > I typed this from memory from my last job. it was never really
> > > seriously tested but worked in practice with low volumes.
> > > 
> > > try {
> > >        // gets connection - ensures AutoCommit off & starts 
> > transaction.
> > >    Connection cnct DbUtils.getConnectionWithTransaction(..)
> > >    DBUserValidator.saveToDb(cnct);
> > >    DBAuthorisationValidator.saveToDb(cnct);
> > >    DbUtils.commit(cnct);
> > > } catch (Exception e) {
> > >    DbUtils.backout(cnct);
> > >    throw e;
> > > } finally {
> > >    DbUtils.releaseConnection(cnct);
> > > }      
> > > =======================
> > > cheers - Keith.
> > > 
> > > --- "Cakalic, James" <Ja...@heybridge.com> wrote:
> > > > Even if all the data is in a single physical RDBMS 
> > instance, your design
> > > has
> > > > to take one of several paths to deal with transactional issues.
> > 
> > 
> > =====
> > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > Search the archive:-
> > http://www.mail-archive.com/struts-user%40jakarta.apache.org/
> > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > Keith Bacon - Looking for struts work - South-East UK.
> > phone UK 07960 011275
> > 
> > __________________________________________________
> > Do You Yahoo!?
> > Yahoo! Sports - Coverage of the 2002 Olympic Games
> > http://sports.yahoo.com
> > 
> > --
> > To unsubscribe, e-mail:   
> > <ma...@jakarta.apache.org>
> > For additional commands, e-mail: 
> > <ma...@jakarta.apache.org>
> > 
> 


=====
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Search the archive:-
http://www.mail-archive.com/struts-user%40jakarta.apache.org/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Keith Bacon - Looking for struts work - South-East UK.
phone UK 07960 011275

__________________________________________________
Do You Yahoo!?
Yahoo! Sports - Coverage of the 2002 Olympic Games
http://sports.yahoo.com

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>