Blake Caldwell: /dev/blog
Not a Java Developer

Java: 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.




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.




Apache Camel: Powerful EIP Framework

Pradeep Elankumaran gives a high-level overview of Apache Camel

From Apache Camel’s project page:

Apache Camel ™ is a versatile open-source integration framework based on known Enterprise Integration Patterns.

Camel empowers you to define routing and mediation rules in a variety of domain-specific languages, including a Java-based Fluent API, Spring or Blueprint XML Configuration files, and a Scala DSL. This means you get smart completion of routing rules in your IDE, whether in a Java, Scala or XML editor.

Apache Camel uses URIs to work directly with any kind of Transport or messaging model such as HTTP, ActiveMQ, JMS, JBI, SCA, MINA or CXF, as well as pluggable Components and Data Format options. Apache Camel is a small library with minimal dependencies for easy embedding in any Java application. Apache Camel lets you work with the same API regardless which kind of Transport is used - so learn the API once and you can interact with all the Components provided out-of-box.

Apache Camel provides support for Bean Binding and seamless integration with popular frameworks such as Spring, Blueprint and Guice. Camel also has extensive support for unit testing your routes.

Check out “What exactly is Apache Camel?” on StackOverflow for other devs’ descriptions.




PDF Emailer v2.1: Multiple Recipient Support

PDF Emailer screenshot

PDF Emailer is a iOS utility app that lets you email PDF and Office documents from Safari using a customizable email template.

In version 2.1, you can now set multiple recipients in your template by separating them with spaces.

PDF Emailer v2.1 is (no longer) available for iPhone, iPad, and iPod Touch




Java: Copy/Paste-Safe Logger Creation

We’ve all copied and pasted a Logger from one class to the other, forgetting to change the class name.

// WRONG
public class SomeNewClass
{
  // OOPS! I forgot to change the class name!
  private final Logger _logger = LoggerFactory.getLogger(SomeOtherClass.class);
  
  // …	
}

Here, use this smarter LoggerFactory which uses the stack trace to figure out what class you really mean. This is safe from copypasta laziness.

package org.blakecaldwell.logging;

import org.slf4j.Logger;

/**
 * Smart logger that uses reflection to figure out the logged class
 */
public final class ClassLoggerFactory
{
    /**
     * Disallow factory instances.
     */
    private ClassLoggerFactory()
    {
    }

    /**
     * Use the stack trace to determine the appropriate logger.
     * 
     * @return a logger for the direct caller's class.
     */
    public static Logger make()
    {
        Throwable t = new Throwable();
        StackTraceElement directCaller = t.getStackTrace()[1];
        return org.slf4j.LoggerFactory.getLogger(directCaller.getClassName());
    }
}

Then, to use this logger:

// CORRECT
public class SomeNewClass
{
    // No chance for screwing up anymore!
    private final Logger _logger = ClassLoggerFactory.make();

    // …	
}