In ver­sion 2.5, released in Novem­ber 2007, Spring intro­duced annotation-based appli­ca­tion con­text con­fig­u­ra­tion ori­ented pri­mar­ily around the org.springframework.stereotype pack­age. Clearly, anno­ta­tions have been around in the Java and Spring world for quite some time now. Leav­ing aside the ques­tion of the pros and cons of anno­ta­tions them­selves for another time, it occurs to me that most devel­op­ers still tend to treat them as if they were a slightly mys­te­ri­ous form of code: they are reluc­tant to imple­ment their own and tend to use those that exist in only the most nor­ma­tive and mun­dane ways. There­fore, I would like to go through a very sim­ple exam­ple of how to take advan­tage of Spring’s stereo­type anno­ta­tions to sup­port and enhance your own appli­ca­tion architecture.

Out of the box, Spring pro­vides 4 basic archi­tec­tural stereo­types used com­monly by n-tier applications:

@Component
Used to indi­cate that the anno­tated class encap­su­lates a generic appli­ca­tion com­po­nent of an essen­tially unde­fined type.
@Repository
Used to indi­cate that the anno­tated class enca­pu­lates access to a sys­tem of record (e.g. a data accessor).
@Service
Used to indi­cate that the anno­tated class encap­su­lates a “ser­vice”; com­monly defined in terms of an API the under­ly­ing imple­men­ta­tion of which organ­ises sequences of lower-level tech­ni­cal logic into a call sequence within a trans­ac­tion bound­ary with the aim of deliv­er­ing a func­tional requirement.
@Controller
Used to indi­cate that the anno­tated class is a con­troller within an MVC application.

With the excep­tion of the @Component anno­ta­tion (which is the base type used to deter­mine that a class is a Spring bean dur­ing con­text ini­tial­i­sa­tion) and the @Controller anno­ta­tion (which is key when using Spring’s MVC sup­port), the spe­cial­i­sa­tions indi­cated serve lit­tle func­tional use on the whole. In most appli­ca­tions, it would be absolutely equiv­a­lent to mark a class as @Component in pref­er­ence to @Service, for exam­ple. How­ever, it need not be that way as not only can this meta­data be utilised for func­tional ends but also extend­ing these stereo­types pro­vides an excel­lent way to clar­ify the archi­tec­tural role of a given unit of code when none of the pre-existing spe­cial­i­sa­tions are appropriate.

For exam­ple, in my lit­tle hobby-project “Appo­site” (which I have men­tioned in pre­vi­ous posts), I have a num­ber of require­ments around ensur­ing state on appli­ca­tion startup (i.e. bootstrapping).

Now, boot­strap­ping is a clas­sic “non-functional” prob­lem (in so far as it usu­ally does not pro­vide func­tion­al­ity to an end user, merely ensur­ing that the appli­ca­tion is in an ade­quate state to be capa­ble of sub­se­quently deliv­er­ing this) … and, by no coin­ci­dence, it is also the kind of thing that there­fore also often gets left to the end and piled into some unread­able file that suf­fers from vir­u­lent bit-rot.

Alter­na­tively (and a slight improve­ment), the more organised-of-mind will retain the basic script­ing approach but struc­ture it via the use of the Tem­plate Pat­tern:

// abstract class with public *final* method defining algorithm, the individual methods for which may or may not also be abstract
public abstract class AbstractTemplatePattern {

    public final void doSomething() {
        doStepOne();
        Foo resultOfStepTwo = doStepTwo();
        doStepThree(resultOfStepTwo);
    }

    protected void doStepOne() {
        // maybe a default implementation here ...
    }

    protected abstracted Foo doStepTwo();

    protected abstracted void doStepThree(Foo foo);

}

How­ever, whilst this is slightly prefer­able, it is still not really ideal for the boot­strap­ping use case. This is because we expect the “algo­rithm” (i.e. “what needs to be done when boot­strap­ping”) to change with some fre­quency … this is usu­ally the cause of the main­te­nance night­mares that can some­times occur around such activ­i­ties. Whilst scripts can become illeg­i­ble under such cir­cum­stances, the tem­plate pat­tern becomes dif­fi­cult to main­tain because it is pre­cisely intended to rep­re­sent a sta­tic algo­rithm with chang­ing imple­men­ta­tions, whereas our boot­strap is the inverse: a chang­ing algo­rithm with sta­tic imple­men­ta­tions. In both cases, the code unit(s) involved are become sub­ject to change and, con­se­quently, bugs are liable to be intro­duced in the process of change. Asso­ci­ated tests may start to fail, and col­lab­o­ra­tors or sub­classes may be affected in all kinds of ways that are, to put it bluntly, a painful waste of time to deal with.

To talk in terms of pat­terns again, what we really want here are com­mands and a com­mand execu­tor. What we want to be able to do is sim­ply “drop-in” a new chunk of “stuff to do” and be com­fort­able in the knowl­edge that it will get done.

NB. It is not nec­es­sary to cre­ate your own inter­face for the com­mand pat­tern: java.lang.Runnable should always suf­fice, in my view. Use the stan­dard libraries when­ever possible!

We could, of course, use the JSR-250 @PostConstruct anno­ta­tion, sup­ported by Spring, wher­ever we wanted to do some kind of “boot­strap­ping”. How­ever, if we do so in an ad hoc fash­ion, (a) this logic becomes scat­tered through­out the code­base under generic meta­data that makes it more dif­fi­cult to iso­late in the process (b) frag­ment­ing this respon­si­bil­ity and (c) hin­der­ing re-use. There­fore, my approach was as follows …

First, cre­ate an org.apposite.command pack­age as the name­space for all code units that con­sti­tute a com­mand (i.e. they are an imple­men­ta­tion of java.lang.runnable and achieve some given tech­ni­cal require­ment (i.e. guar­an­tee state on com­ple­tion or throw an IllegalStateException on post-condition failure).

Sec­ond, extend the @Component stereo­type to intro­duce a new spe­cial­i­sa­tion, which I decided to call @StartupCommand:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface StartupCommand {

    String value() default "";
}

Sec­ond, imple­ment a java.lang.Runnable for each “thing” that needs to be done on startup. For exam­ple, in Appo­site, for var­i­ous rea­sons I will not bore you with here, I want to “reg­is­ter” the run­time instance that is in the pro­ces of start­ing up with a repository:

@StartupCommand public class RegisterRuntimeInstanceCommand implements Runnable {

    private final AppositeRuntimeInstanceDAO ridao;

    private final String riname;

    @Autowired public DetermineRuntimeInstanceCommand(@Value("${apposite.runtime.instance.name}") String instanceName, AppositeRuntimeInstanceDAO appositeRuntimeInstanceDAO) {
        riname = instanceName;
        ridao = appositeRuntimeInstanceDAO;
    }

    @Override public void run() {
        try {
            InetAddress localhost = InetAddress.getLocalHost();
            ridao.insertOrUpdate(riname, localhost.getHostName(), localhost.getHostAddress());
        } catch (Exception e) {
            throw new IllegalStateException("Runtime instance registration failure", e);
        }
    }

}

Now, for the com­mand execu­tor, we needn’t do any­thing nearly so fancy: we can encap­su­late our boos­t­rap logic (@PostConstruct) into a nor­mal Spring bean which, for the sake of argu­ment, I am going to call a boot­strap “service” …

public interface BootstrapService {

    void startup();

}

My imple­men­ta­tion of which is as follows:

@Service public class BootstrapSpringService implements BootstrapService {

    private static final Logger LOG = getLogger(BootstrapSpringService.class);

    private boolean bootstrap = true;

    private List<Runnable> startupCommands = new ArrayList<Runnable>();

    private final PlatformTransactionManager txmanager;

    @Autowired public BootstrapSpringService(PlatformTransactionManager transactionManager) {
        txmanager = transactionManager;
    }

    @Autowired public void setBootstrap(@Value("${apposite.bootstrap}") boolean bootstrap) {
        this.bootstrap = bootstrap;
    }

    @Autowired(required = false) public void setCommands(List<Runnable> commands) {
        for (Runnable command : commands) {
            if (AnnotationUtils.findAnnotation(command.getClass(), StartupCommand.class) != null) startupCommands.add(command);
        }
    }

    // NB. we cannot use @Transactional here because this is called *before* the creation of the transaction proxies
    @PostConstruct @Override public void startup() {
        if (bootstrap) {
            LOG.info("Bootstrapping Apposite ...");
            TransactionStatus tx = txmanager.getTransaction(new DefaultTransactionDefinition());
            for (Runnable command : startupCommands) {
                LOG.info("Running startup action: " + command.getClass().getName());
                long start = System.currentTimeMillis();
                command.run();
                LOG.info(command.getClass().getName() + " completed in " + (System.currentTimeMillis() - start) + "ms");
            }
            txmanager.commit(tx);
            LOG.info("Bootstrap complete.");
        }
    }

}

As a result, I can very eas­ily deter­mine what is sup­posed to hap­pen at startup and where. More­over, nei­ther the boot­strap “ser­vice” nor any of the indi­vid­ual com­mands will be sub­ject to change when, as I expect, addi­tional boot­strap logic is added in future. As a fringe ben­e­fit, the intent of the code is described with greater seman­tic force through the util­i­sa­tion of a spe­cific spe­cial­i­sa­tion annotation.