Tuesday, June 30, 2009

Apache Commons Lang: Builders Example

While it's been around for a while (version 1.0 was released in 2002), I recently discovered Apache Commons Lang and its various Builders that help make writing equals(), hashCode, and toString() much simpler.

To quote the project's homepage:

The standard Java libraries fail to provide enough methods for manipulation of its core classes. The Lang Component provides these extra methods.

Here's a simple object with two properties that demonstrates how to use some of the Builders:

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

public class Person {

String name;
Integer age;

Person(String name, Integer age) {
this.name = name;
this.age = age;
}

@Override
public boolean equals(Object object) {
return EqualsBuilder.reflectionEquals(this, object);
}

@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}

@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
}
An example use of the overriden methods in Groovy:
    def person = new Person("Costanza", 35)
println "String: $person"
println "Hash Code: " + person.hashCode()

def samePerson = new Person("Costanza", 35)
def differentPerson = new Person("Newman", 35)
println "Same equals(): " + person.equals(samePerson)
println "Different equals(): " + person.equals(differentPerson)
Produces:
    String: Person@6bb36[name=Costanza,age=35]
Hash Code: -422159695
Same equals(): true
Different equals(): false
An alternative to ToStringBuilder is ReflectionToStringBuilder:
    import org.apache.commons.lang.builder.ReflectionToStringBuilder;
...
public String toString() {
return ReflectionToStringBuilder.toString(this);
}

For String building, there are also various styles you can pass to the builder's constructor: String Styles.

There's also a CompareToBuilder that I have yet to play with.

Friday, June 26, 2009

Maven: Excluding a Module Artifact from the Deploy Phase

I have a multi-module Maven project where one's module purpose is to create an assembly which is of a good size. I would like the other module's artifacts be deployed to our remote repository when mvn deploy is run, but would like to avoid having the assembled artifact deployed due to its size.

You can configure the maven-deploy-plugin in the POM of a module to exclude it from the deploy:

<build>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.4</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
...
</build>
If done, correctly you should see the following after running mvn deploy in your build output:
[INFO] [deploy:deploy]
[INFO] skipping artifact deployement
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------

Thursday, June 18, 2009

Groovy: Base64 encode/decode with and without Commons Codec

I've been using Apache's Commons Codec to encode and decode base64 data. The Groovy code:
  import org.apache.commons.codec.binary.Base64

def data = "data"
def bytes = data.bytes

Base64 coder = new Base64()

def encodedData = coder.encode(bytes)
def decodedData = coder.decode(encodedData)

println "Original Data: $data"
println "Encoded Data: " + new String(encodedData)
println "Decoded Data: " + new String(decodedData)
Producing:
  Original Data: data
Encoded Data: ZGF0YQ==
Decoded Data: data
But Groovy makes it easy thru its additions to the JDK:
  encodedData = bytes.encodeBase64().toString()  
def decodedBytes = encodedData.decodeBase64()
decodedData = new String(decodedBytes)

println "Groovy Encoded Data: $encodedData"
println "Groovy Decoded Data: $decodedData"
Which produces:
  Groovy Encoded Data: ZGF0YQ==
Groovy Decoded Data: data
Maven coordinates for commons-codec:
  <dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.3</version>
</dependency>
Suggestions for alternative appreciated as always.

Monday, June 15, 2009

Bash: Evaluating a Command from a Variable with a Redirect

In bash, I was assigning a command I wanted to run to a variable while redirecting the output:
  command="mvn clean verify > /tmp/out"
$command
The redirect greater-than sign was being passed to the mvn command. Placing an eval in front of the mvn command does the trick:
  command="eval mvn clean verify > /tmp/out"

Thursday, June 11, 2009

DBUnit & MySQL: DataTypeFactory warning

I've been playing with DBUnit to help setup a database for my integration testing, and the experience has been very good. When my dataset was being loaded into my MySQL database, I found this warning:
    [WARN ] [org.prystasj.myproject.it.MyIntegrationTestCase.setUpDatabase] - Potential problem found: 
The configured data type factory 'class org.dbunit.dataset.datatype.DefaultDataTypeFactory'
might cause problems with the current database 'MySQL' (e.g. some datatypes may not be
supported properly).
In rare cases you might see this message because the list of supported database products is
incomplete (list=[derby]). If so please request a java-class update via the forums.
I found the following DBUnit FAQ Entry on the DBUnit website that helped me out a bunch, the code from the entry:
    IDatabaseConnection connection = new DatabaseConnection(jdbcConnection, schema);
DatabaseConfig config = connection.getConfig();
config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new OracleDataTypeFactory());
My code additions:
    // http://dbunit.sourceforge.net/faq.html#typefactory
def dbConfig = dbConnection.getConfig();
dbConfig.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new MySqlDataTypeFactory()
And all my Groovy DBUnit related code:
import org.dbunit.database.DatabaseConfig
import org.dbunit.database.DatabaseConnection
import org.dbunit.dataset.xml.XmlDataSet
import org.dbunit.ext.mysql.MySqlDataTypeFactory
import org.dbunit.operation.DatabaseOperation
...

class MyIntegrationTestCase extends GroovyTestCase {

...

def setUpDatabase() {
def connection = getConnection()
def data = getDataSet()

try {
DatabaseOperation.CLEAN_INSERT.execute(connection, data)
}
finally {
connection.close()
}
}

def getConnection() {
Class.forName(jdbcDriver)
def jdbcConnection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword)
def dbConnection = new DatabaseConnection(jdbcConnection)

// http://dbunit.sourceforge.net/faq.html#typefactory
def dbConfig = dbConnection.getConfig();
dbConfig.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new MySqlDataTypeFactory())

return dbConnection
}

def getDataSet() throws Exception {
def stream = getClass().getClassLoader().getResourceAsStream(DATASET)
def dataset = new XmlDataSet(stream)
return dataset
}

}

Wednesday, June 10, 2009

Groovy & MySQL: ALTER TABLE

I was having trouble executing a query similar to the following with in Groovy against a MySQL database:
    ALTER TABLE MAP AUT0_INCREMENT = 109
The code:
    import groovy.sql.Sql
...
def setAutoIncrement(table, value) {
def sql = Sql.newInstance(jdbcUrl, jdbcUsername, jdbcPassword, jdbcDriver)
def query = "ALTER TABLE $table AUTO_INCREMENT = $value"
sql.execute(query)
}
I was getting the folowing error:
    com.mysql.jdbc.exceptions.MySQLSyntaxErrorException:
You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for the right
syntax to use near ''MAP' AUTO_INCREMENT = '109'' at line 1
Seems like Groovy was adding single quotes around the table name and the value. I resolved this by strong-typing the query variable to a String to subvert the GString interpolation:
   String query = "ALTER TABLE $table AUTO_INCREMENT = $value"
Quoting the table and value in MySQL is invalid when running the MySQL command-line tool as well.