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>