Requirements for a Configuration Library

gear
For an application developer, the problem of configuring the system for actual operations is usually not regarded as a complicated issue. Sometimes the code needs some settings, which can not, or should not be hard-coded, so some external source is needed to provide these values. It’s not rocket science.

Still, there are some straight-forward, nice-to-have features, which might make this task even easier, not readily found in mainstream configuration libraries.

API

Arguably the most important aspect should be ease of use. It should be trivial to get the right value at the right time, safely. Let’s start with this design:

connection.setTimeout( config.get("net.timeout") );

We need to set a connection timeout, which we get from the “net.timeout” configuration setting. This approach is very similar to how java.util.Properties works:

connection.setTimeout( properties.getProperty("net.timeout") );

There are however a couple of problems with this design:

  1. What should be the type of the returned value? It can not be always String!
  2. What happens if the value is not available?
  3. How to store the timeout without coupling the value to its usage?

Typed values

The first additional requirement should be to allow for different types of configuration values. Not all values are Strings. The approach most frameworks take, including Commons Configuration, Netflix Archaius and Typesafe’s Config is to offer multiple get() methods for the different types of values, like this:

connection.setTimeout( config.getLong("net.timeout") );

This solves the first problem of typed values, but introduces new problems:

  • Decouples the type from the setting (key), which arguably should not be decoupled. The timeout will always be “long”, it can not be different, it is inherently coupled.
  • It makes it hard to extend the existing vocabulary of types. For example what if we want to introduce Date settings?
  • Makes the API more complex.

Typed-er valuesforms

Let’s specify our requirement in more detail to explicitly disallow the decoupling of type and key, and allow for external extension of supported types. One possible design would look like this:

public interface Configuration {
    <T> T get(Key<T> key);
}

In this design, the key is explicitly linked to the returned type, so it is not possible to use the setting key with the wrong return type, as in the previous design. Also, as the key is just an interface, it is left open for external implementations. Any types can be easily implemented.

The connection example would then look like this:

public static final Key<Long> NET_TIMEOUT_KEY = ...;

...
connection.setTimeout( config.get(NET_TIMEOUT_KEY) );

If we assume that the implementation of the Configuration itself would probably have to support different storage/retrieval mechanisms, including file and database perhaps, it would be easier to have all settings be mapped to a String form. This is an easy task if the available types are predetermined by the library, as in the libraries above, but here there might be any number of types, even complex ones that may contain multiple fields. To get around this problem, let’s extend the Key to be able to serialize the value it represents:

public interface Key<T> {
   String getName();

   String serialize(T value);

   T deserialize(String serializedValue);
}

This way, any Configuration implementation would only have to concentrate on storing and retrieving Strings as keys as well as values.

Defaults

What happens if the configuration setting is not found in the backing storage? Should the API return null for example? The practical problem with that is, that the caller would have to always check for null then, for all settings. This would be cumbersome and error prone:

Long timeoutMillis = config.get(NET_TIMEOUT_KEY);
if (timeoutMillis != null) {
   connection.setTimeout(timeoutMillis);
} else {
   connection.setTimeout(1000l);
}

This is ugly, and far from our original goal of doing it as a one-liner. An alternative would be to use Optional to signify that the setting might be missing:

import java.util.Optional;

public interface Configuration {
    <T> Optional<T> get(Key<T> key);
}

Which could be used the following way:

connection.setTimeout( config.get(NET_TIMEOUT_KEY).orElse(1000l) );

The libraries above take a similar, but alternative approach by requiring the default value right in the getter method:

connection.setTimeout( config.get(NET_TIMEOUT_KEY, 1000l) );

It is a little bit more compact, arguably less readable. Also, this approach may require an additional method to be defined to determine whether a setting is given or not:

import java.util.Optional;

public interface Configuration {
    boolean isSet(Key<?> key); // In place of Optional.isPresent()

    <T> Optional<T> get(Key<T> key);
}

There is a third approach, if we realize that the default value, similarly to the type of the value, is not related to the usage, but to the setting (key) itself. In other words, the default value needs to be specified for the “net timeout” setting, and not for the connection.setTimeout() call. This means the default value can be moved to the Key:

public interface Key<T> {
   String getName();

   T getDefault(); // Get default value for this key

   String serialize(T value);

   T deserialize(String serializedValue);
}

In which case the code becomes simple again:

connection.setTimeout( config.get(NET_TIMEOUT_KEY) );

Unitsmeter

There is an aspect of the above connection example, which we didn’t address yet. The timeout value is not really a Long, it is a Duration. The difference might be small, but significant. If the setting is a long value, we still don’t know in what unit it is given in. Is it seconds? Milliseconds? Hours?

Usually we end up with settings like this:

net.timeout = 30 // Is this seconds or milliseconds?

There is no way to decide what this means, other than to look into the code. This might not be possible for colleagues from Operations for example. In other words the configuration is coupled to the implementation of where this setting is used.

How could we decouple the usage from declaration? Simply write the unit used in the configuration into the configuration itself:

net.timeout = 30ms

This unit is completely independent of the unit used in the code. The Typesafe Config’s file format HOCON allows this specifically for durations and sizes (B, KB, MB, etc.), but is not extendable to other units.

Since our current design allows extensions, it would be easy to write a DurationKey which can parse and emit such declarations, or for any other unit types.

To use such settings, the unit-independent Duration must be converted to the desired unit:

connection.setTimeout( config.get(NET_TIMEOUT_KEY).toMillis() );

This would not have to change, even if we would change the setting in the configuration to a seconds-based value.

Dynamic settings

Dynamic settings are values that can change during runtime, at any time. Normally it is thought of as settings that must trigger an immediate change in the application behavior, i.e. to read and apply the new value as soon is it available.

This usually takes the form of registering callbacks to handle changed values, like in the case of Netflix’s Archaius:

config.getIntProperty("net.timeout"), 1000l).addCallback(
   () -> { ...re-apply new value... }
);

As this feature would complicate the API, and might also be quite difficult to implement in a distributed environment correctly, it must be evaluated whether such a feature is worth the effort at all. There are some arguments to be made, that such a feature is usually not needed.

The first argument is, that pieces of code that regularly use configuration values should just query those values directly each time, instead of storing them. For example each time a connection is created, ask for the current value of the timeout directly. This puts some burden on the configuration implementor to provide a very efficient query/cache mechanism internally, but relieves the user from having to specifically prepare for updates, and having to think about threading issues with asynchronously changing values.

There are settings however which are actually only asked for a few specific times, for example on startup, such as the maximal size of a pool. To dynamically change this setting, the pool has to prepare for the change explicitly. This should be however not much more complicated than writing the callback handler above anyway.

Summary

The summary of requirements made in this article to produce a generic configuration library are:

  • API should be easy enough to use inline
  • It should support multiple setting value types
  • The setting key and type should be coupled
  • Value types should be extendable externally
  • Always require default values, do not return null on missing settings
  • Decouple default values from call sites
  • Allow for implementing specific custom units for values (such as duration, length, size, etc.)
  • Allow for getting settings efficiently, possibly thousands of times per second.

One possible interface design:

public interface Key<T> {
   String getName();

   T getDefault();

   String serialize(T value);

   T deserialize(String serializedValue);
}

public interface Configuration {
   boolean isSet(Key<?> key);

   <T> T get(Key<T> key);
}
Requirements for a Configuration Library

Magic-less Dependency Injection with JayWire

JayWire is a small, easy to use magic-less Dependency Injection library for Java 8. This article is a short tutorial on how to get started using it in projects of any size from small single- to large multi-module ones.

Why another Dependency Injection library?lego_brick

Interestingly enough, the key feature of JayWire is not that it can supply objects as dependencies to other objects, nor that objects may be defined to have a scope (such as singleton scope, request scope, etc.). These are all supported by every other DI framework out there.

The distinguishing characteristic of this library is that it doesn’t use “Magic” to achieve these features, and is therefore easier to understand, less restrictive about objects it can work with, and the architectures it can support.

Specifically, following technical solutions all count as “Magic”, and are avoided in JayWire:

  • Classpath-scanning
  • Reflection
  • Annotations
  • Bytecode enhancement / weaving, AOP
  • Transparent proxy objects
  • Code generation or special compiler plugins
  • Hidden static state

JayWire is therefore 100% Java code, does not force its programming model on the objects in manages, is statically safe, can be debugged or logged if needed, and can be used multiple times in a single JVM.

Problem statement: Dependency Injectionevil_injection

The problem is surprisingly simple actually: Some objects need other objects to work. These “other” objects are called Dependencies, and the act of supplying these Dependencies to the objects that need them is called Injection. It looks like this:

public interface Database {
}

public class PeopleRepository {
   public PeopleRepository(Database database) {
      ...
   }
}

In this snippet, PeopleRepository depends on a Database to work, therefore Database is a dependency of PeopleRepository. This is how injection then looks like:

new PeopleRepository(new SomeDatabaseImpl(...));

Please note that neither the definitions of these classes, nor the injection code requires any “framework” or “library” to work. Also note, that the class definitions do not need to know at all how the injection will happen, nor do they need to know what scopes they will be in inside a specific application.

The Application Startup

At some point during the startup of an application, all objects that are needed to “start” the application need to be instantiated, with all of their dependencies, and the dependencies of the dependencies recursively.

In container-based environments, such as in CDI or Spring, this process is implicit and hidden from the developer. It is however relatively easy to make this important part of the application explicit, and with it, put it under the control of the developer. Let’s try to write the application’s “wiring” class, still without any frameworks, to instantiate all objects for startup. Assuming we are trying to start a Web Server with two published Services, this is how it would look:

public class MyApplication {
   public PeopleRepository getPeopleRepository() {
      ...
   }

   public GroupRepository getGroupRepository() {
      ...
   }

   public WebServer getWebServer() {
      return new WebServer(getPeopleRepository(), getGroupRepository());
   }
}

Please note, that the WebServer has two dependencies and both are “injected” using plain old method calls. No magic needed here. MyApplication can be started then with the following code:

new MyApplication().getWebServer().start();

Unfortunately both repository objects still depend on the Database, so that needs to be added:

public class MyApplication {
   public Database getDatabase() {
      ...
   }

   public PeopleRepository getPeopleRepository() {
      return new PeopleRepository(getDatabase());
   }

   public GroupRepository getGroupRepository() {
      return new GroupRepository(getDatabase());
   }

   ...
}

“Singletons” with JayWiresingleton

The challenge here is to implement the getDatabase() in a way, that will instantiate the database only once, and return the same instance for all subsequent calls, because normally the instance would pool the connections to the database, maybe synchronize calls, etc. This can still be done without any frameworks:

public class MyApplication {
   private Database database;

   public synchronized Database getDatabase() {
      if (database != null) {
         database = new SomeDatabaseImpl(...);
      }
      return database;
   }

   ...
}

This is arguably the point when the boilerplate becomes uncomfortably big and error prone. Instead of throwing out our otherwise perfectly good initialization code, JayWire can step in here, and solve this single problem without forcing another programming model on all other objects.

public class MyApplication extends StandaloneModule {
   public Database getDatabase() {
      return singleton( () -> new SomeDatabaseImpl(...) );
   }

   ...
}

Through extending the StandaloneModule, JayWire offers the method singleton(), which takes a “factory” that can instantiate the specific object. This factory can be easily implemented using lambda expressions as seen above. JayWire will use the factory to instantiate the database on the first call, and use the factory as key to return the same instance on all subsequent calls.

Please note, that the information whether the database is a singleton does not reside in the database implementation. Also note, that the database implementation was not changed, not even with an annotation, and therefore does not depend in any way on JayWire.

Dynamic objects

Most traditional “scopes” are supported:

  • Singleton
  • ThreadLocal
  • Request
  • Session

The “singleton” scope will not produce a static singleton (one instance per JVM), but a singleton relative to the Application instance. The request and session scopes are only available if bound to a web context (see JayWire Integration).

Sometimes, when scope boundaries are crossed between object and its dependency, a statically injected object is not enough. Consider following code:

public class OrganizationService {
   public User currentUser;

   public OrganizationService(User currentUser) {
      this.currentUser = currentUser;
   }

   public List<Employee> getSubordinates() {
      return currentUser.getSubordinates();
   }
}

The problem with this piece of code is, that OrganizationService is a singleton, and the current user is a session scoped object. Therefore injecting a static User object does not work. Other DI frameworks usually solve this problem by not really injecting a User object, but a transparent proxy, which again, hides important information from the developer.

To make this underlying difference between the service and user visible, the code can be changed to this:

import java.util.function.Supplier;

public class OrganizationService {
   public Supplier<User> currentUserSupplier;

   public OrganizationService(Supplier<User> currentUserSupplier) {
      this.currentUserSupplier = currentUserSupplier;
   }

   public List<People> getSubordinates() {
      return currentUserSupplier.get().getSubordinates();
   }
}

With the indirection through a Supplier, the code represents the existing indirection through the Session, without actually depending on the Session. The code can/must therefore explicitly prepare for getting different instances of users, as it should anyway.

The standard scopes in JayWire all support this kind of explicit indirection through a Supplier the following way:

public class MyApplication extends SparkModule {
   public Supplier<User> getCurrentUserSupplier() {
      return sessionScope( () -> new User(...) );
   }

   public OrganizationService getOrganizationService() {
      return new singleton( () -> new OrganizationService(getCurrentUserSupplier()) );
   }
}

Going Multi-Module

To be able to scale up the object graph of the application, it needs to be possible to split the wiring code into different fragments or Modules. To do this, there needs to be a mechanism for defining module-level dependencies, objects which the module needs but does not manage.

Some frameworks, like Spring, have a solution to this (called “external beans” in this case), others, like CDI, just sidestep the issue with implicit “automatic” wiring based on interfaces.

JayWire of course does not only explicitly define inter-module dependencies, but makes them compile-time safe. If some module dependency is not fulfilled, the application will not compile!

The mechanism for this is quite simply abstract methods. Let’s assume a Module contains the previous two repository objects, but does not know what the database implementation should be or how it is instantiated. In this case the Module can be defined as:

public abstract class RepositoryModule extends StandaloneModule {
   public abstract Database getDatabase();

   public PeopleRepository getPeopleRepository() {
      return singleton( () -> new PeopleRepository(getDatabase()) );
   }

   public GroupRepository getGroupRepository() {
      return singleton( () -> new GroupRepository(getDatabase()) );
   }

   ...
}

Obviously this Module can not be instantiated as long as the Database dependency is not defined explicitly somewhere higher up the module dependency tree.

Dependency on Scopes

One problem with the above Module is that it extends the StandaloneModule directly to be able to access the standard JayWire scopes. This dependency is wrong most of the time, since a Module does not need to know whether the application it will be included in will be a standalone application, a JEE application, or a Spark application.

To avoid directly depending on a specific integration class, JayWire offers interfaces for all standard scopes, which can be used the following way:

public abstract class RepositoryModule implements SingletonScopeSupport {
   public abstract Database getDatabase();

   public PeopleRepository getPeopleRepository() {
      return singleton( () -> new PeopleRepository(getDatabase()) );
   }

   public GroupRepository getGroupRepository() {
      return singleton( () -> new GroupRepository(getDatabase()) );
   }

   ...
}

This Module still defines the same objects, but now has a “dependency” on the singleton scope (there is an abstract getSingletonScope() method through the SingletonScopeSupport interface), which somebody higher up has to provide, quite similarly to how a Database needs to be provided. So basically Scopes can be thought of as ordinary dependencies themselves.

Combining Modulespuzzle

To start an application, all the relevant Modules need to be used, with all the missing dependencies filled/implemented at this point, including the Scope objects themselves.

Combining multiple Modules through inheritance is not possible, since that would be multiple inheritance. Combining multiple Modules through composition, while possible, would be quite complicated and redundant. Java 8 however offers another (though still admittedly controversial) approach: Mixins.

Since the Modules themselves do not define any instance variables, only methods to create objects, it is possible to convert them to interfaces with default methods:

public interface RepositoryModule extends SingletonScopeSupport {
   Database getDatabase();

   default PeopleRepository getPeopleRepository() {
      return singleton( () -> new PeopleRepository(getDatabase()) );
   }

   default GroupRepository getGroupRepository() {
      return singleton( () -> new GroupRepository(getDatabase()) );
   }

   ...
}

This Module still contains the same knowledge, but now as a pure interface, and therefore can be combined freely.

At the top of the dependency graph, all the Modules can be combined in the following way:

public class MyApplication extends SparkModule implements
   RepositoryModule, DatabaseModule, WebPagesModule {

   @Override
   public Database getDatabase() {
      return getSomeSpecificDatabase();
   }
}

The Scopes are provided by extending a specific integration implementation of JayWire, and the application Modules are “mixed-in” through the interfaces implemented.

At this point, the decision can be made what database to use for the repository objects, and with that all dependencies are available to instantiate MyApplication. Please note, that if any dependencies are missing the compiler would indicate an error immediately.

Summary

This tutorial shows how JayWire can be used to explicitly and safely wire objects graphs of arbitrary size together. The resulting code is not only compile-time safe, but avoids magical tools that would make the process less transparent and less readable, and also does not impose any programming models or life-cycle restrictions on the objects used.

JayWire is available on GitHub: https://github.com/vanillasource/jaywire

Additional topics at GitHub Wiki: https://github.com/vanillasource/jaywire/wiki

 

 

Magic-less Dependency Injection with JayWire

A story of Checked Exceptions and Java 8 Lambda Expressions

lambda-throws-150Image you are writing a small, awesome Transaction Management library to be used in a project you are working on. You want to provide an easy and safe way for your colleagues to get an SQL Connection from the current transaction, use it, and then close it when the processing is done. The very first draft could very well look like this:

public interface Transaction {
   Connection open();
}

As the Connection implements AutoCloseable, the intended usage of the Transaction object is a “try-with-resources” construct:

try (Connection connection = transaction.open()) {
   ...work with connection...
}

This guarantees that connections are always closed. Job well done, right? Well…, if the developer remembers to use connections exactly this way, always, even if sometimes it would be convenient to do otherwise, even next year, and the year afterwards, and actually not just current developers but all developers who might later join the team, and so on. On second thought, maybe we could still improve the API of this awesome library to make it more safe, less prone to misuse?

Starting down the rabbit hole…

The new Java 8 features may hold some new ideas how to approach this problem. The streams API for example builds on the idea, that developers do not have to write loops to iterate a list anymore, rather the logic how to process items of a list need to be passed into the list (or its stream) itself.

So applying that strategy to the Transaction object, we might want the users of this API to pass in the logic to work with the connection, instead if “leaking” the connection out to the user:

import java.util.function.Consumer;

public interface Transaction {
   void open(Consumer<Connection> logic);
}

The Consumer is a standard Java 8 class that only has one method “accept()“, and returns nothing. The intended usage then does not include a “try-with-resources” construct, instead it involves passing the logic into the transaction:

transaction.open(connection -> {
   ...work with connection...
});

The Transaction class could be then implemented to contain the connection closing part:

public class DataSourceTransaction implements Transaction {
   @Override
   public void open(Consumer<Connection> logic) {
      try (Connection connection = dataSource.getConnection()) {
         logic.accept(connection);
      }
   }
}

The result is, that you can centralize the safety aspect of closing the connection independently of what the logic is, independently of how the connection will be used. This way developers don’t have to remember anything.

At this point you might give yourself a pat on the back for making the world a better place, with your new, shiny library. Well…, until you try to compile it.

Exceptions along the waymadhat

Unfortunately the library as shown above won’t compile, because “getConnection()” throws “SQLException“, and that means “open()” also needs to throw it. But, thinking about exceptions, isn’t it the case that whatever logic tries to work with the provided connection also sometimes need to throw “SQLException“? Yes, of course. Creating and executing statements on the connection certainly throws “SQLException“, so it must be declared somehow for the logic too. Unfortunately the Consumer is defined this way:

public interface Consumer<T> {
   void accept(T t);
}

There are no exceptions there, so basically this interface is not up to the task, you have to write a new one like this:

public interface SQLConsumer<T> {
   void accept(T t) throws SQLException;
}

That would work in this case, but there may be other cases where you would perhaps like to allow for different exception types, so let’s make the exception type generic:

public interface ThrowingConsumer<T, E extends Exception> {
   void accept(T t) throws E;
}

Is that actually allowed? Well, it turns out it is, you can define generic exceptions, and the Java 8 compiler will even try to infer the exception type from the code if it can. This means, the transaction can be modified to:

public interface Transaction {
   void open(ThrowingConsumer<Connection, SQLException> logic) throws SQLException;
}

Yay, the code compiles! Everything still works, although you have made a small compromise of not using the standard classes, but this is a small price to pay for such the coolest API ever.

Other people’s exceptions

Everything seems to work fine, until somebody actually tries to use the library. Your colleague just made a small utility that reads lines from a file, and puts them into the database. The problem is, it can not be compiled because the logic she implemented throws “IOException” in addition to “SQLException“.

This is bad. Because your class is now responsible for running any fool’s code that can throw basically any exception, that would mean that the transaction’s “open()” method could actually throw any kind of exception depending on what logic is given.

It can even get worse than that! What if the logic throws multiple different exceptions? What if it throws IOException, ClassNotFoundException, or a bunch of application specific ones? At this point, there may be multiple strategies to deal with this problem:

  1. Just declare everything to throw Exception, the base class of all exceptions, this way, everything can throw anything.
  2. Catch everything and rethrow as RuntimeException, basically making everything an unchecked exception.
  3. Try to stick with generics a little bit further, and declare multiple exceptions, not just one.

The first “solution” obviously does not really solve the problem, and sooner or later makes everything declare Exception in the “throws” clause. This arguably defeats the purpose of checked exceptions.

The second solution also defeats the purpose of checked exceptions, but in exactly the opposite way: Nothing (or at least very few methods) would declare checked exceptions, because everything would tend to be unchecked after some point.

Generics to the rescue?

Let’s try to explore a third solution for now. If one exception is not enough, maybe multiple exceptions will do? What if ThrowingConsumer would declare 5 generic exceptions, instead of one?

public interface ThrowingConsumer<T, E1 extends Exception, E2 extends Exception, E3 extends Exception, E4 extends Exception, E5 extends Exception> {
   void accept(T t) throws E1, E2, E3, E4, E5;
}

You are probable asking: why 5? Well, “five exceptions should be enough for everybody” I say to that, and you can quote me on that one, I’m pretty sure it will never come back to haunt me.

So now, the transaction’s open() method just needs to take these generic exception types, and rethrow them:

public interface Transaction {
   <E1 extends Exception, E2 extends Exception, E3 extends Exception, E4 extends Exception, E5 extends Exception>
   void open(ThrowingConsumer<Connection, E1, E2, E3, E4, E5> logic) throws SQLException, E1, E2, E3, E4, E5;
}

Your only hope at this point, is that following code will somehow magically work:

transaction.open(connection -> {
   if (1==2) {
      throw new IOException("test");
   }
   if (1==3) {
      throw new SQLException("test");
   }
});

In turns out, that this does not work as expected. The Java 8 type inference is not that clever to know that the signature of the lambda expression could take 2 different exception types. Instead, it infers that the lambda expression should throw Exception, the greatest common superclass of both exception types. Too bad.

The only way left to make this work, is to “help” the type system by not leaving this decision up to the type inference engine, but to the developer to specify the exact type of exceptions to throw. This could be done with helper methods:

// Method to construct a logic without exceptions
public <T>
       ThrowingConsumer<T, VoidException, VoidException, VoidException, VoidException, VoidException>
       throwing(ThrowingConsumer<T, VoidException, VoidException, VoidException,  VoidException, VoidException> logic) {
          return logic;
}
// Construct with 1 exception
public <T, E1 extends Exception>
       ThrowingConsumer<T, E1, VoidException, VoidException, VoidException, VoidException>
       throwing(
          Class<E1> e1Class,
          ThrowingConsumer<T, E1, VoidException, VoidException, VoidException, VoidException> logic) {
             return logic;
}
// Construct with 2 exceptions
public <T, E1 extends Exception, E2 extends Exception>
       ThrowingConsumer<T, E1, E2, VoidException, VoidException, VoidException>
       throwing(
          Class<E1> e1Class, Class<E2> e2Class,
          ThrowingConsumer<T, E1, E2, VoidException, VoidException, VoidException> logic) {
             return logic;
}
// And so on for all 5 exceptions

If you still have your sanity, you might try implementing the previous example with these helper methods:

transaction.open(throwing(IOException.class, SQLException.class, connection -> {
   if (1==2) {
      throw new IOException("test");
   }
   if (1==3) {
      throw new SQLException("test");
   }
}));

Yes it works! The compiler says that the open() method actually throws both exact exception classes, not the Exception superclass. This is a breakthrough! Maybe sanity is also a small price to pay? Anyway, your colleagues will love this for sure!

The Void of Exceptions

Since we declare all 5 exceptions as generic parameters in the ThrowingConsumer, there is a small problem of how to express if actually only one exception is thrown for example. The other generic parameters still need to be supplied, so maybe they could be RuntimeExceptions. Those are by definition unchecked exceptions, so they don’t have to be declared at the caller site. There is however a small problem that the intention gets lost in the noise. The intention being not to throw any additional exceptions.

This situation is similar to return values from methods. If a method does not return anything, we can say its return type is “void“. We know that void does not have any instances, so the intention of not returning anything is very clear. Well, the same can be done for exceptions too:

public class VoidException extends RuntimeException {
   private VoidException() {
   }
}

That’s it! It is a RuntimeException, so it does not need to be declared, and it has a private constructor, so it can not be instantiated at all. Which means this exception can never be actually thrown.

This is why the ThrowingConsumer declares all “unused” exception parameters as VoidException.

Lost in the Labyrinthlabyrinth

This all seem well and good, provided you are ready to surrender your sanity, and don’t mind your colleagues cursing your name. But unfortunately there are still technical problems with this solution, which becomes apparent if you try to extend the library a little bit.

What if a use-case comes up to be able to put a “finally” block into the transaction? Basically a developer wants to supply a “main” logic, and another logic, that will always be executed at the end, but still within the same transaction? You would have to define a new method, which takes 2 logic arguments this way:

   <E1 extends Exception, E2 extends Exception, E3 extends Exception, E4 extends Exception, E5 extends Exception,     F1 extends Exception, F2 extends Exception, F3 extends Exception, F4 extends Exception, F5 extends Exception>
   void open(
      ThrowingConsumer<Connection, E1, E2, E3, E4, E5> logic
      ThrowingConsumer<Connection, F1, F2, F3, F4, F5> finallyLogic
   ) throws E1, E2, E3, E4, E5, F1, F2, F3, F4, F5;

Although that looks horrible, it actually works for this specific case. The problem is that the open() method now has to declare 10 exceptions, 5 for each of the two logic parameters, of which we don’t know which ones are used. So any usages of this method can not be inside another such construct, for example in the case of an embedded transaction. In other words, this solution resists (function) composition, therefore ultimately becomes useless.

This is the point where a good player needs to fold. The root of the problem is, that exceptions behave differently than other type parameters. They somewhat resemble varargs, but with each position potentially having a different type. There is unfortunately no way to properly handle this characteristic with the current generics syntax.

Escape / Conclusion

It seems that there is no practical way to actually use checked exceptions together with lambda expressions consistently. This is the unfortunate state of affairs at the moment, whether it is a deliberate omission from the Java language architects, or a simple oversight, does not really matter.

There are two practical possibilities to deal with checked exceptions, either throw the superclass “Exception” and let implementations define a smaller subset if they can, or just make everything an unchecked exception. Even the Java SDK is not consistent on this decision, some classes like AutoCloseable take the former solution, while others, like most of the functional interfaces take the latter approach.

These are therefore the same options the we developers have, at least until a proper language feature is introduced to correctly deal with this issue, or checked exceptions become completely deprecated.

A story of Checked Exceptions and Java 8 Lambda Expressions

Evil Annotations

When Java 1.5 introduced Annotations, Enteevil_annotationrprise Developers had high hopes that it would make their life developing EJBs and other Enterprise Artifacts much easier. See for example this contemporary article: Simplify enterprise Java development with EJB 3.0.

Since then however, using Annotations the way Java Enterprise started to use them had some unforeseen consequences and side effects, which still go almost unnoticed today. Fortunately not completely unnoticed, see for example this completely valid comment on Stackoverflow titled “Why Java Annotations?“, this article with very good points: “Are Annotations Bad?“, and others: “Magics Is Evil“, “Annotations…Good, Bad or Worse?“.

Not All Annotations Are Created Equal

Although the above discussions do address many valid points, not all Annotations are the same.

There are two categories of Annotations depending on whether they have any influence on the runtime behavior of the program. First, there are the harmless types, which have no impact on running code at all, and there are the evil ones, which modify runtime behavior. Examples for harmless Annotations include: @Deprecated, @Override, @SuppressWarnings, and so on. Evil Annotations include: @Entity, @Table, @PostConstruct, @ApplicationScoped, etc.

Additionally there is a subset of the harmless Annotations, which are positively useful. These are the ones that offer some kind of additional (statically checked) functionality compile-time to catch some error or safety issue. Useful Annotations are for example: @Override, @NonNull/@Nullable (from the Checker Framework), etc.

Why are evil Annotations bad?

Aside from having defined a subset of Annotations evil, why would one want to avoid using them?

Just image if the standard Java Date class would have a @PostConstruct method. This Annotation denotes that the said method should be invoked right after the construction of the object is done. This functionality is not handled by the JVM itself, so right off the bat the Date class implicitly pulls some yet unknown framework or container that actually has nothing to do with the Date itself semantically. What if the consuming code does not run in any Container, just the plain JVM? This Annotation effectively reduces the reusability of the class significantly. Additionally it would be a nightmare to unit-test anything using Date, because now you have to make sure the post-construction is triggered somehow each time, simulating a compatible container. This might seem ridiculous to consider, a Date class needing a Container to run, but this is exactly what evil Annotations force on classes, methods and parameters.

Admittedly, business logic is often more complex, has more dependencies and relations than a relatively simple Date class. However, that does not in any way excuse unnecessary explicit or implicit dependencies or constraints within a class, and evil Annotations are just that: dependencies and constraints.

The Enterprise Trap

Unfortunately evil Annotations were largely legalized by Java Enterprise 5. Although a lot of businesses did invest in Java Enterprise on both the provider and user sides, which made it on a purely market share point of view a success, up until JEE 5 developers largely tried to avoid it in favor of Spring, which was much more lightweight and (compared to the alternative) a breeze to use.

Let us also remember however, that the goal of Java Enterprise was to have “reusable business components” and in this sense it failed completely. Even today, with the newest release, no one actually downloads a “ShoppingCart” EJB from the Maven Repository, which is then “Assembled”, “Configured” and “Deployed” by the various Enterprise Developer Roles.

So with this goal basically abandoned, the JEE 5 release concentrated on winning back the developers by making EJBs much more approachable and usable, this is where Annotations came in. This actually moderately succeeded, thereby legalizing much of the questionable architecture decisions (see below).

The biggest selling point was, that the new release is lightweight and simple, which on the outside seems true, but is nonetheless a slight but crucial misrepresentation of what is really going on.

@Stateless
public class DocumentRepository {
   public Document getDocument(String title) {
      ...
   }
   ...
}

So, to get a Stateless EJB, one has to “only” annotate a class with a @Stateless Annotation. While it is true that the actual action of writing this class is simple enough, please notice that with this evil Annotation this class is now bound to a couple of hundred pages of specification which can only be implemented with a couple of hundred megabytes of software called the Application Server. It is not, in any meaningful sense of the word “lightweight”. So this Annotation became a placeholder for actual Java Code that previously needed to be written, but instead of simplifying the framework and specification itself, still needed to be there in some form. So it was hidden under an Annotation.

Unfortunately, this workaround became a pattern, and now evil Annotations are legally everywhere: JPA, CDI, Common Annotations, JAXB, etc.

Evil Annotations are sometimes in the wrong place

Precisely because they are mostly workarounds, sometimes evil Annotations are regarded as exempt from basic programming best-practices such as Single Responsibility Principle or Separation of Concerns.

Let’s consider the following example from CDI:

@ApplicationScoped
public class DocumentFormatter {
   ...
}

The above Annotation describes that this class should be a CDI Bean, that is, its instantiation should be exclusively handled by CDI and additionally there should be only one instance per application.

This information does not belong in this class. The functionality of this service (whatever that may be) has nothing to do with how it is used in the current application. These are two very distinct concerns.

A similar example from JPA:

@Entity
@Table("PERSON")
public class Person {
   ...
}

This in itself is not problematic, but problems arise when this Person is reused as a domain model object. If this is a domain object, than it should not be responsible for persistence too. If this is not a domain object, but purely persistence object, then usually its data has to be shuffled into a very similar object, sometimes called a Data Transfer Object, either through copy-paste or through reflection-based libraries. Either way, this is a wrong approach.

All of these additional functionalities and/or information should be external to these classes, but they get a pass because they are “only” Annotations.

Evil Annotations are sometimes contagious

evil_injection

Annotations sometimes infect other objects. Consider the CDI Bean above. Every other object which uses this one, and every dependency this Bean uses must be annotated now with one of the CDI Annotations, otherwise the dependency tree can not be constructed.

The @Entity Annotation does the same. Every other object now that needs to be persisted needs to be annotated and because there are relationships between these objects, sooner or later all persisted objects will have this Annotation. There is no room for using third party objects natively (other than serializing or wrapping them), no room to use other persistence mechanisms (like pushing some objects to a NoSQL DB).

These Annotations are effectively making these objects non-reusable. They are only usable in a very strict, controlled, opaque  environment, that can not be integrated with anything else.

What are the alternatives?

Is it XML? No it definitely isn’t, at least for the examples above.

The Spring Framework for example contends that plugging objects together is configuration and therefore can be outsourced to XML configuration files. However, does a certain dependency really need to be changed runtime or without recompiling? If it does not, it’s hard to argue that it should be externalized into something that is effectively a whole other language, that can not be refactored easily, can not be tested easily and can not be managed without specific tools.

The real alternative is of course good old Java Code, properly encapsulated and separated. Yes, code that plugs objects together, although sometimes regarded as boilerplate, is not bad. It makes the code readable, debuggable, refactor-able, which is good! Only long, complicated, redundant boilerplate is bad, for example “Read all about EJB 2.0“. But the solution is not to get rid of all boilerplate or to hide the boilerplate into another language, rather than to have a clear and simple architecture that requires no more information than it needs in a straightforward, preferably object-oriented and easy way.

The same applies of course to JPA, Spring and others too. Instead of misusing Annotations to express functionality that may result in classes and methods like in this Stackoverflow question: “Arguments Against Annotations“, why not use the tools that are already given: the Java Language and its Compiler, to solve these problems the “old fashioned” way, using object-orientation and software design best-practices?

Summary

An Annotation is evil, if it represents some additional functionality or constraint that alters runtime behavior of code. This is bad, because it hides aspects of a class or method and therefore makes the Code harder to understand, reuse, debug, refactor and to test.

Unfortunately Java Enterprise largely desensitized the Java Developer Community  against such misuses of Annotations and so there is little hope that subsequent specifications of Enterprise Java or other “official” frameworks  will address these issues.

What can be done however, is to be on the lookout for evil Annotations, avoid them if possible, and to write new frameworks and software which replace those that won’t recognize these problems.

 

Evil Annotations