More about Groovy SQL Maps

myndian.de

Samstag, 22. Dezember 2007

More about Groovy SQL Maps

A week ago I posted about a GroovyIBatisDao. Here I like to tell you about a few details as I announced.


First I added Support for SQL Map namespaces which are mandatory in our architecture. To avoid to much configuration I used a naming convention: For example a DAO for ProjectModules will be named “projectModuleDao” (the bean, not the class). The namespace for the SQL Map Statements would be “ProjectModule”. So a qualified statement could be “ProjectModule.findById”.


So I implemented the interface BeanNameAware and overrode initDao() to set the default namespace from the beanName:

class GroovyIBatisDao
    extends SqlMapClientDaoSupport
    implements BeanNameAware
{
  
  def String beanName
  
  def String namespace

  // ...
  
  @Override
  void initDao()
  {
    if(!namespace)
      namespace = capitalise(substringBefore(beanName, “Dao”))
  }

  // ...
}

Nothing very exciting, but with use of an abstract bean configuration the needed configuration is as short as possible:

<bean name=“projectModuleDao” parent=“abstractDao” />

I think this is really nice! You just need an abstract bean configuration. Which I placed into a base configuration file for the database together with the sqlMapClient, the datasource, etc. That is to keep the configuration file with the concrete DAOs clean, so it show the intended architecture an not to much details. The Spring configuration files are the first thing to look at if you really want to know about the architecture and there is no documentation (as usual ;-) ).

<bean name=“abstractDao” abstract=“true”
  class=“....GroovyIBatisDao”
  p:sql-map-client-ref=“sqlMapClient” />

By the way: The expression capitalise(substringBefore(beanName, “Dao”)) does not work in “Eclipse Groovy”, because the plugin does not yet support static imports. :-( (The methods are from org.apache.commons.lang.StringUtils.)


The second change is that the new method methodMissing is now implemented instead of invokeMethod. The first one is new in Groovy 1.5 and is called when a method is called that not exist. Whereas invokeMethod is called every time a method is called. Instead of calling the correct method of SqlMapClientTemplate directly, the implementation of methodMissing wraps the correct call in a closure and saves it as a property of the DAO objects MetaClass under the name of the missing method. Then it calls the property on the object itself like a method. Because the value is a closure, it also acts like a method.


Object methodMissing(String methodName, Object arguments)
{
  def useMethod = methodMapping.find{ methodName.startsWith it.key }?.value

  if(!useMethod)
    throw new MissingMethodException(methodName, DynamicSqlMapDao, arguments)
    
  metaClass.“${methodName}” = { arg ->
      sqlMapClientTemplate.“${useMethod}”(“${namespace}.${methodName}”, arg)
  }
  
  this.“${methodName}”(arguments[0])
}

All this using the Groovy Style Reflection. :-) The implementation also uses the namespace. The main advantage is that the method is not missing after the first call. It really exists and call be called by the clients. So the overhead of methodMissing is executed once per method. Note also the MissingMethodException which is thrown if we can not implement the method dynamically. So the developers of the clients get the right information in case of a failure.


But to do all this we have to do change the MetaClass. The default MetaClass can not be expanded that way. So we have to use the ExpandoMetaClass. I do not know how to use it properly without using Expando. But the following code of the constructor works just fine:


DynamicSqlMapDao()
{
  metaClass = new ExpandoMetaClass(DynamicSqlMapDao, true, true)
  metaClass.initialize()
}

The flags are indicating that we can add properties and methods after initializing. Documentation says that an dynamically added property could be removed because of garbage collection. That’s no problem in our case, because methodMissing would add it again when needed. Maybe I should have a look at the source code of Expando to know how to use ExpandoMetaClass correct. :-) An interesting aspect is that the method is really added to the instance and not to all DAOs. This should not be a problem with the current closure, but I added an unit test as a precaution.


// Java, not Groovy
@Test
public void addFind()
{
  String methodName = “findPersonByName”;
  String methodArg = “Anna”;

  testDao.methodMissing(methodName, new Object[]{methodArg});

  assertNotEmpty(testDao.getMetaClass().respondsTo(testDao, methodName));
  assertEmpty(otherDao.getMetaClass().respondsTo(otherDao, methodName));
}

Remembering the above mentioned expression capitalise(substringBefore(beanName, “Dao”))? If we would manipulate the MetaClass of String as Groovy does, we could also write it in real OO Style: beanName.substringBefore(“Dao”).capitalise(). But we have no agreement yet about extending existing classes, especially those of the JDK.


At last there is also a ‘feature’ which was removed: I made the methodMapping private. I have done this because it is implementation dependent at the moment. “findAll” had to be before “find” for example, otherwise each findAll methods would be executed as find method. We also agreed not to add more features at the moment, because we use other methods of SqlMapClientTemplate very rare.

Geschrieben von Jörg in Softwaretechnik um 15:33 | Kommentare (0) | Trackbacks (0)
Tags für diesen Artikel: dynamic typing, groovy, ibatis, java, sql maps, test
Artikel mit ähnlichen Themen:
  • Grails tutorials and a free e-book
  • Runnig Grails
  • Premature optimization and object orientation
  • POJOs, POGOs und POCOs
  • View technologys for generated web layers
  • Make your SQL Maps Groovy!
  • Groovy again
  • last language war language trolling
  • Dynamic two dimensional array in Java
  • static vs. dynamic typed configuration

Trackbacks
Trackback für spezifische URI dieses Eintrags

Keine Trackbacks

Kommentare
Ansicht der Kommentare: (Linear | Verschachtelt)

Noch keine Kommentare

Kommentar schreiben

Umschließende Sterne heben ein Wort hervor (*wort*), per _wort_ kann ein Wort unterstrichen werden.
Standard-Text Smilies wie :-) und ;-) werden zu Bildern konvertiert.
Die angegebene E-Mail-Adresse wird nicht dargestellt, sondern nur für eventuelle Benachrichtigungen verwendet.

Um maschinelle und automatische Übertragung von Spamkommentaren zu verhindern, bitte die Zeichenfolge im dargestellten Bild in der Eingabemaske eintragen. Nur wenn die Zeichenfolge richtig eingegeben wurde, kann der Kommentar angenommen werden. Bitte beachten Sie, dass Ihr Browser Cookies unterstützen muss um dieses Verfahren anzuwenden.
CAPTCHA

Sie können [geshi lang=LANG][/lang] Tags verwenden um Quellcode abhängig von der gewählten Programmiersprache einzubinden
 
 

Suche

Inhalt

Startseite
Galerien
Impressum

Kategorien

  • XML Alltag
  • XML Internet
  • XML Musik
  • XML Politik
  • XML Softwaretechnik
  • XML Sonstiges
  • XML Visuelles

Alle Kategorien

Archive

September 2010
August 2010
Juli 2010
Das Neueste ...
Älteres ...

Blog abonnieren

XML RSS 2.0 feed
ATOM/XML ATOM 1.0 feed
XML RSS 2.0 Kommentare

Login

Verwaltung des Blogs

Login

Aktuelle Einträge

Netzwerkkultur verändert die Gesellschaft
Dienstag, 17. November

Absolute and relative date and time
Sonntag, 18. Oktober

Oren Lavie - Her Morning Elegance
Dienstag, 6. Oktober

Twitter & Blogroll
Samstag, 8. August

Read It Later: Round-Trip-Integration mit Firefox und Google-Reader
Montag, 3. August

Blogroll

* Jörg bei Twitter
* Jens bei Twitter
* Nils bei Twitter

* Beetlebum
* a life less ordinary?
* Martin Fowler's Bliki
* Springify
* BILDblog
* Plazeboalarm
* LawBlog
* ADOM Blog
* Being busy
* Dr. Gero Presser

Links

* Heise
* The Scala Programming Language
Nils' Fotos bei fotocommunity.de
Jogi auf Qype
Get Firefox!
Use OpenOffice.org

Heise News

* Mit Flux flugs über die Grenzen

* Neuer E-Mail-Wurm unterwegs

* Umfrage der EU zur Wiederverwendung öffentlicher Daten

* Studie: Fernsehen bleibt Leitmedium

* Dating-Website durchforstet Twitter, Facebook und Co.

kostenloser Counter