Butterfly DI Container 2.7.9-beta
Butterfly DI Container is an ultra lightweight Java dependency injection container. It supports pretty much all the most commonly used DI features. Butterfly DI Container is different from Spring in that it uses a DI specific script language for its configuration, allowing configurations to be very dense, and look more like ordinary Java code.
Butterfly Container is part of a small application stack called Butterfly Components. Butterfly Components contains a persistence API, a component based web framework, and a mock testing API too. More lightweight components may be added in the future.
Butterfly Container 2.7.9-beta adds support for using Butterfly Container Script as application configuration mechanism.
Using BCS for Application Configuration
From version 2.7.9 Butterfly Container Script (BCS) has support for using it as a general purpose application configuration mechanism, and not just for wiring objects. This text describes how to do this.
Here is a list of the topics covered in this text:
- Application Configuration using Standard Java
- Application Configuration using Butterfly Container Script
- Lists and Hierarchies in Configuration Structures
Application Configuration using Standard Java
Until now, developers have often used either Java property files or XML files for application configuration. Both of these mechanisms forces you to to parse the configuration files into the corresponding configuration objects yourself.
Granted, you don't have to parse the files into String's. That is done for you when you use property files, and it is easy when using XML files. But if you need to convert those String's into objects or primitives (int, long etc.) you need to do that yourself.
Application Configuration using Butterfly Container Script
Using Butterfly Container you can have the configuration parameters injected directly into the components that need them. No parsing of strings into objects or primitives. Butterfly Container does all that for you.
You can even isolate the application configuration parameters in their own configuration file, and still have them injected into the components defined in script files elsewhere. This is a good thing to do, so the administrators of the application only have to be exposed to the part of the application configuration they are supposed to change.
What has changed in Butterfly Container Script in version 2.7.9 is that if you omit the instantion mode, the factory defaults to singleton. Let us first look at an example using the old script format:
noOfThreads = 1 10;
This factory definition defines a factory called noOfThreads which returns the value 10, and the factory's instantiation mode is singleton (set by the first '1' after the '=' and before the '10').
If you understand Butterfly Container Script, this may make sense to you. But imagine that you are an application administrator that needs to configure the application. What does the '1' mean? He or she will have no clue whatsoever. Therefore, it would be nice if the factory definition could omit the instantiation mode, like this:
noOfThreads = 10;
This way, the only difference between this format and the standard Java property file format is the semicolon (';') at the end of the line.
This is what has been made possible from version 2.7.9. So what about the instantiation mode? Well, the most natural default instantion mode for such configuration parameters is singleton. Once the application is running, the configuration parameters rarely change, and since the configuration parameters are most often immutable objects like Long, Integer, String etc, it is okay to share the same intance of that configuration parameter among all components in the application.
It is actually possible to change configuration parameters at runtime, since Butterfly Container allows runtime reloading of script files. You can read how to do that in the text Replacing Factories at Runtime.
Lists and Hierarchies in Configuration Structures
Your first objection against the BCS format may be, that this only works for single value configuration files. That it will be hard to define hierarchical structures. But keep in mind that you can also use lists and maps in BCS. Here are two examples:
emailAddresses = ["email@example.com", "firstname.lastname@example.org"];
serverConfig = <"noOfThreads" : 15,
"noOfConnections" : 15,
"idleTime" : 1000 >;
You can also combine lists and maps to create more complex hierachies.
You can also go all the way, and create a configuration object and have Butterfly Container inject into that, like this:
appConfig = 1 com.jenkov.myapp.Configuration()
myBean = com.jenkov.myapp.MyBean().setIdleTime(appConfig.getIdleTime());
But this of course looks more like code than configuration parameters.
You can also use public members in your configuration object, and set it up like this:
appConfig = 1 com.jenkov.myapp.Configuration();
$appConfig.emailAddresses = ["email@example.com", "firstname.lastname@example.org"];
$appConfig.noOfThreads = 10;
$appConfig.idleTime = 1000;
myBean = com.jenkov.myapp.MyBean().setIdleTime(appConfig.idleTime);
But this too looks a bit more cryptic to the application operator than the simpler property like format. But at least it is possible, and you still don't have to parse anything inside your application. Butterfly Container does all the parsing for you.