Tuesday, August 26, 2014

Existing Configuration Solutions

Existing Application Configuration Solutions

Within this blog I try to give some details on existing common configuration mechanisms in place. If I miss something, let me know, so I can add it here. Also not that the ordering of the section in this blog is completely random, it does not reflect any valuation from my side.

Also I explicitly do not focus on deployment configuration such as EJB deployment descriptors, CDI beans configuration, resource configuration, configuration for JPA, Bean Validation, web applications etc. This may be covered in another blog.

1. Play Framework

See http://www.playframework.com/documentation/2.0/Configuration

The default configuration file of a Play 2.0 application must be defined inconf/application.conf. It uses the HOCON format ( “Human-Optimized Config Object Notation”).

These system properties specify a replacement for application.conf. In the replacement config file, you can use include “application” to include the original default config file; after the include statement you could go on to override certain settings.

HOCON Syntax

Its basically a simplified JSON-Format with some changes, but not compatible with pure JSON.
  • Comments, with # or //
  • Allow omitting the {} around a root object
  • Allow = as a synonym for :
  • Allow omitting the = or : before a { so foo { a : 42 }
  • Allow omitting commas as long as there's a newline
  • Allow trailing commas after last element in objects and arrays
  • Allow unquoted strings for keys and values
  • Unquoted keys can use dot-notation for nested objects, foo.bar=42 means foo { bar : 42 }
  • Duplicate keys are allowed; later values override earlier, except for object-valued keys where the two objects are merged recursively
  • include feature merges root object in another file into current object, so foo { include "bar.json" }merges keys in bar.json into the object foo
  • include with no file extension includes any of .conf, .json, .properties
  • you can include files, URLs, or classpath resources; use include url("http://example.com") or file()or classpath() syntax to force the type, or use just include "whatever" to have the library do what you probably mean (Note: url()/file()/classpath() syntax is not supported in Play/Akka 2.0, only in later releases.)
  • substitutions foo : ${a.b} sets key foo to the same value as the b field in the a object
  • substitutions concatenate into unquoted strings, foo : the quick ${colors.fox} jumped
  • substitutions fall back to environment variables if they don't resolve in the config itself, so ${HOME} would work as you expect. Also, most configs have system properties merged in so you could use ${user.home}.
  • substitutions normally cause an error if unresolved, but there is a syntax ${?a.b} to permit them to be missing.
  • += syntax to append elements to arrays, path += "/bin"
  • multi-line strings with triple quotes as in Python or Scala
Examples:
foo {
    bar = 10
    baz = 12
}
foo.bar=10
foo.baz=12

2. Typesafe Config Library

  • Formats supported: Java properties, JSON, and a human-friendly JSON superset.
  • merges multiple files across all formats
  • can load from files, URLs, or classpath
  • users can override the config with Java system properties
  • converts types, so if you ask for a boolean and the value is the string "yes", or you ask for a float and the value is an int, it will figure it out
  • Supports substitutions
  • API based on immutable Config instances, for thread safety and easy reasoning about config transformations
  • API Example
Config conf = ConfigFactory.load();
int bar1 = conf.getInt("foo.bar");
Config foo = conf.getConfig("foo");
int bar2 = foo.getInt("bar");
The convenience method ConfigFactory.load() loads the following (first-listed are higher priority):
  • system properties
  • application.conf (all resources on classpath with this name)
  • application.json (all resources on classpath with this name)
  • application.properties (all resources on classpath with this name)
  • reference.conf (all resources on classpath with this name)
The idea is that libraries and frameworks should ship with a reference.conf in their jar. Applications should provide an application.conf, or if they want to create multiple configurations in a single JVM, they could useConfigFactory.load("myapp") to load their own myapp.conf. (Applications can provide a reference.conf also if they want, but you may not find it necessary to separate it from application.conf.)
Finally it supports configuration merging based on so called fallbacks:
Config devConfig = originalConfig
                     .getConfig("dev")
                     .withFallback(originalConfig)

3. Spring


Spring Boot allows you to externalize your configuration so you can work with the same application code in different environments. You can use properties files, YAML files, environment variables and command-line arguments to externalize configuration. Property values can be injected directly into your beans using the @Value annotation, accessed via Spring’s Environment abstraction or bound to structured objects.
Spring Boot uses a very particular PropertySource order that is designed to allow sensible overriding of values, properties are considered in the the following order:
  1. Command line arguments.
  2. Java System properties (System.getProperties()).
  3. OS environment variables.
  4. A RandomValuePropertySource that only has properties in random.*.
  5. @PropertySource annotations on your @Configuration classes.
  6. Application properties outside of your packaged jar (application.properties including YAML and profile variants).
  7. Application properties packaged inside your jar (application.properties including YAML and profile variants).
  8. Default properties (specified using SpringApplication.setDefaultProperties).
SpringApplication will load properties from application.properties files in the following locations and add them to the Spring Environment:
  1. A /config subdir of the current directory.
  2. The current directory
  3. A classpath /config package
  4. The classpath root
In addition to application.properties files, profile specific properties can also be defined using the naming convention application-{profile}.properties.

The values in application.properties are filtered through the existing Environment when they are used so you can refer back to previously defined values (e.g. from System properties).
app.name=MyApp
app.description=${app.name} is a Spring Boot application
dev:
    url: http://dev.bar.com
    name: Developer Setup
prod:
    url: http://foo.bar.com
    name: My Cool App

Placeholders and dynamic resolution

Using the @Value("${property}") annotation to inject configuration properties can sometimes be cumbersome, especially if you are working with multiple properties or your data is hierarchical in nature. Spring Boot provides an alternative method of working with properties that allows strongly typed beans to govern and validate the configuration of your application. For example:
@Component
@ConfigurationProperties(prefix="connection")
public class ConnectionSettings {

    private String username;

    private InetAddress remoteAddress;

    // ... getters and setters

}

Uses a Java based variant: 

@Configuration
// @Profile("production")
@EnableAutoConfiguration(exclude={EmbeddedDatabaseConfiguration.class})
public class MyConfiguration {
}

4. Apache Deltaspike

The Apache DeltaSpike configuration system enables providing a default configuration inside the binary and allowing to amend this configuration (e.g. database credentials, some URLs from remote REST or SOAP endpoints, etc) from outside like environment settings, JNDI or the current ProjectStage.

Drop-In Configuration

The mechanism also allows for dynamic configuration in case of a JAR drop-in. By adding some JAR to the classpath, all it's contained configuration will get picked up and considered in the property value evaluation. You could also use this mechanism to switch implementations of some SPI (Service Provider Interface) in your own code.

CDI-Extension Configuration

In some cases low-level configs are needed e.g. during the bootstrapping process of the CDI container.
The good news: our DeltaSpike configuration mechanism does not rely on any other EE mechanism to be booted. Which means it can perfectly get used to even configure those parts itself. Since the mechanism doesn't rely on CDI it can for example be used to configure CDI-Extensions.
Currently this is e.g. used to configure the value of the current ProjectStage, configured values which can be used in the expressions for @Exclude, 'Deactivatable', etc. DeltaSpike needs such a low-level approach for several features internally, but users can utilize it for their own needs as well. This is done by using the ConfigResolver which resolves and caches ConfigSources per application.

Userland Configuration

DeltaSpike also provides a mechanism to inject those configured values using the @ConfigProperty CDI Qualifier.

ConfigSources provided by default

Per default there are implementations for the following config sources (listed in the lookup order):
  • System properties (deltaspike_ordinal = 400)
  • Environment properties (deltaspike_ordinal = 300)
  • JNDI values (deltaspike_ordinal = 200, the base name is "java:comp/env/deltaspike/")
  • Properties file values (apache-deltaspike.properties) (deltaspike_ordinal = 100, default filename is "META-INF/apache-deltaspike.properties")
It's possible to change this order and to add custom config sources.
To add a custom config-source, you have to implement the interface ConfigSource and register your implementation in a file /META-INF/services/org.apache.deltaspike.core.spi.config.ConfigSource by writing the fully qualified class name of the custom implementation/s into it.

Type-safe configuration

Finally DeltaSpike provides also a way to directly inject configured values into your code via the qualifier @ConfigProperty.
@ApplicationScoped
public class SomeRandomService
{
    @Inject
    @ConfigProperty(name = "endpoint.poll.interval")
    private Integer pollInterval;

    @Inject
    @ConfigProperty(name = "endpoint.poll.servername")
    private String pollUrl;

    ...
 }

5. Apache Commons Configuration

Configuration parameters may be loaded from the following sources:
  • Properties files
  • XML documents
  • Windows INI files
  • Property list files (plist)
  • JNDI
  • JDBC Datasource
  • System properties
  • Applet parameters
  • Servlet parameters
Different configuration sources can be mixed using a ConfigurationFactory and a CompositeConfiguration. Additional sources of configuration parameters can be created by using custom configuration objects. This customization can be achieved by extendingAbstractConfiguration or AbstractFileConfiguration.
The full Javadoc API documentation is available here.
For manipulating properties or their values the following methods can be used:
addProperty()
Adds a new property to the configuration. If this property already exists, another value is added to it (so it becomes a multi-valued property).
clearProperty()
Removes the specified property from the configuration.
setProperty()
Overwrites the value of the specified property. This is the same as removing the property and then calling addProperty() with the new property value.
clear()
Wipes out the whole configuration

6. Mechanism provided with the JDK

System Properties

Of course the well known Java system properties are always an easy way to configure things. By adding additional properties on the command line starting the Java process additional properties can be defined, e.g.

java -Dfoor.bar=notYet  <mainClass>

will start the given <mainClass>. Hereby the value from foor.bar can be extracted by calling System.getProperty("foo.bar"); This mechanism is widely used, but also has its limitations, mainly because it is a global configuration mechanism (the value is the same for the whole VM). Also adding very large amounts of system properties may lead to comlpex installation and deployment scenarios.

java.util.Properties

Of course, you could use simple property files. E.g. you can add a property file foobar.properties to your classpath (or a file, if you like)and then read it using the corresponding reader methods:

Properties props = new Properties();
props.read(getClass().loadResource("foobar.properties");

Additionally the JDK also support storing properties using a XML format:

Properties props = new Properties();
props.readfromXML(getClass().loadResource("foobar.properties");

Unfortunately there is no support for overriding of properties. So this mechanism is very limited.

java.util.Preferences

Another API present in the JDK is java.util.preferences. It models a tree of nodes, where each node can have arbitrary attributes:

Prefereces systemPrefs = Preferences.systemRoot();
Prefereces userPrefs = Preferences.userRoot();

String configuredValue = systemPrefs.get("a.b.c.myKey", "myDefaultValue");
int configuredIntValue = userPrefs.get("my.foo.intValue", 190);

The key used above hereby resolve to paths in the tree, so "a.b.c.myKey", references the following node:

<root>
  \_ a
      \_ b
         \_ c

myKey is finally the key looked up in the node c.

Basically a node supports the following data types:
  • String
  • int
  • long
  • float
  • double
  • byte[]
So the API is simple but in practice has shown to be very limited and not appropriate as a base for modelling configuration, because
  • The API's absrtactions are modelled by abstract classes, which prevents the flexibility required.
  • Registering additional PreferencesFactory instances (SPI) may interfere with texisting code.
  • Access to the tree is widely synchronized, which is not acceptable for accessing configuration in a EE environment.
  • The Preferences SPI also supports writing configuration back, but is in combination with remote backends basically very cumbersome to implement and use.

7. JFig

See http://jfig.sourceforge.net/

JFig allows developers to:

  • Store application configuration in one common repository of XML files
  • Access configuration data using one common, convenient interface
  • Easily define multiple configurations, dynamically modifying those variables that need to change in different situations.
  • Eliminate the error prone practice of defining the same configuration variables in multiple locations
  • Ease the management, deployment, and control of configuration files
JFig structures configuration as a hierarchy of configuration files. It supports .xml and .ini files:

XML Format
<configuration>
<include name=”base.config.xml”/>
      <section name=”locos”>
<entry key=”instance” value=”development” />
      </section>
<section name=”Paths”>
<entry key=”locosHome” value=”d:/[locos]{instance}/project/” />
<entry key=”locosExternal” value=”d:/external/[locos]{instance}/” />
</section>

<section name=”attachments”>
<entry key=”attachmentDirectory” value=”[paths]{locosExternal}attachments/”/>
     </section>
</configuration>

INI File Format
Section names are in brackets, followed by key/value pairs.
Following is a sample file:
[project]
instance=development
timeout=5

[Paths]
locosHome=d:/project/[locos]{instance}/
locosExternal=d:/[locos]{instance}/

[attachments]         
attachmentDirectory=[paths]{locosHome}attachments/

Hereby JFig allows to read multiple files. The “include” directive instructs the JFig parser to find the included configuration file. Files are parsed in reverse order. Thus, if a prod config file includes a base config file, the base config is parsed first.


Variable Substitution

The system provides substitution and cross referencing of variables. Substitution variables are in the format: [section]{key}. The second value, section Paths, key locosHome, uses the value of project, instance to build its value. So, locosHome resolves to d:/project/development . The next entry, attachmentDirectory, uses the previous entry to build its value. Thus, attachmentDirectory resolves to d:/project/development/attachment.
Also JFig allows to reference system properties:
<entry key=”docomentDir” value=”$user.home$/documents” />

Accessing Configuration

Configuration then can be accessed as follows:

JFig.getInstance().getValue(sectionName, key) Or 
JFig. getInstance().getValue(sectionName, key, defaultValue)

If you use a default value and the section/key is not found, the default value will return. If you don’t use a default value and the section/key is not found, ConfigException is thrown.

To set JFig values, use 
JFig.setConfigurationValue(sectionName, key, newValue);

For the most part, however, config values are set during the initial parsing of one or more ini files.

To show a complete listing of JFig values, use 
JFig.getInstance().printConfigurationDictionary()

8. Carbon


See http://carbon.sourceforge.net/modules/core/docs/config/Usage.html
The Carbon configuration model takes two steps to improve the use of externalized data files for configuration. The first is to provide a simple configuration hierarchy based on the model of folders and documents. The second is to provide more advanced integration between the data and code using something called data binding. This provides much more advanced error checking as well as a consistent method for managing the data and most importantly strongly-typed access to the data.
The primary interface to configuration data is through extensions of the Configuration interface. The configuration service, through data binding, is able to implement any interface that extends the Configuration interface and adheres to the JavaBean™ Specification for properties.
package examples; 
public interface WebServiceConfiguration extends Configuration {
 String getServiceName(); void setServiceName(String value); String getServiceAddress(); void setServiceAddress(String serviceAddress);
 boolean isSecureConnection(); void setSecureConnection(boolean secureConnection);
 Class TransportClass = org.apache.soap.transport.SOAPHTTPConnection.class; Class getTransportClass(); void setTransportClass(Class value);
}
A Carbon configuration file then would look as follows:
<Configuration ConfigurationInterface="examples.WebServiceConfiguration">
   <ServiceName>HelloWorld</ServiceName>
   <ServiceAddress>http://ws.examples/HelloWorld</ServiceAddress>
   <SecureConnection>true</SecureConnection>
</Configuration>

The configuration can then be accessed as follows:

WebServiceConfiguration myConfig = (WebServiceConfiguration)
    Config.getInstance().fetchConfiguration("/WS/example"); 
if (myConfig.isSecure()) {
    // ... use ssl socket factory
    ...
} 
else {
    // ... use standard socket factory 
    ... 
} 
Transport transport = myConfig.getTransportClass().newInstance(); transport.send(new URL(myConfig.getServiceAddress()), "hello", // .....

Additionally there is also a weakly typed variant:

<Configuration ConfigurationInterface="org.sape.carbon.core.config.PropertyConfiguration">
 <MyInt>4</MyInt>
 <MyFloat>6.6</MyFloat> <MyString>Hello, World!</MyString>
 <MyClass>org.sape.carbon.core.config.format.test.ConfigurationFormatServiceTest
   </MyClass> 
 <Name> <First>John</First> <Last>Doe</Last> </Name>
</Configuration>
Which can be accessed as follows:


int num = myConfig.getIntProperty("MyInt");String firstname = myConfig.getProperty("Name.First");

9. Owner

See https://github.com/lviggiano/owner

The approach used by OWNER is to define a Java interface associated to a properties file.
Suppose your properties file is defined as ServerConfig.properties:
port=80
hostname=foobar.com
maxThreads=100
To access this property you need to define a convenient Java interface in ServerConfig.java:
public interface ServerConfig extends Config {
    int port();
    String hostname();
    int maxThreads();
}
OWNER calls this interface the Properties Mapping Interface or just Mapping Interface since its goal is to map Properties into a an easy to use piece of code. Finally, you can let OWNER read and assign your config as follows:
ServerConfig cfg = ConfigFactory.create(ServerConfig.class);
This looks rater simple and straight forward. But owner has a bunch of additional interesting features and is one of the most sophisticated solutions I have found so far

  • default values support
  • collection support, including custom tokenizers
  • type conversion support
  • overriding mechanisms
  • placeholders (called variable expansion) and dynamic resolution
  • mutability and configuration hot reload (both synchronous and asynchronous)
  • listening to reload events
  • explicit modelling of accessibility and mutability of configuration
  • Meta-Configuration

10. Other Configuration Mechanisms

I encountered several configuration frameworks and mechanism during my work life so far. Nevertheless I also want to describe one of the more powerful ones, just to show some of the features/requirements identified in bigger companies.
Typically such custom solution either use one or more of the mechanisms described above, or the companies decided to write a feasible configuration solution themselves.

Hereby it is noteable that
  • most of the solutions are based on simple key, value pairs, with String values only.
  • some companies added also support for different Collection types of String, but in general this concepts has shown to add more complexity and issues than it provides advantages.
  • some of them use flat keys, but most of them define a tree structure, similar to what the JDK's preferences API is doing.
  • the system differentiate between the execution context, such as
    • executed during system startup (system class loader)
    • executed during ear startup/shutdown (ear class loader)
    • executed during application startup (application class loader)
    • executed during a request, e.g. a http request, or an EJB called.
    • also a stage is defined, which may look very different for different companies
  • the system define different override rules, e.g.
    • system properties override everythging
    • application properties override ear config
    • ear config overrides system config
  • some of them also map environment,system properties and the command line arguments into the global configuration tree.
  • some also use additional environment settings, such as tier, network zone, security policy, server or JVM/app server instance names to define further possibilities for customizing the final configuration active.


Friday, August 22, 2014

Injecting and Updating Configuration

At the last Hackergarten in Zurich, I discussed some configuration aspects with Andres Almiray (Twitter: @aalmiray). He showed my some very interesting aspects in the Griffon framework concerning injecting and updating String based configuration (preferences plugin). Image the following bean:

@Singleton
public class MyConfiguredBean{

  @Configured
  private String myConfigValue;

  ...
}

Basically this is simple and realizable just using today's existing CDI mechanisms, where @ConfiguredProperty is simply injecting the corresponding configuration value with the key "myConfigValue" (the field name). Of course, if the field name is not, what you want, you can explicitly define the configuration key to be used.

@Singleton
public class MyConfiguredBean{

  @Configured(key="a.b.configValue")
  private String myConfigValue;

  ...
}

Given that declaration the configuration system will just inject the correct configuration value once, when the bean is initialized. Now interesting could be how we can define an easy mechanism, to make the bean aware of configuration changes on the given property. With CDI, we could simply add a ConfigChangeEvent, which will be provided for each Configuration Change:

@Singleton
public class MyConfiguredBean{

  @Configured(key="a.b.configValue")
  private String myConfigValue;

  public void configChanged(@Observes ConfgChangeEvent evt){
    ...
  }

  
}

This would be easy. Furthermore we can add en injection mechanism, where the changes can directly be applied to the current bean:

public void configChanged(@Observes ConfigChangeEvent evt){
    evt.applyChanges(this);
}

This would implicitly update all the configuration injected, including Strings.

If we look at the example above, we basically can make things even easier (and that is what Griffon has already built-in): we simply add another top level annotation on the bean, telling the configuration system, that it should automatically reinject configuration values, when they change:

@AutoConfigured
@Singleton
public class MyConfiguredBean{

  @ConfiguredProperty(key="a.b.configValue")
  private String myConfigValue;

  ...
}

So whenever I access myConfigValue, I will see the current accurate result. I think this is an easy and intuitive way for managing String based configuration. Nevertheless this mechanism must not be constraint to Strings, it can be used for any configured resource.



Saturday, May 31, 2014

Use Case Summary from Google Groups

Use Cases

In todays blog, I am summarizing the use cases as discussed in groups.google.com/forum/#!forum/java-config. I did only some minor rework on the original posts and hope to still reflecting the essence right.


Configurable Priorities

The configuration system in DeltaSpike uses, what they call, sources http://deltaspike.apache.org/configuration.html#configsource). Configuration hereby comes from several sources :
  • System properties
  • Environment properties
  • JNDI values
  • Properties file values (default filename is "META-INF/apache-deltaspike.properties")
These sources have a default priority (System first…. properties file last) that can be changed. So we could easily say "by default, the WEB-INF/classes directory is a source that has a priority lower that an external file". This way, by default, if there is a config file within a war, it will have lower priority, meaning Java EE components will behave as they use to. By adding an external source this (defaults) can be overriden or extended. And of course, this default behavior can be changed.

→ Configuration comes from different sources.
→ Configuration must be combinable.
→ Configuration must have different priorities that may taken into account, when combining configuration.

Configurable Overrides

Overriding behavior must be configurable, e.g. refer to the way of the Jersey team does things. You can register components and given them a priority. This approach would allow us to provide a default chain of sources of configuration properties and to allow the user to specify his own chain.

→ Configuration can be evaluated by a complex combination of sub-configurations or providers (e.g. a chain of responsibility)
→ Different environments may require different combinations in place


Multi Tenancy

In multi tenancy setups a hierarchical/graph model of contexts for configurations is required. For example there might be some kind of layering:
  • Layer 0: Default App configuration
  • Layer 1: Tenant specific configuration
  • Layer 2: User specific configuration
Configurations made in the tenant or user layer override the default app configuration etc.

→ Configuration must be orgainizable in layers that can override/extend each other.
→ The current environment must be capable of mapping tenant, user and other aspects, so a corresponding configuration (or layer) can be derived.

Scenario Operations

Current support of Java EE for operations (e.g. PaaS offerings) is weak. Also corresponding providers may not be fully compatible, which makes it more difficult to move applications between providers or different offerings/products within the same provider. Hereby a provider requires an extension to the EE runtime model, where all relevant deployment configuration can be controlled by an external source, managed by the provider and consumed by the EE platform. Basically if one deploys a java application a standard way to define it’s configuration, resources and environment to integrate with the provisioning tooling in place should be defined. The configuration should be pluggable (e.g. from a database, an external file,…) and the configuration should also be changeable at runtime.

Also there should be a standardized way to evaluate a configuration for an already deployed application.

→ EE deployments must be configurable. Configuration must be controllable from external sources, which are not controlled by the EE container.
→ External resource can override all aspects, or only override/extend specific parts, but still consider configuration data deployed with the application.
→ a contract is required, how this external configuration can be included/provided.
→ a contract is required, how according configuration is modelled, so the external source can "implement" the contract.
→ Configuration may be fully or partially mutable.
→ Changes on configuration must be observable.
→ a service is required that allows to read out the configuration of a deployed application.


Injectable Configuration and Fragments

As a developper I want to be able to configure my application/module something like this :
public MyPojo {
  private String currency;
  private Long currencyRate;

  // complex algorithm based on the currency
}

How do I configure that depending if my app is dealing with dollars or euros ? The DeltaSpike way of doing is something like :

public MyPojo {
  @Inject @Config("myCurrency")
  private String currency;
  @Inject @Config("myCurrencyRate")
  private Long currencyRate;

  // complex algorithm based on the currency
}

The Seam Config way of doing is quite clever. They use a namespace that is relative to the packing. So, without changing the initial code (so, forget about the @Inject above) they have an XML file that is able to override each attribute of any file.
As a Java EE user (developer or devops) I would like also to be able to package different versions of deployment descriptor fragments within my Java EE application archive, and be able to select which one is used via a -D command line argument.
E.g. have the following file structure within the application archive (a .war in this case):

WEB-INF
    conf
        dev
            web-fragment.xml
        qa
            web-fragment.xml
        live
            web-fragment.xml

And then either directly be able to say that conf/dev/web-fragment.xml should be used, or do this indirectly via an include directive and a placeholder in the main deployment descriptor for this type of fragment (in this case web.xml):

<web-app>
    ...
    <fragment>WEB-INF/conf/${mycompany.staging}/web-fragment.xml</fragment>
</web-app>

→ Application Configuration must be supported.
→ Configuration must be injectable using CDI
→ Configuration should support fragements, which can dynamically loaded by properties on the current runtime environment, or other mechanisms.


Scenario Testing

When testing a Java EE solution, it must be possible to easily control the configuration provided, so isolated component tests can be written effectively. Also it should be possible to control/isolate the configuration level for each test case.

→ isolation of configuration services
→ API for controlling the configuration provided, required for according implementations in the testing frameworks.

Scenario Modules

Complex applications are often built out of many more fine granular pieces, often called modules or plugins. This could be technical abstractions, business models, products or UI components. All of them require some configuration, which may be different for different runtime deployments (e.g. product customizations).

→ it must be possible to add configuration that exceeds the EE deployment aspects (Application Configuration).
→ this configuration must be deployable in different ways, along the code, or from external sources.

Scenario Staging

Different companies go through different staging levels during the development of software components. Currently only rarely the EE frameworks support staging aspects, nevertheless no broader, well modelled staging concept is defined. 
Different companies also have different staging or sub-staging levels in place, which also must be reflected. Especially with sub-stages inheritance of stage related configuration is common sense and should be supported.

→ Main stages available and to be supported by Java EE must be defined.
→ Enable sub-stages, additional aspects to be added, so also custom stages can be supported by configuration.
→ Allow stage properties inheritance, where needed.

Custom of the Shelf (COTS) Integration

When buying software from an external software company it is often very cumbersome to integrate, adapt and customize third party software to the internal operational requirements. Especially, when software is delivered as ear modules portability is often very difficult and time consuming. Configuration should enable COTS providers to define a customization contract, which also can be part of the COTS software interface and integration specifications. This would allow operations to better control and configure third party solutions as possible, whereas in the evaluation phase the integration and configuration options can explicitly be defined.

→ It must be possible to document configuration aspects supported.
→ It must be possible to configure arbitrary aspects, with basically arbitrary complexity, exceeding what is defined by Java EE.
→ Configuration must be overridable from external sources (the operations which must operate the COTS solution).

When operating huge server farms targeting Java EE solutions a typical process is as follows:
  1. An order for a Java EE deployment is created.
  2. An according logical domain is created and prepared image with a standard setup is installed.
  3. The logical domain and the containing Java EE application server are started in standalone mode.
  4. The application(s) are copied to the server and automatically deployed.
Hereby it would ease life of administrators, if deployment of EE solutions can be controlled/automated by the application server. This requires that the application server can be startup in some "maintenance mode", which allows to trigger its configuration service, so according deployments can be controlled by some (external) deployment controller.

→ Configuration must be injectable/deployable also into a running application server.
→ It must be possible to listen to configuration changes, so the deployment could be controlled similarly based on configuration changes (events).
→ configuration must be mutable and changes observable.               

Some Conclusions

So taking all into account, I would suggest the following:

  • Configuration is a very complex thing (OK, this is not new).
  • Configuration is dependent on the environment.
  • Configuration can be static and/or dynamic.
  • Configuration can come in different flavors and types.
  • Different companies have different sources and external systems in place, where and how they manage configurations. It must be possible to interoperate with all/most of them.
  • If EE Configuration focuses only on Java EE aspects, it will fail to cover some of the most important use cases and will make Java EE to fall back much behind e.g. what Springsource or other Cloud platforms are offering already as of today.
  • Configuration should leverage existing functionalities, e.g. by being injectable into CDI, instead of reinventing the wheel.
The good news is that, if interpreting configuration as a more broader and generic concept all/most of these aspects can be covered quite well with only a few abstractions. Though having said that, I am not sure, what will be covered at the end. Nevertheless the benefits for application programmers in Java EE would be tremendous, even if only a few aspects will be targeted. 
One of the risks I currently see, is that configuration aspects are targeted in a too narrow sense, focusing on leveraging EE as a platform only, because
  • focusing on EE only may not require to model configuration in a generic way, which may reduce the flexibility achieved at the end. Especially it might constrain the interoperability of configuration per se or, even worse, it might lead to two different ways of configuration in the future: one for application logic, one for EE logic.
  • adding configuration to all the existing JSRs is a huge and tremendous effort. To try to drive (remodel?) all required changes out of one JSR may quite probably make it fail. Nevertheless, focusing on the most important EE aspects, like EJBs, CDI, servlets, JSF, JMS, JPA, would still create huge benefits, but leave enough time for other aspects described above.
As always, you can add your comments or, even better, add your use cases, you want to be solved, so we can ensure we have covered the most important ones here...


Monday, May 26, 2014

A Proposal for Java EE Configuration (Follow up)

A Proposal for Java EE Configuration (Follow up)

Given all the feedback and discussions from last week I would come up with the following more concrete feature list, what should be covered IMO. Finally I outline a rough server lifecycle including configuration. As always feedback is welcome!

High Level Features

  • Define mechanisms to​ enable applications being deployed by adding configuration externally (from an application viewpoint). This means it must be theoretically possible to configure an application completely externally. This would include loading and providing existing deployment descriptors and other configuration files to be provided based on external configuration.
  • Define mechanisms to provide deployment descriptors, e.g. by some API or more generic, accessible under certain keys. Alternatively a common configration access point for EE configuration is defined that can be used, by other JSRs.
  • From a DevOps perspective, also additional aspects, today configured outside of an ear/war archive should be considered, such as security setup, data sources, message queues, worker thread pools etc. This is also one of the more interesting areas, where we must see in what kind of runtime environment we are running. If CDI 2.0 would define some shared system level container, this will be the place to be, if not application servers must load EnvironmentManager and ConfigurationManager and provide them as JNDI entries.
  • Application configuration is also very important for portability. A key/value store has shown in a variety of frameworks its strengths, so with another 10+ interfaces this feature should also be included. 
  • Wiring and injection of the effective configuration should be done based on CDI. 


Additional Details

  • Environments are hierarchic, meaning environment settings from lower levels, e.g. startup are also visible in inheriting contexts, but may be overriden. Environments also define the basic hierarchy levels for configuration.
  • At a current runtime point exact one environment is active.
  • An environment provides a Stage, which is predefined. Additional custom stages can be realized by adding additional properties to the environment. An SPI allow to add additional values to an environment.
  • Configuration (parts) can be active/non active based on the current environment.
  • All configured String values support EL syntax to be used for wildcards and cross-references and dynamic replacements.
  • Default values can be deployed along the code by adding configuration to a configuration.xml loaded deployed with the code on the classpath.
  • Application Configuration basically is modelled along the environment hierarchy and thus runtime dependent, whereas deployment configuration is identified by the requested target state.

Portable and Externalizable Application Configuration

  • A common application.xml file (name and location to be discussed) will be defined, which summarizes all/most configuration aspects as of today. 
  • Similarly a programmatic Java API is defined that allows to configure an application, modelling the same features as the application.xml. An instance of such an object can be injected as a configuring resource into the CDI container (e.g. ApplicationConfiguration). From a user's persepctive this can be an implementation based on the application.xml (default) or provided by any other mechanism (including external ones).
  • Configuration may be accessed using a restful service API, that is not active by default.


Out of Scope

  • Versioning of Configuration may be addressed later.
  • The key/value API will be minimal (mostly API only and injection into managed beans). As an advantage most of existing configuration mechanisms could be used to implement the backend needed. Standardizing this mechanism fully for SE will be out of scope for this JSR and might be solved in another separate JSR.


A possible Server Lifecycle

1) Server startup:


  • the shared system (CDI 2.0 ?) container is starting up. This maybe a CDI based container (preferred) or an application server specific one.
  • the configuration JSR root components are loaded as part of the system container and made accessible via JNDI, mainly


    • EnvironmentManager
    • ConfigurationManager

  • If the system container is built on CDI the following aspects are injectable:
    • EnvironmentManager
    • ConfigurationManager
    • (Current) Environment
    • (Current) Stage
    • (Current) Configuration
  • When the current server configuration has been loaded, a config loaded event should be triggered, containing also a reference to the current system Configuration. This event can be used to configure early server resources.

2) Ear/War startup:

  • For each ear (and/or for each war):
  • load "application" CDI context, consider the configuration provided from the system container to configure application CDI.
  • Trigger a config preload event, that the application Configuration will be loaded now.
  • Trigger a config loaded event, that the application Configuration has been loaded and now is available (containing the current Configuration).
All features, including application configuration are fully based/extending CDI. JNDI entries for EnvironmentManager, ConfigurationManager are still the same (access restrictions are to be discussed). If we have some kind of shared a CDI context on system level of the container, we could fully build the configuration system based on CDI.

Thursday, May 15, 2014

A Proposal for Java EE Configuration

Requirements for Java EE Configuration

In this post I want to outline, what I see a reasonable scope for a Java EE Configuration JSR. I would first try to summarize different use cases, people want to have to be covered. In a next part I try to deduce corresponding requirements. Finally I will try to discuss, what is needed to cover these aspects.

Use Cases

First I will summarize the use cases that were mentioned so far in the discussion, especially also here.

  1. An enterprise wants to centrally control their deployments (could be cloud, but is not restricted to). Hereby according configuration should be managed externally within a database or some other kind of data container. The configuration should be accessible with an administrative console and it should be possible to change configuration and remotedly update running instances affected by a configuration change. Especially administrative resources, such as data sources, thread pools, users, roles etc. should be configurable, so these aspects can be managed in a central location.
  2. For different stages or runtime environments different CDI components should be loaded that reflect the different runtime environments. This includes configuring CDI, Enterprise Java Beans and similar aspects (basically everything that can be configured with some kind of deployment constructor deployed with an ear or war archive).
  3. Depending on the stage and some additional aspects different configuration must be used (including, but not limited to deployment profiles). Advanced use cases include network zones, host, tier, server instance and more. Hereby the possible properties are not constraint and may heavily differ between applications and especially enterprises (runtime environments). Many applications use a file based configuration approach, which is often cumbersome and error prone.
  4. It should be possible to adapt/reconfigure COTS applications to better accomodate them into the concrete environments. It should be possible to deploy them on different stages, without having to redeploy anything (also because traceability of the deployment may be a legal requirement).
  5. It should be possible to provide configuration that goes beyond what is defined by the current EE standards. E.g. there are companies that redeploy the exact some jars in different setups, but reconfigure them (e.g. in multitenant, multiproduct scenarios). Thinking in extremes that could mean having a single application deployed multiple times very differently.
  6. Configuration should be accessible both using a Java API, as well as being injected using CDI mechanisms.
  7. It should be easily possible to use this configuration mechanism also in testing. Developers should be capable of easily configure their test setup that should be loaded.
  8. Similar to views in relational database configuration should be scoped, so only a subset is visible. This can be required for example because of security concerns.
  9. Finally for multi-tenant/SaaS setups configuration must be dynamic, so a SaaS provider can lookup configuration programmatically.

Requirements


This list is quite probably not complete. Nevertheless it is possible to deduce some requirements:
  1. It must be possible to store and manage configuration at an arbitrary place independent of the target deployments.
  2. It must be possible to store and manage configuration along the target deployments.
  3. It must be possible to provide configuration with deployment artifacts (jars, wars, ears)
  4. It must be possible to mix configuration from different locations.
  5. It must be possible to priorize configuration.
  6. It must be possible to combine configuration in different ways (override, extend, ignore duplicates, ...).
  7. It must be possible to change configuration and trigger the changes to interesting observers.
  8. Configuration must be loadable within early boot of a system, where no EE context is available.
  9. Configuration must be adaptable depending on the current runtime context.
  10. Configuration must be accessible/injectable using CDI mechanisms.
  11. Configuration must be accessible using a Java based API.
  12. Configuration services must allow to configure administrative resources, such as datasources, users, roles.
  13. The runtime environment must be modeled in a flexible way, because different companies have different deployment/runtime and consequenty configuration needs.
  14. Configuration must support staging. It would be possible to define a minimal staging type applied to an environment, But such a concept would require to allow concrete sub-stages to be modellable to accommodate also complex runtime environments.
  15. Configuration should be able to support a wide range of EE.  If some areas would be excluded, we would stop half-way and destroying much of the benefits a powerful configuration mechanism can provide, since we in such case have to do workarounds as before.
  16. Configuration may be marked as read-only. An simple accessor should allow to determine if configuration is mutable.
  17. Configuration must be thread-safe.
  18. Whereas configuration itself must not be serializable, it must be possible to extract a current state of configuration and serialize this state (e.g. as immutable configuration). This enables sending configuration easily over network connections.
  19. Configuration must also support aspects that are currently not part of any EE standard, especially it must be possible to also configure application aspects. Without that you simply have to do workarounds to mitigate this lacking feature, distrying the benefits of other configurations.
The list is for sure not yet complete, but I tend to say the most important aspects are covered. If you are something missing, let me know, so I can extend the list above.

Conclusions


Give the huge areas of use cases above, one may think, it it will not be possible to define a useful scope for a JSR. I would fully agree, if one would try to solve everything from scratch modeling every aspect explicitly. But why should we? Configuration is per se quite an abstract concept, as we have seen also in previous blogs here. So lets keep configuration abstract and simple (KISS principle):

Configuration = Map<String,String> + Metadata
Metadata = Name + Map<String,String>

Finally we need some mechanism to access configuration. Given the requirements above it is not useful, to define configuration access as an interface injectable by CDI only, since it will prevent us of using configuration at early stages, where CDI is not loaded yet. Similarly it would not be possible to use configuration for configuring administrative resources. But if we would fail to cover these requirements, it is quite useless to file a JSR for this topic.

So basically configuration must IMO be provided by some simple accessor as a global service. Now some people might argue that this is not EE styled. So I would ask, what EE is all about, so I look up Wikipedia:
"Java EE provides an API and runtime environment for developing and running enterprise software, includingnetwork and web services, and other large-scale, multi-tiered, scalable, reliable, and secure network applications. Java EE extends the Java Platform, Standard Edition (Java SE), providing an API for object-relational mapping, distributed and multi-tier architectures, and web services."
So there is nothing said that is can not be done in that way. Additionally, we have some additional benefits:
  • There is a clear separation of concerns. The configuration service has a clear, well defined API, how it can be accessed and what kind of features it must provide. The configuration service itself does basically not neet to know anything about its EE context, which is the way how modularized systems are built as of today.
  • We have defined a simple interface, that allows us to hook in different kind of implementations and solutions to provide configuration. For example any vendor can provide additional configuration management tools and products that allow to manage your application server configuration centrally thus also creating additional benefits (and profits).
  • Basically it can be left over to the implementations how the configuration provided is stored and retrieved. The JSR should focus on the mechanisms and interfaces, not on how different companies should manage their configurations.
  • The interface and the access points must be defined by the JSR, but the effective data feeds can still be adapted to the needs of the concrete usage scenarios.
  • Said that, this also enables us to support configuration in SE cases, especially for testing. Especially when CDI would also be configurable, it can be used (e.g. with CDI 2.0) in combination with configuration services also in test environments very effectively, which would simplify testing of EE a lot.
  • Over the years the former complex and over-engineered EJB design was transformed into a lean POJO (POJI) based easy to use component model, where additional services and cross-cutting concerns can simply be annotated. It would look very strange if we would add a configuration mechanism that again only works within a EE context.
Additionally there are other possible things that might be useful:

  • Finally configuration of application aspects is also required. Defining a generic and easily accessible configuration service allows to cover these aspects similarly, without having to file another JSR. Defining some additional annotations to be used with CDI for injecting configuration into managed beans should be rather trivial. Advanced use cases hereby may be ommitted and left over for future releases.
  • provide configuration in different versions.
  • node and cluster based configuration.

So there is IMO a strong coincidence for going that way, because
  • the mechanism is simple
  • the mechanism builds on top of existing interfaces (Map), hereby also supporting features such as Lambdas and streams out of the box
  • the mechanism is not intersecting with CDI, because it is constraint.
  • String keys and values, can easily be combined and filtered, so aspects included above can be easily supported:
    • filtering/views
    • templating/defaults
    • intersections
    • unions
    • ...
One of the following key aspects would be, how we then integrate this new functîonality with all the existing JSRs? Basically there are two different possible ways to go forward:
  1. The JSR itself defines, how each JSR must support adaptable configuration.
  2. The JSR defines the basic mechanism. The JSRs to be included into EE8 should define on their own, how they want to make use the new mechanisms. Hereby the EE8 umbrella JSR group, lead by Bill Shannon and Linda DeMichels are coordinating the initiative.
I personally think going for (1) is not the way, it should be. I think each JSR itself has the best know how, what might be feasible points of integration with the new configuration services. Additionally this would also help to reduce the scope of the Configuration JSR drastically. As a precondition to that, the API to be used should be defined and stable very early in the overall process. My idea would be to have it defined the latest until end of this year (assuming we can file the JSR within next few weeks). So we have two years time to integrate it into the existing standards, which looks for me a reasonable time frame. At the same time I would suggest the configuration JSR provides some kind of guidelines and corresponding templates, so the other JSRs can easily adopt the new mechanism. As an example a template could look something like that:


Configuration
for JSR 220
Configuration KeyConfiguration TypeAvailabilityExpected Content
javax.jpa.persistenceUnitsjava.lang.Stringapplication/ear startupComma separated lists of names of the registered persistence units.
javax.jpa.persistenceUnit.[name]java.io.InputStreamapplication/ear startupDeployment Descriptor (persistence.xml) as described in section XXX


Of course, the example above is not probably not complete. But it shows the main intend quite well. Nevertheless it would still be feasible that the configuration JSR makes proposals, how the other JSRs can be accomodated to the new mechanism, if other JSRs wish us to do so.

If then finally a JSR is nevertheless failing to use the new APIs, the configuration JSR and the EE overall planning would not be affected. This greatly reduces the risk for EE8 to be delayed, but still there is a reasonable chance that we can achieve a new flexible EE platform.

Proposal and Scope

Given all the aspects described above a configuration JSR will cover the following:

Next:
  • Open the JSR

Until end of 2014:


  • Define the Java API as far as possible
    • Define a simple map based configuration abstraction, as basically outlines in my previous posts. 
    • Define a simple, but flexible and extendible Configuration Service (accessor) API. It consists of an accessor that is also loadable outside of CDI.
    • Define a SPI to configure/back the implementation used by the accessor API.
  • Define a configuration description template. Send it out to each JSR included in EE8, so each JSR can individually decide how the want to be configurable. The results then can be included either into updated JSRs, or/and in summarized form into the configuration JSR.

Basically this implies that the JSR will publish its early draft review until end of 2014.

    In 2015:
    • Discuss and coordinate configuration support with other JSRs.
    • Define configuration keys/support for administrative resources.
    • Provide fully functional reference implementation, so it can be included into Glassfish as one of the first modules.
    This will be a reasonable scope for a Public Review during 2015.


    In 2016:
    • Finish the TCK and RI work and go final.

    Comparing with the Proposal done by Mike Keith at last Java One

    Mike Keith did several presentations during the last years at different conferences, e.g. at JavaOne 2013. 



    Mike hereby did quite a good job, basically the use cases match very well, what is defined above here. So also this proposal does not target things completely differently, but given the experience of Credit Suisse, CloudBees and other companies that run huge application server farms and cloud or cloud like infrastructures, there is one crucial aspect, where I really disagree:
    • Do not define another archive format to provide configuration!
    There are a couple of reasons, why I think, we should not follow the idea of configuration archives as proposaed by Mike Keith:
    1. We already know from experience with ears and wars that handling of archives is not always easy and often is cumbersome (especially during development). Whereas also in Credit Suisse, application configuration is delivered along the code as jar artifacts, it is only covering parts of the deployment. 
    2. Additionally the JSR would have to define the format of the archive, define the stages and other sub schemas/folders so the archive covers all kind of aspects required. This would add complexity to the configuration JSR, without benefit for users.
    3. In Credit Suisse Datasources, thread pools, users, security roles, certificates and other resources are not managed as file resources primarly. Within the deployment process according files are generated, by this makes the deployment inflexible, since even simple changes require a complete redeployment. Similary the deployment packages have to rebuilt for each stage. 
    4. Often configuration changes are assummed to be more easily deployable, but experience has shown that this must not be the case. Additionally there might be cases, where operations has to adapt a configuration, e.g. because a database or other resources has been moved. With archives the application has to be redeployed, which is exactly, what we want to prevent.
    Instead, I would let it open, how the Configuration Service effectively is locating its configuration. As shown above we can define different configurations (and locations) more effectively as shown above in the template, but without implying constraints how this configuration must be deployed.
    This point has been proven in discussions during the last year with leading engineers and Java Champions. Also other colluegues have written blogs on this e.g. see http://blog.loof.fr/2013/10/configuration-management-jsr.html

    So my proposal would be slightly adapted:




    Higher Level Services

    As already mentioned also at https://java.net/jira/browse/JAVAEE_SPEC-19 and also as commented by Arjan Tijms, we must be capable of providing higher level services on top of that very basic concepts. Most prominent use cases are the deployment descriptors, located at several different locations throughout the system, but there are also other settings that may be considered. I outlined in the previous blog, some of the possibilities to add additional functionalities using generic functional extensions. Tijms has outlined, that an additional higher level API for providing configuration information to the different components in a EE container would be useful, which may go beyond adding specialized configuration adapters. I would not disagree on that topic. 
    Basically the template idea above could then similarly extended, so instead of modelling the template entries on the low level, as described above, we would model a high level API (e.g. as an interface?), that is finally provided by the configuration JSRs. This would shield existing components from the details of the configuration service.

    Since different components in a EE container are configured rather differently, it might require to define multiple interfaces to be provided. I would like to postpone this at this point, since this topic is worth it's own blog entry ;-)

    Feedback Required

    I would like to encourage all readers to give feedback on this blog. Please do not only raise your concerns, but also give positive feedbacks, what you think. It would help to see, if this would be a feasible way to go ahead.