Friday
Oct182013

Conditionally Run JUnit Integration Tests with Spring

Ideally, your unit test suites require no external dependencies - those should be mocked out. However, sometimes you want extra assurance that your code works with live endpoints via integration tests.

For example, you might want to make sure that your code can successfully navigate your corporate proxy and firewall to make external web requests. For this, we’ll write tests that only run when a command line parameter is defined.

This demonstration assumes that you’re using Spring’s JUnit Runner and Maven for running your tests. The @IfProfileValue annotation will tell the test runner to only include this test suite if our configured ProfileValueSource returns a “true” for “live-external-tests-enabled”.

Let’s verify that this test suite is ignored by default with the maven command:

You’ll see that you now have a skipped test:

Now, try it again, but this time with our test included:

You’ll now see that the test was run:

The @IfProfileValue annotation can also be used above an individual test.

Tuesday
Sep032013

Don't Rely on EntityManager.persist() for Immediate Insert

I had always counted on EntityManager's persist() method to immediately insert entities. I would rely on this when writing database integration tests - I'd persist some records, then test my DAO methods to find them.

On my current project, I decided to add a configuration option to allow me to run my datbase integration tests on my development Oracle database rather than my embedded HSQLDB test database - just for an extra sanity check. The tests that tried to persist() and then retrieve those new entities failed. Adding an entityManager.flush() method after the persist() invocations solved the issue.

...But why?

From en.wikibooks.org:

The EntityManager.persist() operation is used to insert a new object into the database. persist does not directly insert the object into the database, it just registers it as new in the persistence context (transaction). When the transaction is committed, or if the persistence context is flushed, then the object will be inserted into the database. If the object uses a generated Id, the Id will normally be assigned to the object when persist is called, so persist can also be used to have an object's Id assigned. The one exception is if IDENTITY sequencing is used, in this case the Id is only assigned on commit or flush because the database will only assign the Id on INSERT. If the object does not use a generated Id, you should normally assign its Id before calling persist.

Here's how I wire up my entities' primary key:

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

For my embedded HSQLDB database, the generation strategy is GenerationType.IDENTIY, which relies on the database to generate an autoincrementing primary key for that row. This requires an insert, so the persist() immediately inserts in HSQLDB.

Oracle, on the other hand, uses a cross-table GenerationType.SEQUENCE @Id generator, which doesn't require an insert, but the following SELECT:

select
    hibernate_sequence.nextval
from
    dual

This select is called immediately on persist() so that the EntityManager has an ID to assign the entity. That entity will only be inserted after a flush(), which is called automatically on transaction commit.

Long story short: If you're relying on your entity existing in the database after your call to persist(), but before the transaction commits, then call flush() first. Leave a comment justifying it, as manually calling flush is largely considered an anti-pattern akin to invoking the garbage collector. Delayed flush() calls give Hibernate the chance to perform more performant bulk updates.

Tuesday
Sep032013

Object/Relational Mapping: Know Your Frameworks

I've been working with Hibernate for several years now, yet I learn something new about it all the time. The more time I spend with the framework, the more concerned I am about how it will be used by developers new to it.

Mirko Novakovic Alois Reitbauer nails it in a post about O/R Mapping Anti-Patterns:

The simplicity of the entrance into the world of O/R mapping however gives a wrong impression of the complexity of these frameworks. Working with more complex applications you soon realize that you should know the details of framework implementation to be able to use them in the best possible way. In this article, we describe some common anti-patterns which may easily lead to performance problems.

This is an echo of Joel Spolsky's warnings of the Law of Leaky Abstraction:

The law of leaky abstractions means that whenever somebody comes up with a wizzy new code-generation tool that is supposed to make us all ever-so-efficient, you hear a lot of people saying "learn how to do it manually first, then use the wizzy tool to save time." Code generation tools which pretend to abstract out something, like all abstractions, leak, and the only way to deal with the leaks competently is to learn about how the abstractions work and what they are abstracting. So the abstractions save us time working, but they don't save us time learning.

Don't stop learning about a framework once you figure out how to use it - that's only the beginning.

Friday
Aug302013

Builder Pattern Instead of Error-Prone Constructors

When designing your classes, rather than following the path of the unreadable telescoping constructor, or leaving yourself open for bugs where the caller incorrectly passes a value into the wrong parameter because you have several of the same type, consider the following Builder pattern.

public class Person
{
    // required
    private String firstName;

    // required
    private String lastName;

    // optional
    private String url;

    // private constructor to defer responsibility to Builder.
    private Person()
    {
    }

    public String getFirstName()
    {
        return this.firstName;
    }

    public void setFirstName(final String firstName)
    {
        if(StringUtils.isBlank(firstName))
        {
            throw new IllegalArgumentException("Person.firstName must not be blank");
        }
        this.firstName = firstName;
    }

    public String getLastName()
    {
        return this.lastName;
    }

    public void setLastName(final String lastName)
    {
        if(StringUtils.isBlank(lastName))
        {
            throw new IllegalArgumentException("Person.lastName must not be blank");
        }
        this.lastName = lastName;
    }

    public String getUrl()
    {
        return this.url;
    }

    public void setUrl(final String url)
    {
        this.url = url;
    }

    // builder class to ensure that all required fields are set while avoiding clunky, "telescopic" constructors
    public static class Builder
    {
        private Person built;

        public Builder()
        {
            built = new Person();
        }

        public Builder setFirstName(final String firstName)
        {
            built.setFirstName(firstName);
            return this;
        }

        public Builder setLastName(final String lastName)
        {
            built.setLastName(lastName);
            return this;
        }

        public Person build()
        {
            if(built.firstName == null)
            {
                throw new IllegalStateException("Person.firstName is required");
            }
            if(built.lastName == null)
            {
                throw new IllegalStateException("Person.lastName is required");
            }
            return built;
        }
    }
}

Having a private constructor will prevent anyone but the Person's Builder from instantiating a Person. The setters in the Builder return the Builder, which allows method chaining, providing a DSL-like self-documenting interface. The Builder's build() method is responsible for making sure that all properties are set before returning the Person.

Of course, this is a simple example with only two fields, so the alternative isn't exactly error prone:

Person blogger = new Person("Blake", "Caldwell");
blogger.setUrl("http://blakecaldwell.org");

But, once you add a few more required fields, the following makes your code easier to follow, while still ensuring all required fields are set.

Person blogger = new Person.Builder()
        .setFirstName("Blake")
        .setLastName("Caldwell")
        .build();
blogger.setUrl("http://blakecaldwell.org");

I first came across this pattern via a post by Petri Kainulainen. Check out his blog for great posts about Spring Data JPA and other topics.

Wednesday
Jul032013

Mouse Issues on Mac OS X 10.8 [SOLVED] 

I recently started noticing performance issues with my new Logitech M570 trackball. Occassionally, when moving the mouse, the cursor would briefly freeze, and then show up on the far end of the screen. It seemed as though there was a high priority task that would spike the cpu every 5 seconds or so.

At first, I thought it was an issue with the mouse's wireless communication, so I tried wired mice and found the same issue. I went through the normal process of elimination, stopping bluetooth, Internet and File Sharing, Spotlight indexing, iCloud, Messages, Quicksilver, Flux, Backblaze, and all of the launch agents, daemons, and startup items.

It turns out that the issue was caused by Apple's Screen Mirroring. I usually have two displays hooked up to my Mac Pro: an Apple Cinema Display and a Dell UltraSharp U2711. I often share the Dell with another computer, and since it has so many inputs (unlike the Cinema Display), I just use a different input, rather than disconnect it from my Mac. Since the Mac then has no idea that I can't see what it's doing on the Dell anymore, I tell it to mirror the display on both screens.

When I unhooked the Dell from my Mac, everything worked as it should. My apologies to the hardworking developers whose work I cursed under my breath the past few days - this time, it was Apple's fault.