ibatis-user-java mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Clinton Begin <clinton.be...@gmail.com>
Subject Re: Some IBATIS Design Issues
Date Sat, 18 Dec 2004 16:57:03 GMT
Hi Dibyendu,

Thanks for your questions.

On DAO...

Before I get into any of the other topics, I'll say that your
requirements are likely too complex for iBATIS DAO (not SQL Maps). 
iBATIS DAO is a simple DAO implementation meant for 80% of the cases,
whereas you would seem to be in the 20%.  I recommend you use a custom
DAO framework with iBATIS SQL Maps.

On JTA transaction management...

If you look at the code for JtaTransaction in the SQL Maps framework,
you'll see that there is logic there that allows a transaction to be
externally managed by the "client".  Note the "newTransaction" field
of the JtaTransaction class.  That tracks whether iBATIS has started
the transaction, or if it was started externally.  iBATIS will ONLY
begin and commit/rollback if the client has NOT.  This allows iBATIS
code to be written in a consistent fashion, whether you're using JTA
or not.  If this logic doesn't work for you, then like Brandon said,
you have the option to use EXTERNAL.  Also, the TX management is a
pluggable component of iBATIS, so you should NEVER have to change any
of the core framework code.  You can write your own TX manager and
configure like any of the predefined ones.

On DataSource factories and JNDI...

JNDI is a standard for registration of managed resources.  I would
recommend you use it.  We could perhaps support DataSource factories
in the future, but I don't yet see any compelling reason why we would?
 If you're going to write a custom DataSource Factory, why not just
write a custom DataSource that proxies to the real DataSource
implementation?  Why does it have to be a factory?

These answers probably aren't what you were looking for, but I am not
yet able to see the problems you're describing, nor the need for the
solutions you've offered.

Best regards,

Clinton

On Fri, 17 Dec 2004 23:18:55 -0000, Dibyendu Majumdar
<dibyendu@mazumdar.demon.co.uk> wrote:
> Hi,
> 
> We have been looking to use IBATIS for our DAO layer, and have feedback on
> one or two design aspects. I will try to explain this as best I can - but it
> will probably take a few messages before I can get this across - so please
> bear with me.
> 
> Like many other folks, we are building an application framework that allows
> us to build our application in layers. Broadly speaking, we have:
> 
> Presentation layer based upon Struts - I will call this the Client tier.
> Application Logic (Business Logic) layer.
> Database Layer - this is where we are planning to use IBATIS.
> 
> We want the Client tier to know nothing about the DAO tier. Only the
> application tier knows about the DAO tier.
> 
> The reason I use the term "Client tier" is that, instead of the Presentation
> tier, a client may also be a command line program, or a Job run by a
> Scheduler.
> 
> The important thing for us is to ensure that the framework can work with or
> without a J2EE server.
> 
> We also want to be able to run distributed transactions across two or more
> databases - without making any changes to the application or DAO layer. The
> idea is that the DAO layer deals with JDBC connections - and does not know
> or care how the JDBC connections are obtained. A JDBC connection may be from
> an ordinary datasource or from an XA datasource - it should not matter to
> the DAO.
> 
> So far it must appear that there is no issue here - for IBATIS is designed
> to handle this requirement. However, this is not exactly the case.
> 
> We think that the problem in IBATIS is that it mixes the "Transaction"
> pattern and the "Connection" pattern into one single abstraction. A
> Transaction in IBATIS is not only a mechanism for committing data, but also
> for managing the Connection object.
> 
> Let me present a scenario that illustrates the kind of problem this creates.
> 
> Let us say that we have two DAO classes - A and B.
> We have configured our system so that A accesses a different database from
> B.
> 
> Now, we have two application level components - X and Y.
> X obtains an object of type A, whereas Y obtains and object of type B.
> A user of X or Y does not know that there are two databases involved. It is
> not even aware of how the DAO layer works.
> 
> Within X, we have code that looks like this:
> 
> DaoManager.startTransaction();
> A.dowork();
> DaoManager.commitTransaction();
> DaoManager.endTransaction();
> 
> The code for Y looks similar, but uses B.
> 
> From a Client tier - the code that invokes X and Y may look like this:
> 
> X x = new X;
> Y y = new Y;
> x.doWork();
> y.doWork();
> 
> So far the code looks similar to the JPetStore example - our X and Y classes
> are like the "Service" classes in JPetStore.
> 
> The problem starts if we do not want X and Y to commit or rollback - because
> we need the Client tier to decide when to commit or rollback. Remember that
> the Client tier knows nothing about the DAO layer. To commit therefore the
> Client tier must use a UserTransaction object like this:
> 
> UserTransaction ut = new UserTransaction();
> ut.begin();
> X x = get new X;
> Y y = get new Y;
> x.doWork();
> y.doWork();
> ut.commit;
> 
> But this won't work because IBATIS will attempt to commit inside
> DaoManager.commitTransaction().
> 
> We think that when a Global Transaction (JTA) is being used, IBATIS should
> only manage Connections and not attempt to perform transactions. The whole
> idea of JTA is that it is the "Client" that decides when to commit - the
> application tier cannot make that decision. Since all access to DaoManager
> is within the application tier - it follows from this that DaoManager must
> not attempt to manipulate a UserTransaction object.
> 
> IBATIS treats JTA and JDBC as separate mechanisms - but the fact is that
> even with JTA, JDBC Connections are used. Hence, from the DAO perspective,
> the code for DAO that uses JDBC looks the same as that which uses JTA.
> 
> We therefore think that this separation is incorrect - we only need one kind
> of DaoManager - a JDBC one. To support Global Transactions, all that is
> required is a flag that says - do not commit or rollback using the
> connection object - assume commits ae handled elsewhere.
> 
> We have worked around this problem by replacing the IBATIS transaction
> classes with our own. In the example configuration and classes I am
> attaching, you will see that the same DAO classes are switched from JDBC to
> JTA/XA without any change in the type of Transaction Manager.  Only the
> DataSource is changed, and a flag (globalCommit) is set.
> 
> The other change we have made is that we do not assume that a DataSource
> will be obtained from JNDI in a JTA environment - instead we use a Factory
> class which is responsible for creating a DataSource. The factory class may
> or may not obtain the datasource from JNDI.
> 
> I do not know if I have been able to explain the "problem" or the
> "solution". To summarise, what I am saying is:
> 
> a) IBATIS should not manipulate UserTransaction objects.
> b) The difference between JTA and JDBC is a spurious one - only one type is
> required. Only the type of DataSource needs to be changed to switch from one
> to the other, and some intelligence that switches "off" local
> commits/rollbacks. In our case, we use a flag called "globalCommit" - if set
> to "true" (in JTA mode), this means that the DAO layer must not commit or
> rollback.
> 
> You will also notice in the example that we use SqlMap in one DAO Context
> and plain JDBC in the other. For SqlMap implementation, we would have liked
> to push the DataSource/globalCommit settings from dao-config.xml - but
> IBATIS doesn't allow that. So we have had to setup these in the SqlMap
> config file.
> 
> I should like to hear your views.
> 
> Thanks and Regards
> 
> Dibyendu
> 
> 
>

Mime
View raw message