Thursday, March 06, 2014

World's smallest DAO

The world's smallest Java DAO (with heavy lifting provided by Spring Framework):

public class SimpleDAO {
    private final DataSourceTransactionManager transactionManager;

    public SimpleDAO(DataSourceTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

    public <T> T dao(Dao<T> dao) {
        return dao.using(transactionManager);
    }

    public interface Dao<T> {
        default T using(DataSourceTransactionManager transactionManager) {
            return new TransactionTemplate(transactionManager).execute(
                    status -> on(new JdbcTemplate(transactionManager.getDataSource()), status));
        }

        T on(JdbcTemplate jdbcTemplate, TransactionStatus status);
    }
}

Usage:

class InviteesDAO {
    private final SimpleDAO transact;

    InviteesDAO(DatabaseTransactionManager transactionManager) {
        transact = new SimpleDAO(tranactionManager);
    }

    List<String> getInvitees() {
        return transact.dao((jdbcTemplate, status) -> jdbcTemplate.queryForList(
            "SELECT username FROM invitees", String.class));
    }

    void invite(String username) {
        transact.dao((jdbcTemplate, status) -> jdbcTemplate.update(
            "INSERT INTO invitees (username) VALUES (?)", username));
    }
}

UPDATE: Demonstrate with composition rather than inheritance.

Saturday, February 08, 2014

ServiceBinder

I've released ServiceBinder 0.2 to Maven Central (details below; soon to be 0.3 with more documentation). I wrote this to fix a common problem for my projects.

I like using the JDK ServiceLoader for discovery: it is simple to use and understand and always available. And Kawaguchi's META-INF/services generator makes use as simple as an annotation.

However, ServiceLoader is missing one key feature for me. It requires a default constructor for implementations, and I am a fan of constructor injection.

ServiceBinder fills this gap. It discovers service classes as ServiceLoader does, and injects them with Guice or Spring. See the GitHub site for examples and source. A taste:

Guice

public final class SampleModule
        extends AbstractModule {
    @Override
    protected void configure() {
        ServiceBinder.with(binder()).bind(Bob.class);
    }
}

Spring Framework

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AppConfig.class);
ServiceBinder.with(context).bind(Bob.class);
context.refresh();

Saturday, February 01, 2014

The Java fake return trick

Sometimes we have a method that does nothing but throw an exception (after munging arguments a bit). For example:

static void fail(Bob bob, Fred fred, Exception cause) {
    throw new SadError(format(
            "Sorry, but {} and {} did not meet today",
            bob, fred), cause);
}

Great when used as:

void friends(Bob bob, Fred fred) {
    try {
        meetAgain(bob, fred);
    } catch (MissedTrainException e) {
        fail(bob, fred, e);
    }
}

But what about this?

PhoneNumber exchange(Bob bob, Fred fred {
    try {
        return beamBusinessCards(bob, fred);
    } catch (LostPhoneException e) {
        fail(bob, fred, e);
        return null; // Never reached
    }
}

There's a neat generics trick to help:

static <R> R fail(Bob bob, Fred fred, Exception cause) {
    // Code unchanged - return ignored
}

Now we can write:

PhoneNumber exchange(Bob bob, Fred fred {
    try {
        return beamBusinessCards(bob, fred);
    } catch (LostPhone e) {
        return fail(bob, fred, e);
    }
}

The main downside is readability for the casual reviewer. Unless expecting this technique, he may think the new catch body returns a value. It may help to limit use to Exception, forcing handling in the caller method, but not with RuntimeException.

JDK8: Improved Iterator

One of my favorite changes in Java 8, default methods on interfaces, adds this gem to venerable Iterator:

    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

By default now when you implement an iterable you need not supply "remove()". Beautiful.

There is also a new, defaulted "forEachRemaining(Consumer)".

Sunday, January 19, 2014

Adapters with Lambda

Java 8 lambdas make some things more interesting:

import org.slf4j.Logger;
import static java.lang.String.format;

interface EasyLogger {
    void log(Throwable cause, String message,
             Object... arguments);

    enum LogLevel {
        TRACE(logger -> logger::trace),
        DEBUG(logger -> logger::debug),
        INFO(logger -> logger::info),
        WARN(logger -> logger::warn),
        ERROR(logger -> logger::error);

        Adapt adapt;

        LogLevel(Adapt adapt) {
            this.adapt = adapt;
        }

        EasyLogger using(Logger logger) {
            return (Throwable cause, String message,
                    Object... arguments)
                -> adapt.from(logger)
                    .log(format(message, arguments), cause);
        }

        static String format(String message, Object... arguments) {
            return null == message
                    ? null : String.format(message, arguments);
        }

        interface Call {
            void log(String message, Throwable cause);
        }

        interface Adapt {
            Call from(Logger logger);
        }
    }
}

This is just an example, not a real logger class! (Also please excuse the formatting, done to keep the code readable on narrow screens.)

Key point: Java has no "perfect forwarding", so simulate it with method references. Using enums complicated things; essentially these are "factory factories" mapping a level and a logger to a method reference.

Perhaps over clever.

UPDATE: Still a toy class but this makes the interface more familiar:

    default void log(String message, Object... arguments) {
        log(null, message, arguments);
    }

    default void log(Throwable cause) {
        log(cause, null);
    }

An example will help:

import static EasyLogger.INFO;
// Other suitable imports

class Example {
    public static void main(String... args) {
        EasyLogger info = INFO.using(LoggerFactory.getLogger("main"));

        info.log("Hi, %s!", "mom"); 
    }
}

Friday, January 10, 2014

Java 8 AutoCloseable trick

I am working with an API some of whose interfaces have a "close()" method but which do not implement AutoCloseable (they predate this JDK addition), yet I would like to use them in a try-resources block. What to do?

Previously I would give up and just do the try/finally dance — Java has no perfect forwarding, implementing a wrapper class preserving the original's calls is terribly hard.

Java 8 provides a neat trick with method references:

interface Foo {
    void close();

    void doFoo();
}

Elsewhere:

final Foo foo = new SomeFoo();
try (final AutoCloseable ignored = foo::close) {
    foo.doFoo();
}

Presto!

A practical use is pre-4 Spring Framework. When a context type in version 4 declares "close", it implements AutoCloseable; version 3 and earlier do not.

Another neat trick here, the method names need not be the same:

interface Bar {
    void die();

    void doBar();
}

And:

final Bar bar = new SomeBar();
try (final AutoCloseable ignored = bar::die) {
    bar.doBar();
}

Wednesday, January 08, 2014

Links at Google Plus

I've mostly switched over to using my Google Plus account for programming links. If you'd like me to share them with you, please drop me a post. My account there is: Brian Oxley. Longer posts and source code will remain here.

Saturday, December 07, 2013

Wednesday, December 04, 2013

10 Java dos and dont's

Nice list of 10 Java coding pratices from Data Geekery GmbH in Switzerland. These 10 are close to my programmer heart:

  1. Remember C++ destructors
  2. Don’t trust your early SPI evolution judgement
  3. Avoid returning anonymous, local, or inner classes
  4. Start writing [functional interface]s now!
  5. Avoid returning null from API methods
  6. Never return null arrays or lists from API methods
  7. Avoid state, be functional
  8. Short-circuit equals()
  9. Try to make methods final by default
  10. Avoid the method(T…) signature

Saturday, November 23, 2013

Generic logback.xml

I've started using a generic logback.xml file for my projects which use logging:

<?xml version="1.0"?>
<configuration debug="${log.debug:=false}">
  <property resource="logback-style.properties"/>
  <appender name="console"
      class="ch.qos.logback.core.ConsoleAppender">
    <encoder
        class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <pattern>${${log.style:-standard}}</pattern>
    </encoder>
  </appender>
  <root level="${log.level:-warn}">
    <appender-ref ref="console"/>
  </root>
  <include resource="logback-included.xml" optional="true"/>
  <contextListener
      class="ch.qos.logback.classic.jul.LevelChangePropagator"/>
  <jmxConfigurator/>
</configuration>

Some explanation:

  • I make use of the substitution with default feature to make use of system properties:
    log.debug
    Setting this to "true" gets logback to log during configuration, default is "false"
    log.style
    See below
    log.level
    This adjusts the global log level, default is "warn" so only errors and warnings log
  • Reading variables from a property file as a resource lets me externalize them to the classpath, in particular, the log style (see the next item).
  • The name nesting for substitution feature is neat: it lets you use the value of a variable as the name of another variable. For log.style I read a log format string from a properties file, using another property for the key name.
  • File inclusion let me keep the boilerplate in this example, and the application-specific bits in a separate logback XML file.
  • Lastly I add a context listener to hook java.util.logging into logback and turn on JMX support. I do these last for some small performance gain.

Here is one example log-style.properties:

standard=%date{yyyy-MM-dd'T'HH:mm:ss.SSS'Z',UTC} %level [%thread] %logger - %message%n

Update:

A handy trick to automatically lower logging to "debug" when "logback.debug" is true, best placed near the top:

<if condition='property("logback.debug").equals("true")'>
    <then>
        <variable name="log.level" value="debug"/>
    </then>
</if>

Wednesday, October 30, 2013

Cautionary tale

Toyota is a cautionary tale for following good practice at software.

Friends don't let friends smash their own stack.