Loading test BLOB data into HSQLDB with a Groovy Ant Task

At my current client we use an in-memory HSQLDB for unit testing. An in-memory DB provides us a mechanism to test DAO’s and services against a known dataset. Overall this has worked out very well for us and our unit testing.

Until recently we only used the HSQL jar file to create the schema and DBUnit Ant task to load the data from .csv files.  The Ant tasks looked something like the following.

Ant INIT target

<target name="init">
  <property name="hsql.url" value="jdbc:hsqldb:hsql://localhost:9001/testSchema" />
  <property name="hsql.username" value="testUser" />
  <property name="hsql.password" value="testPass" />
  <property name="hsql.dir" value="./hsqldb" />
  <property name="hsql.jar" value="${hsql.dir}/lib/hsqldb-1.8.0.7.jar" />
  <property name="ddl.dir" value="./ddl" />
  <property name="data.dir" value="./data" />
</target>

Ant Target to load the DDL

<target name="hsql-load-schema"
           depends="init"
      description="Loads schema into hsql.">

  <!-- load ddl -->
  <java jar="${hsql.jar}" fork="true" failonerror="true">
  <arg value="--rcFile" />
  <arg value="${hsql.dir}/sqltool.rc" />
  <arg value="testSchema" />
  <arg value="${ddl.dir}/base-schema.ddl" />
  </java>
</target>

This solution worked great for the data types we normally use. Recently however, we needed to add support for logos stored as jpg’s. In the DB the jpg files are stored as BLOB’s. From what I could find, DBUnit wasn’t an option for loading BLOB datatypes from image files in the same manner we were familiar with.

Our solution for loading images into a BLOB was to use the Ant Groovy task . This plugin allowed us to write Groovy code inside the same build.xml file we were already using to create the tables and load the data.

Updated Ant INIT task

<target name="init">
  <property name="hsql.url" value="jdbc:hsqldb:hsql://localhost:9001/testSchema" />
  <property name="hsql.username" value="testUser" />
  <property name="hsql.password" value="testPass" />

  <property name="hsql.dir" value="./hsqldb" />
  <property name="hsql.jar" value="${hsql.dir}/lib/hsqldb-1.8.0.7.jar" />
  <property name="ddl.dir" value="./ddl" />
  <property name="data.dir" value="./data" />

<!-- Setup the Groovy Path to define the tasks  -->
  <path id="groovy.path">
    <fileset dir="./lib">
      <include name="groovy-all-1.7.5.jar" />
    </fileset>
    <fileset dir="${hsql.dir}/lib">
      <include name="hsqldb-1.8.0.7.jar" />
    </fileset>
  </path>

<!-- Define the Groovy Task  -->
  <taskdef name="groovy"
             classname="org.codehaus.groovy.ant.Groovy"
          classpathref="groovy.path" />
  </target>

Groovy Ant task to load BLOB’s

<target name="hsql-load-logos"
           depends="init"
      description="Loads Logos into the DB.">
<!-- Below is an Groovy-Ant task that allows Groovy code to be executed.
The script uses Groovy to load an image into a blob DB Column.   -->

    <groovy>
      import groovy.sql.Sql
      import org.hsqldb.jdbcDriver

      def sql = Sql.newInstance("jdbc:hsqldb:hsql://localhost:9001/testSchema", "testUser", "testPass", "org.hsqldb.jdbcDriver")

// Read the directory containing the images.  Image files are prefixed with a 4 digit school identifier "

     def dir = new File('../finance-student-test/blobs/logos')
     dir.eachFile {
     if (it.isFile()) {
        println "----  processing file ---- " + it.name

        def schoolId = it.name.substring(0,4)

//  The table was not setup with a sequence to generate next value so we need to get the current max_id value for the school

        def firstRow = sql.firstRow("select LOGO_ID
                                                      from LOGO_CNTRL
                                                    where SCHOOL_ID = ${schoolId}
                                                     order by LOGO_ID desc")

        def maxId = 0
        if(firstRow != null) {
          maxId = firstRow.get("LOGO_ID")
        }

// get the file as a FileInputStream
       InputStream fis = new FileInputStream(it);

// Create a PreparedStatement to do the insert.  Some values are hardcoded in the insert statement.
       def ps = sql.connection.prepareStatement(
       "insert into LOGO_CNTRL
            (SCHOOL_ID, LOGO_ID, LOGO_TYPE_ID, LOGO_FILE_TYPE_ID, LOGO_BEGIN_DATE, LOGO_END_DATE, LOGO_FILE)
            values(?, ?, 101001, 42, ?, ?, ?)")

        ps.setObject(1, rcId)
        ps.setObject(2, maxId + 1)
        ps.setObject(3, beginDate)
        ps.setObject(4, endDate)

// Set the BLOB with the FileInputStream

        ps.setBinaryStream(5, fis, (int)it.length());

        ps.execute()
        sql.commit()
        ps.close()

      }
    }
    sql.close()

  </groovy>
</target>

If you have a better way to solve this problem I would encourage you to share it in the comments below.

About the Author

Object Partners profile.
Leave a Reply

Your email address will not be published. Required fields are marked *

Related Blog Posts
Android Development for iOS Developers
Android development has greatly improved since the early days. Maybe you tried it out when Android development was done in Eclipse, emulators were slow and buggy, and Java was the required language. Things have changed […]
Add a custom object to your Liquibase diff
Adding a custom object to your liquibase diff is a pretty simple two step process. Create an implementation of DatabaseObject Create an implementation of SnapshotGenerator In my case I wanted to add tracking of Stored […]
Keeping Secrets Out of Terraform State
There are many instances where you will want to create resources via Terraform with secrets that you just don’t want anyone to see. These could be IAM credentials, certificates, RDS DB credentials, etc. One problem […]
Validating Terraform Plans using Open Policy Agent
When developing infrastructure as code using terraform, it can be difficult to test and validate changes without executing the code against a real environment. The feedback loop between writing a line of code and understanding […]