java.beans.XMLEncoder Considered Harmful

To all java engineers out there:

Before you even think about using java.beans.XMLEncoder and it’s sibling, XMLDecoder, make sure you verify two things:

Are you OK with your application running single-threaded? XMLEncoding hits a static synchronized helper method. Expect to see blocked threads.

Are you OK with forcing your JVM to process an obscene amount of object garbage? A 1 hour stress test generated more than 1.2 Tb of object garbage. While the stress test was running, the JVM was between 50 and 80% devoted to garbage collection.

After switching to xstream, the GC problems are gone, there aren’t any blocked threads, my whites are whiter, my coat is a whole lot more glossy, and cherubs are flying by with banners that say “Huzzah.”

TestNG, test groups, IDEA, and @BeforeMethod

Say you have

public class SomeTestNG {
@BeforeClass
public void setup() {}
@Test
public void test1() {}
@Test
public void test2() {}
}

You’ll get the following methods invoked:

  • setup()
  • test1()
  • test2()

Not surprising.

What happens, though, with this?

public class SomeTestNG {
@BeforeClass
public void setup() {}
@Test(groups = {"database"})
public void test1() {}
@Test
public void test2() {}
}

And you run the “database” group?

Does setup() get called?

It’d have to, right?

Well…

Not so much.

Not so much.

@BeforeClass has a groups() attribute as well, and it’s respected when you run group test suites. If you want it to run before all methods, you need to use the alwaysRun = true:

public class SomeTestNG {
@BeforeClass(alwaysRun = true)
public void setup() {}
@Test(groups = {"database"})
public void test1() {}
@Test
public void test2() {}
}

What’s a serious humdinger–when you run the test manually in IDEA, you’re running the test outside the scope of it’s group test suite, so the @BeforeClass runs as expected. Only in ant will the @Before… fail to get called.

Hibernate Naming Strategies

Using Hibernate annotations with the default naming strategy leaves you with camelCasedColumnNames in your database schema.

Gavin King provided a good camelCase to underscore_separated naming strategy with org.hibernate.cfg.ImprovedNamingStrategy. The only glitch I found was in foreign key references. I’ve always seen the naming convention of ${tablename}_id, but ImprovedNamingStrategy just called the column the same name as any other field. That’s easily overridden in a subclass:

public class NewAndImprovedNamingStrategy extends ImprovedNamingStrategy {
    @Override
    public String foreignKeyColumnName(String propertyName, String propertyEntityName, String propertyTableName, String referencedColumnName) {
        String s = super.foreignKeyColumnName(propertyName, propertyEntityName, propertyTableName, referencedColumnName);
        return s.endsWith("_id") ? s : s + "_id";
    }
}

If you’re using Spring, wire it up to your SessionFactoryBean:

  <bean id="namingStrategy" class="...NewAndImprovedNamingStrategy"/>
  ...
  <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="namingStrategy" ref="namingStrategy"/>
    ...

And you’ll be freed from doing boilerplate “name=” attributes in your domain POJOs.