views:

222

answers:

3

usual idiom of using ibatis with spring support is following. Or this is how I'm doing it. please let me know if it can be done a better way?

beans xml:

<bean id="DataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="jdbc/some/som1/my/mydb"/>
</bean>
<bean id="SqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
  <property name="configLocation" value="classpath:sql-map-config-oracle.xml"/>
  <property name="dataSource" ref="DataSource"/>
</bean>
 <bean id="myDAO" class="com.reports.MyUserAccessDAO">
    <property name="sqlMapClient" ref="SqlMapClient"/>
    <property name="dataSource" ref="DataSource"/>
 </bean>

interface:

public interface MyUserAccessIface {
    public SomeBean getUserReports (String org);
}

DAO:

public class MyUserAccessDAO extends SqlMapClientDaoSupport implements MyUserAccessDAO {
    public SomeBean getUserReports (String org)
    {
      SomeBean bean = new SomeBean();
      //code for parameters goes here 
      getSqlMapClientTemplate().queryForList("namesp.userreport", parm);
      //fetch the result from parm and put them in SomeBean
      return bean
    }
}

calling the DAO:

MyUserAccessIface iBatisDAO = 
(MyUserAccessIface) ApplicationInitializer.getApplicationContext().getBean("myDAO");

even though this works fine I dont understand the need for an interface.

Questions

  • Can the interface be taken out of the picture and still have this working?
  • can the design/settings be changed so the call to the DAO is simply (even if that requires a base abstract class)

    MyUserAccessDAO mydao = new MyUserAccessDAO(); mydao.getUserReports("blah");

I've asked question along these lines couple days back but after struggling for 2 days and finding more things out I asked this question again now. If possible please provide code snippets of what you'd change/add.

Unit testing with this design does not work because everything is residing inside the container. If I get that working, then I will be adding that to the question as well (for information purpose).

Also, I think for someone trying to make spring + ibatis work...this would end up being a good place to start.

Edit:

Like I mentioned above that I would like to call my DAO like this (or i'm fine with passing something along as constructor parameter):

MyUserAccessDAO mydao = new MyUserAccessDAO(); mydao.getUserReports("blah");

To achieve above I would have following line in my DAO

setSqlMapClient((SqlMapClient)ApplicationInitializer.getApplicationContext().getBean("SqlMapClient"));

Still need to know what all to overwrite to be able to write test case for this. Test case wont be able to access anything inside the container so it will depend on Driver Datasource...

Since I am going against the best practice here...i dont mind changing my DAO exclusively just for the test case...

A: 

The interface is there to decouple you from depending directly on the implementation, which is, in general, good practice. It should all work fine without the interface, but it is better to depend on abstractions rather than implementations.

As for testing, well by using the interface, it becomes much easier to test the code using the DAO as you can just create a "mock" implementation of this that just returns dummy data and "inject" this manually in your unit test - your client code can't tell the difference between this and the real DAO as all it knows about is the interface.

alasdairg
say I dont have the interface. then how will testing work? I plan to do testing by simply calling mydao.getUserReports("blah). also, since testing will need for me to create my own datasource (outside of the container) how will that work?
Omnipresent
+2  A: 

Can the interface be taken out of the picture and still have this working?

Don't take the interface out. It's there for a good reason (e.g., proxy generation for transactions, AOP, mocks for testing in services, etc.)

Why do you want to take it out? What angst is it causing for you?

Can the design/settings be changed so the call to the DAO is simply (even if that requires a base abstract class)

Why are you calling "new"? If you're using Spring, you should be injecting this using the App Context. If you call "new", it's not under Spring's control. That should be the whole point.

duffymo
@duffymo I understand it goes against what spring preaches. I am changing the body of DAO methods so that they use iBatis as compared to JDBC code. I want to avoid changing everywhere where the DAO methods were called. This might not be good complete refactoring but at this time we dont have the liberty to scan through the code and see where the DAO was called and then change the way it was called. I hope that makes senseq
Omnipresent
That's what an interface would have bought you. If your clients were dealing with an interface, you could inject an iBatis or JDBC implementation as needed. Now you're stuck. I think a good IDE (e.g., IntelliJ) would make it easy to scan through and refactor your code in exactly this way. It could be worth a look before you abandon it because "you don't have the liberty."
duffymo
A: 

I can think of 1 major principle taking out the interface would break... 'object orientation' and most importantly, the inability to change method signatures without disrupting clients calling your code. That alone would stop me on my tracks. GOOD QUESTION THOUGH!! During many engagements, I am usually asked this question. Or simply people want to program to abstract classes. =)

Josh Molina