Archive for August, 2009

Add Package (or Class) Filtering To Your Findbugs Ant Task

Following on from my last post about using hbm2java to generate a @Entity bean DAO layer for our application, Findbugs, the great automatic bug finding tool, will find a lot of issues with Hibernate’s auto-generated code (primarily around exposing internal Date objects to callers). So long as this is something we are aware of and don’t have a problem with, we don’t want find bugs to tell us about this stuff. It’s possible to filter out an entire package or class tree with the use of Findbugs’ filters.

For example, say we wanted to filter out the classes in the package com.mycom.dbautodao, we could create a findbugs_filter.xml which contains:

<FindBugsFilter>
  <Match>
    <Package name="~com\.mycom\.dbautodao\..*"/>
  </Match>
</FindBugsFilter>

This uses a regular expression to filter out checks against all contents and sub-packages of the com.mycom.dbautodao package.

Similarly it’s possible to do the same with a <class name=”myregex”/> element rather than a <package/> element for finer control.

To enable the filtering we just need modify the tag in our Ant build file to include the filter, e.g.

<findbugs home="${findbugs.home}" output="xml" outputFile="${basedir}/dist/findbugs/findbugs.xml" excludefilter="findbugs_filter.xml">

While on the topic of regular expressions, I often find myself using this online regex checker tool which uses Java’s regex syntax – http://www.fileformat.info/tool/regex.htm. It’s a really quick and handy way of writing and testing a regular expression, since you can enter test string which provide both positive and negative test cases to develop against.

, , , , ,

No Comments

Using Bottom-Up Iterative Object/Database Layer With hbm2java and warp-persist

This post sort of follows on from my last one – for the project I’m currently working on at work, we have a very large legacy database (1500+ tables) on top of which we are implementing a new business layer (Java/Guice).

Due to the legacy data structures (which are mostly in need of major refactoring, that can only occur in a long-term iterative fashion), we are completely segmenting the DAO layer from the business domain layer. The DAO layer and associated @Entity beans are generated automatically (and frequently) using the hbm2java tool which is part of Hibernate. To make things even more complex, our business layer also supports multiple logical databases…. We are using Guice, and the excellent warp-persist library to manage the JPA transactions and bootstrapping across these multiple databases (multi-unit support is relatively new in warp-persist).

The problem then comes though – unless we manually add all of our 1000’s of @Entity beans to the JPA configuration for each persistence unit (which is a potential source of bugs, and a pain in the ass), how do we figure out which beans belong to which database unit? Well annotations is the way that warp-persist implements this, unfortunately, hbm2java doesn’t know that… (i.e. it won’t add the annotations against the relevant classes).

This is actually easily solved using the same trick with Ant and the regex replacement from my last post…

   <target name="gen_hibernate" description="generate hibernate classes">
        <hibernatetool>
            <jdbcconfiguration revengfile="src/hibernate.reveng.xml"
                               configurationfile="src/hibernate.cfg.xml"
                               packagename="com.mycom.db.model"
			       detectmanytomany="true"
                               />
            <hbm2java destdir="src" ejb3="true" jdk5="true"/>
        </hibernatetool>
        <loadfile property="javaheader" srcFile="lib/standardheader.txt"/>
        <replaceregexp match="^package " 
                       replace="${javaheader}// DO NOT EDIT THIS FILE - THIS CODE IS AUTO-GENERATED${line.separator}package ">
            <fileset dir="src/com/mycom/db/model">
                <include name="**/*.java"/>
            </fileset>
        </replaceregexp>
        <replaceregexp match="/\*\*.*generated by hbm2java.*\*/" 
                       flags="sm" 
                       replace="/**${line.separator} * @version $Id$ ${line.separator} */${line.separator}">
            <fileset dir="src/com/mycom/db/model">
                <include name="**/*.java"/>
            </fileset>
        </replaceregexp>
        <replaceregexp match="@Entity" 
                       replace="@Entity @MyDbUnit">
            <fileset dir="src/com/mycom/db/model">
                <include name="**/*.java"/>
            </fileset>
        </replaceregexp>
        <replaceregexp match="import javax.persistence.Entity;" 
                       replace="import javax.persistence.Entity; import com.mycom.db.MyDbUnit;">
            <fileset dir="src/com/mycom/db/model">
                <include name="**/*.java"/>
            </fileset>
        </replaceregexp>
    </target>

You’ll notice I threw in a couple of bonuses there too… the following changes are automatically made to all of the generated code -

  1. Our “standard header” (copyright / licence info) is added to the top of the file above the package …. descriptor.
  2. The @version $Id$ Javadoc tag is added to the class level Javadoc (this is assuming you’re using SVN or CVS – replace as necessary).
  3. The database unit annotation (@MyDbUnit in this case) is added next the @Entity annotation.
  4. Finally we add the import for the @MyDbUnit annotation (this would only be required if it’s in a separate package – which it in our case it is).

We then copy / replicate this job for each database in the system (with appropriately separate hibernate.cfg.xml and hibernate.reveng.xml configurations).

Well I think this takes the cake for the most esoteric and narrow detail blog post yet… but my whole goal in setting up and posting to this blog is for my own future reference; if other people find it useful then that’s great, but really when I implement something that was kinda interesting, tricky, or indeed esoteric, then this is my own reference for later. YMMV.

, , , , , , ,

No Comments