You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user-java@ibatis.apache.org by Dibyendu Majumdar <di...@mazumdar.demon.co.uk> on 2004/12/18 00:18:55 UTC

Some IBATIS Design Issues

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.

Re: Some IBATIS Design Issues

Posted by Brandon Goodin <br...@gmail.com>.
Hmmm, I'll have to defer this to Clinton. I have my ideas on what you
could do. But, I would hate to steer you in the wrong direction.

Brandon

On Sat, 18 Dec 2004 00:22:10 -0000, Dibyendu Majumdar
<di...@mazumdar.demon.co.uk> wrote:
> > Have you used EXTERNAL transaction management? This allows for you to
> > decide when to commit a transaction. It becomes your responsibility to
> > start, commit and end transactions. See Page 5 of the DAO Developer
> > Guide.
> 
> Yes, I have looked at EXTERNAL.
> 
> The SqlMap ExternalTransaction is similar to what I have done in
> SqlMapTransaction (when globalCommit = true). But the EXTERNAL type
> (ExternalDaoTransaction) in Dao framework is not the same as my
> GenericDaoTransaction - because my GenericDaoTransaction is a
> ConnectionDaoTransaction - ie, we still use a DataSource to manage
> connections - for example, we use the JDBC template to create DAO classes. I
> don't think that the EXTERNAL type (ExternalDaoTransaction) in DAO allows
> this.
> 
> Regards
> 
>

Re: Some IBATIS Design Issues

Posted by Dibyendu Majumdar <di...@mazumdar.demon.co.uk>.
> Have you used EXTERNAL transaction management? This allows for you to
> decide when to commit a transaction. It becomes your responsibility to
> start, commit and end transactions. See Page 5 of the DAO Developer
> Guide.

Yes, I have looked at EXTERNAL.

The SqlMap ExternalTransaction is similar to what I have done in
SqlMapTransaction (when globalCommit = true). But the EXTERNAL type
(ExternalDaoTransaction) in Dao framework is not the same as my
GenericDaoTransaction - because my GenericDaoTransaction is a
ConnectionDaoTransaction - ie, we still use a DataSource to manage
connections - for example, we use the JDBC template to create DAO classes. I
don't think that the EXTERNAL type (ExternalDaoTransaction) in DAO allows
this.

Regards



Re: Some IBATIS Design Issues

Posted by Brandon Goodin <br...@gmail.com>.
Have you used EXTERNAL transaction management? This allows for you to
decide when to commit a transaction. It becomes your responsibility to
start, commit and end transactions. See Page 5 of the DAO Developer
Guide.

Another option for more complex DAO management is the Spring framework.

Brandon


On Fri, 17 Dec 2004 23:18:55 -0000, Dibyendu Majumdar
<di...@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
> 
> 
>

Re: Some IBATIS Design Issues

Posted by Clinton Begin <cl...@gmail.com>.
One more thing:

To make you feel better, please understand that I'm not trying to say
that iBATIS DAO is a "perfect" or "the correct" design. There are a
lot of things I'd like to do differently the next time around. 
However, version 2.0 is not the place to make dramatic redefinitions
of the behavior or semantics of the current design.

Cheers,
Clinton

On Sun, 19 Dec 2004 00:22:33 -0700, Clinton Begin
<cl...@gmail.com> wrote:
> >> a) Modify EXTERNAL type in DAO to match the EXTERNAL type in SqlMap
> 
> DAO and SQL Maps are very different frameworks, with very different
> purposes. There is no reason that their behaviour should "match".  I
> think that by comparing these frameworks, you're getting confused.
> Don't try to draw parallels between them.
> 
> >> Also provide a DaoTemplate for EXTERNAL
> 
> The templates are intended to wrap an implementation specific
> transaction.  By its very definition, EXTERNAL doesn't have a known
> transaction implementation.  So a template for EXTERNAL doesn't make
> any sense at all.
> 
> >> EXTERNAL should manage connections as in JDBC type
> 
> No it shouldn't.  In the case of the DAO framework (which is a generic
> framework), EXTERNAL means that there is no known or controllable
> transaction manager at all, or its managed "externally".  In the case
> of SQL Maps (which is a JDBC framework), EXTERNAL simply means that
> you'll start and stop transactions yourself....but SQL Maps always
> needs a DataSource (hence the separate configurations).
> 
> 
> >> b) Make DataSource management in DAO framework
> >> factory based as it is in SqlMap
> 
> I don't see how this would help you.  The factory is not a public API
> in SQL Maps and it wouldnt' be in DAO either.
> 
> By definition, an iBATIS DAO implementation binds a transactional
> management facility (Connection, UserTransaction), with a persistence
> facility (SqlMaps, Hibernate, JDBC) and some persistent resource
> (database, flat file etc.).  Each DAO transaction manager
> implementation binds these three things together and allows them to be
> configured.  That's the design choice for iBATIS DAO, and it works for
> many people.  I often recommend that people with more complex
> requirements build their own.  In fact, *I* often build custom DAO
> implementations for clients instead of using iBATIS DAO.
> 
> Use it if it works for you.  If it doesn't, write your own.  It's
> usually only about 500 lines of code!
> 
> Cheers,
> Clinton
> 
> On Sat, 18 Dec 2004 23:28:59 -0000, Dibyendu Majumdar
> <di...@mazumdar.demon.co.uk> wrote:
> > Clinton,
> >
> > Thanks for the detailed response. I am still learning about IBATIS
> > everyday - the stuff I sent was my very first attempt to work around the
> > problems I was facing. However, I can already see that my workaround can be
> > simplified - eventually I will come down to the really essential bit - and
> > that would be my problem statement.
> >
> > > 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.
> >
> > I was actually working on my own DAO framework when I realised that IBATIS
> > DAO already had most of what I wanted - it was just a small bit that I
> > needed changing. Fortunately, due to the fact that the TransactionManager
> > can be changed, this worked for me.
> >
> > In particular, I like the following about the IBATIS DAO framework :
> > a) It is small and simple.
> > b) It allows association between DAO classes and a DataSource - which is
> > cool.
> > c) I like the fact that the interface between the caller of a DAO class and
> > the DAO class is so opaque - the caller does not need to know how the DAO
> > classes work or even obtain database connections - this is also cool.
> >
> > While I have a working solution, it bothers me that I am having to change
> > some default bevaiour - this could potentially cause future problems - for
> > example, if you decided to change the way the DAO framework interacts with
> > the TransactionManager. Ideally, I would like to use IBATIS as is, without
> > any changes.
> >
> > I have a question - why is the EXTERNAL type in DAO different from the
> > EXTERNAL type in SqlMap - ie why does the former lack Connection management?
> > A related question is - does anyone actually use the EXTERNAL type in DAO
> > framework?  Also, see my proposals below regarding this.
> >
> > > 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.
> > >
> >
> > I have noticed what you describe. Basically, IBATIS will only
> > commit/rollback a UserTransaction that it has begun itself.
> >
> > I still do not think that IBATIS should be touching UserTransaction objects.
> > Because the whole point of these is to allow the Client to manage
> > transactions. Do you have anyone actually using the JTA facility and relying
> > upon IBATIS to manage the UserTransaction objects?
> >
> > But, as you say, EXTERNAL type in SqlMap does what I want ... so I don't
> > need to worry about the JTA transaction manager in SqlMap. DAO is another
> > story (see below).
> >
> > > 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?
> >
> > I think that the problem I am facing is due to the difference between how
> > DAO handles data sources, and how SqlMap handles them. SqlMap seems to be
> > more generic - ie, the datasource factory can be one of the predefined ones
> > or user supplied. But in case of DAO, there seems to be some rigid rules -
> > example:
> >
> > JDBC can only use SIMPLE, DBCP or JNDI.
> > JTA can only use JNDI.
> > EXTERNAL does not support a DataSource at all.
> >
> > Why not make DAO behave the same as SqlMap - ie use a DataSourceFactory -
> > and let it be user customisable?
> >
> > -----
> >
> > Now for my revised proposals:
> >
> > a) Modify EXTERNAL type in DAO to match the EXTERNAL type in SqlMap - ie,
> > EXTERNAL should manage connections as in JDBC type, and provide a
> > DataSource, but commits and rollbacks should be no-ops. Also provide a
> > DaoTemplate for EXTERNAL type (although, JdbcDaoTemplate would also work
> > fine).
> >
> > b) Make DataSource management in DAO framework factory based as it is in
> > SqlMap - and let it be user customisable regardless of the transaction
> > manager type (as in SqlMap).
> >
> > Regards
> >
> > Dibyendu
> >
> >
>

Re: Some IBATIS Design Issues

Posted by Clinton Begin <cl...@gmail.com>.
>> a) Modify EXTERNAL type in DAO to match the EXTERNAL type in SqlMap 

DAO and SQL Maps are very different frameworks, with very different
purposes. There is no reason that their behaviour should "match".  I
think that by comparing these frameworks, you're getting confused. 
Don't try to draw parallels between them.

>> Also provide a DaoTemplate for EXTERNAL 

The templates are intended to wrap an implementation specific
transaction.  By its very definition, EXTERNAL doesn't have a known
transaction implementation.  So a template for EXTERNAL doesn't make
any sense at all.

>> EXTERNAL should manage connections as in JDBC type

No it shouldn't.  In the case of the DAO framework (which is a generic
framework), EXTERNAL means that there is no known or controllable
transaction manager at all, or its managed "externally".  In the case
of SQL Maps (which is a JDBC framework), EXTERNAL simply means that
you'll start and stop transactions yourself....but SQL Maps always
needs a DataSource (hence the separate configurations).


>> b) Make DataSource management in DAO framework 
>> factory based as it is in SqlMap 

I don't see how this would help you.  The factory is not a public API
in SQL Maps and it wouldnt' be in DAO either.

By definition, an iBATIS DAO implementation binds a transactional
management facility (Connection, UserTransaction), with a persistence
facility (SqlMaps, Hibernate, JDBC) and some persistent resource
(database, flat file etc.).  Each DAO transaction manager
implementation binds these three things together and allows them to be
configured.  That's the design choice for iBATIS DAO, and it works for
many people.  I often recommend that people with more complex
requirements build their own.  In fact, *I* often build custom DAO
implementations for clients instead of using iBATIS DAO.

Use it if it works for you.  If it doesn't, write your own.  It's
usually only about 500 lines of code!

Cheers,
Clinton


On Sat, 18 Dec 2004 23:28:59 -0000, Dibyendu Majumdar
<di...@mazumdar.demon.co.uk> wrote:
> Clinton,
> 
> Thanks for the detailed response. I am still learning about IBATIS
> everyday - the stuff I sent was my very first attempt to work around the
> problems I was facing. However, I can already see that my workaround can be
> simplified - eventually I will come down to the really essential bit - and
> that would be my problem statement.
> 
> > 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.
> 
> I was actually working on my own DAO framework when I realised that IBATIS
> DAO already had most of what I wanted - it was just a small bit that I
> needed changing. Fortunately, due to the fact that the TransactionManager
> can be changed, this worked for me.
> 
> In particular, I like the following about the IBATIS DAO framework :
> a) It is small and simple.
> b) It allows association between DAO classes and a DataSource - which is
> cool.
> c) I like the fact that the interface between the caller of a DAO class and
> the DAO class is so opaque - the caller does not need to know how the DAO
> classes work or even obtain database connections - this is also cool.
> 
> While I have a working solution, it bothers me that I am having to change
> some default bevaiour - this could potentially cause future problems - for
> example, if you decided to change the way the DAO framework interacts with
> the TransactionManager. Ideally, I would like to use IBATIS as is, without
> any changes.
> 
> I have a question - why is the EXTERNAL type in DAO different from the
> EXTERNAL type in SqlMap - ie why does the former lack Connection management?
> A related question is - does anyone actually use the EXTERNAL type in DAO
> framework?  Also, see my proposals below regarding this.
> 
> > 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.
> >
> 
> I have noticed what you describe. Basically, IBATIS will only
> commit/rollback a UserTransaction that it has begun itself.
> 
> I still do not think that IBATIS should be touching UserTransaction objects.
> Because the whole point of these is to allow the Client to manage
> transactions. Do you have anyone actually using the JTA facility and relying
> upon IBATIS to manage the UserTransaction objects?
> 
> But, as you say, EXTERNAL type in SqlMap does what I want ... so I don't
> need to worry about the JTA transaction manager in SqlMap. DAO is another
> story (see below).
> 
> > 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?
> 
> I think that the problem I am facing is due to the difference between how
> DAO handles data sources, and how SqlMap handles them. SqlMap seems to be
> more generic - ie, the datasource factory can be one of the predefined ones
> or user supplied. But in case of DAO, there seems to be some rigid rules -
> example:
> 
> JDBC can only use SIMPLE, DBCP or JNDI.
> JTA can only use JNDI.
> EXTERNAL does not support a DataSource at all.
> 
> Why not make DAO behave the same as SqlMap - ie use a DataSourceFactory -
> and let it be user customisable?
> 
> -----
> 
> Now for my revised proposals:
> 
> a) Modify EXTERNAL type in DAO to match the EXTERNAL type in SqlMap - ie,
> EXTERNAL should manage connections as in JDBC type, and provide a
> DataSource, but commits and rollbacks should be no-ops. Also provide a
> DaoTemplate for EXTERNAL type (although, JdbcDaoTemplate would also work
> fine).
> 
> b) Make DataSource management in DAO framework factory based as it is in
> SqlMap - and let it be user customisable regardless of the transaction
> manager type (as in SqlMap).
> 
> Regards
> 
> Dibyendu
> 
>

Re: Some IBATIS Design Issues

Posted by Dibyendu Majumdar <di...@mazumdar.demon.co.uk>.
Clinton,

Thanks for the detailed response. I am still learning about IBATIS
everyday - the stuff I sent was my very first attempt to work around the
problems I was facing. However, I can already see that my workaround can be
simplified - eventually I will come down to the really essential bit - and
that would be my problem statement.

> 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.

I was actually working on my own DAO framework when I realised that IBATIS
DAO already had most of what I wanted - it was just a small bit that I
needed changing. Fortunately, due to the fact that the TransactionManager
can be changed, this worked for me.

In particular, I like the following about the IBATIS DAO framework :
a) It is small and simple.
b) It allows association between DAO classes and a DataSource - which is
cool.
c) I like the fact that the interface between the caller of a DAO class and
the DAO class is so opaque - the caller does not need to know how the DAO
classes work or even obtain database connections - this is also cool.

While I have a working solution, it bothers me that I am having to change
some default bevaiour - this could potentially cause future problems - for
example, if you decided to change the way the DAO framework interacts with
the TransactionManager. Ideally, I would like to use IBATIS as is, without
any changes.

I have a question - why is the EXTERNAL type in DAO different from the
EXTERNAL type in SqlMap - ie why does the former lack Connection management?
A related question is - does anyone actually use the EXTERNAL type in DAO
framework?  Also, see my proposals below regarding this.

> 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.
>

I have noticed what you describe. Basically, IBATIS will only
commit/rollback a UserTransaction that it has begun itself.

I still do not think that IBATIS should be touching UserTransaction objects.
Because the whole point of these is to allow the Client to manage
transactions. Do you have anyone actually using the JTA facility and relying
upon IBATIS to manage the UserTransaction objects?

But, as you say, EXTERNAL type in SqlMap does what I want ... so I don't
need to worry about the JTA transaction manager in SqlMap. DAO is another
story (see below).

> 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?

I think that the problem I am facing is due to the difference between how
DAO handles data sources, and how SqlMap handles them. SqlMap seems to be
more generic - ie, the datasource factory can be one of the predefined ones
or user supplied. But in case of DAO, there seems to be some rigid rules -
example:

JDBC can only use SIMPLE, DBCP or JNDI.
JTA can only use JNDI.
EXTERNAL does not support a DataSource at all.

Why not make DAO behave the same as SqlMap - ie use a DataSourceFactory -
and let it be user customisable?

-----

Now for my revised proposals:

a) Modify EXTERNAL type in DAO to match the EXTERNAL type in SqlMap - ie,
EXTERNAL should manage connections as in JDBC type, and provide a
DataSource, but commits and rollbacks should be no-ops. Also provide a
DaoTemplate for EXTERNAL type (although, JdbcDaoTemplate would also work
fine).

b) Make DataSource management in DAO framework factory based as it is in
SqlMap - and let it be user customisable regardless of the transaction
manager type (as in SqlMap).

Regards

Dibyendu





Re: Some IBATIS Design Issues

Posted by Clinton Begin <cl...@gmail.com>.
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
<di...@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
> 
> 
>