The Mute Design Pattern

Have you been writing a lot of code following the Mute-Design-Pattern™ lately? E.g.

try {
    complex();
    logic();
    here();
}
catch (Exception ignore) {
    // Will never happen hehe
    System.exit(-1);
}

There’s an easier way with Java 8!

Just add this very useful tool to your Utilities or Helper class:

public class Helper {

    // 18395 lines of other code here

    @FunctionalInterface
    interface CheckedRunnable {
        void run() throws Throwable;
    }

    public static void mute(CheckedRunnable r) {
        try {
            r.run();
        }
        catch (Throwable ignore) {
            // OK, better stay safe
            ignore.printStackTrace();
        }
    }

    // 37831 lines of other code here
}

Now you can wrap all your logic in this nice little wrapper:

mute(() -> {
    complex();
    logic();
    here();
});

Done!

Even better, in some cases, you can use method references

try (Connection con = ...;
     PreparedStatement stmt = ...) {

    mute(stmt::executeUpdate);
}

Let’s Review How to Insert Clob or Blob via JDBC

LOBs are a PITA in all databases, as well as in JDBC. Handling them correctly takes a couple of lines of code, and you can be sure that you’ll get it wrong eventually. Because you have to think of a couple of things:

  • Foremost, LOBs are heavy resources that need special lifecycle management. Once you’ve allocated a LOB, you better “free” it as well to decrease the pressure on your GC. This article shows more about why you need to free lobs
  • The time when you allocate and free a lob is crucial. It might have a longer life span than any of your ResultSet, PreparedStatement, or Connection / transaction. Each database manages such life spans individually, and you might have to read up the specifications in edge cases
  • While you may use String instead of Clob, or byte[] instead of Blob for small to medium size LOBs, this may not always be the case, and may even lead to some nasty errors, like Oracle’s dreaded ORA-01461: can bind a LONG value only for insert into a LONG column

So, if you’re working on a low level using JDBC (instead of abstracting JDBC via Hibernate or jOOQ), you better write a small utility that takes care of proper LOB handling.

We’ve recently re-discovered our own utility that we’re using for jOOQ integration testing, at least in some databases, and thought this might be very useful to a couple of our readers who operate directly with JDBC. Consider the following class:

public class LOB implements AutoCloseable {

    private final Connection connection;
    private final List<Blob> blobs;
    private final List<Clob> clobs;

    public LOB(Connection connection) {
        this.connection = connection;
        this.blobs = new ArrayList<>();
        this.clobs = new ArrayList<>();
    }

    public final Blob blob(byte[] bytes) 
    throws SQLException {
        Blob blob;

        // You may write more robust dialect 
        // detection here
        if (connection.getMetaData()
                      .getDatabaseProductName()
                      .toLowerCase()
                      .contains("oracle")) {
            blob = BLOB.createTemporary(connection, 
                       false, BLOB.DURATION_SESSION);
        }
        else {
            blob = connection.createBlob();
        }

        blob.setBytes(1, bytes);
        blobs.add(blob);
        return blob;
    }

    public final Clob clob(String string) 
    throws SQLException {
        Clob clob;

        if (connection.getMetaData()
                      .getDatabaseProductName()
                      .toLowerCase()
                      .contains("oracle")) {
            clob = CLOB.createTemporary(connection, 
                       false, CLOB.DURATION_SESSION);
        }
        else {
            clob = connection.createClob();
        }

        clob.setString(1, string);
        clobs.add(clob);
        return clob;
    }


    @Override
    public final void close() throws Exception {
        blobs.forEach(JDBCUtils::safeFree);
        clobs.forEach(JDBCUtils::safeFree);
    }
}

This simple class has some nice treats:

  • It’s AutoCloseable, so you can free your lobs with the try-with-resources statement
  • It abstracts over the creation of LOBs across SQL dialects. No need to remember the Oracle way

To use this class, simply write something like the following:

try (
    LOB lob = new LOB(connection);
    PreparedStatement stmt = connection.prepareStatement(
        "insert into lobs (id, lob) values (?, ?)")
) {
    stmt.setInt(1, 1);
    stmt.setClob(2, lob.clob("abc"));
    stmt.executeUpdate();
}

That’s it! No need to keep references to the lob, safely freeing it if it’s not null, correctly recovering from exceptions, etc. Just put the LOB container in the try-with-resources statement, along with the PreparedStatement and done.

If you’re interested in why you have to call Clob.free() or Blob.free() in the first place, read our article about it. It’ll spare you one or two OutOfMemoryErrors

Inadvertent Recursion Protection with Java ThreadLocals

Now here’s a little trick for those of you hacking around with third-party tools, trying to extend them without fully understanding them (yet!). Assume the following situation:

  • You want to extend a library that exposes a hierarchical data model (let’s assume you want to extend Apache Jackrabbit)
  • That library internally checks access rights before accessing any nodes of the content repository
  • You want to implement your own access control algorithm
  • Your access control algorithm will access other nodes of the content repository
  • … which in turn will again trigger access control
  • … which in turn will again access other nodes of the content repository

… Infinite recursion, possibly resulting in a StackOverflowError, if you’re not recursing breadth-first.

Now, you have two options:

  1. Take the time, sit down, understand the internals, and do it right. You probably shouldn’t recurse into your access control once you’ve reached your own extension. In the case of extending Jackrabbit, this would be done by using a System Session to further access nodes within your access control algorithm. A System Session usually bypasses access control.
  2. Be impatient, wanting to get results quickly, and prevent recursion with a trick

Of course, you really should opt for option 1. But who has the time to understand everything? ;-)

Here’s how to implement that trick.

/**
 * This thread local indicates whether you've
 * already started recursing with level 1
 */
static final ThreadLocal<Boolean> RECURSION_CONTROL 
    = new ThreadLocal<Boolean>();

/**
 * This method executes a delegate in a "protected"
 * mode, preventing recursion. If a inadvertent 
 * recursion occurred, return a default instead
 */
public static <T> T protect(
        T resultOnRecursion, 
        Protectable<T> delegate) 
throws Exception {

    // Not recursing yet, allow a single level of
    // recursion and execute the delegate once
    if (RECURSION_CONTROL.get() == null) {
        try {
            RECURSION_CONTROL.set(true);
            return delegate.call();
        }
        finally {
            RECURSION_CONTROL.remove();
        }
    }

    // Abort recursion and return early
    else {
        return resultOnRecursion;
    }
}

/**
 * An API to wrap your code with
 */
public interface Protectable<T> {
    T call() throws Exception;
}

This works easily as can be seen in this usage example:

public static void main(String[] args) 
throws Exception {
    protect(null, new Protectable<Void>() {
        @Override
        public Void call() throws Exception {

            // Recurse infinitely
            System.out.println("Recursing?");
            main(null);

            System.out.println("No!");
            return null;
        }
    });
}

The recursive call to the main() method will be aborted by the protect method, and return early, instead of executing call().

This idea can also be further elaborated by using a Map of ThreadLocals instead, allowing for specifying various keys or contexts for which to prevent recursion. Then, you could also put an Integer into the ThreadLocal, incrementing it on recursion, allowing for at most N levels of recursion.

static final ThreadLocal<Integer> RECURSION_CONTROL 
    = new ThreadLocal<Integer>();

public static <T> T protect(
        T resultOnRecursion, 
        Protectable<T> delegate)
throws Exception {
    Integer level = RECURSION_CONTROL.get();
    level = (level == null) ? 0 : level;

    if (level < 5) {
        try {
            RECURSION_CONTROL.set(level + 1);
            return delegate.call();
        }
        finally {
            if (level > 0)
                RECURSION_CONTROL.set(level - 1);
            else
                RECURSION_CONTROL.remove();
        }
    }
    else {
        return resultOnRecursion;
    }
}

But again. Maybe you should just take a couple of minutes more and learn about how the internals of your host library really work, and get things right from the beginning… As always, when applying tricks and hacks! :-)

How to Execute Something Multiple Times in Java

When writing unit / integration tests, you often want to execute something multiple times, with different configurations / parameters / arguments every time. For instance, if you want to pass a “limit” or “timeout” or any other argument value of 1, 10, and 100, you could do this:

@Test
public void test() {
    runCode(1);
    runCode(10);
    runCode(100);
}

private void runCode(int argument) {

    // Run the actual test
    assertNotNull(new MyObject(argument).execute());
}

Exracting methods is the most obvious approach, but it can quickly get nasty, as these extracted methods are hardly re-usable outside of that single test-case and thus don’t really deserve being put in their own methods. Instead, just use this little trick:

@Test
public void test() {

    // Repeat the contents 3 times, for values 1, 10, 100
    for (int argument : new int[] { 1, 10, 100 }) {

        // Run the actual test
        assertNotNull(new MyObject(argument).execute());
    }

    // Alternatively, use Arrays.asList(), which has a similar effect:
    for (Integer argument : Arrays.asList(1, 10, 100)) {

        // Run the actual test
        assertNotNull(new MyObject(argument).execute());
    }
}