Configuration with Apache Tamaya

This is a first post of a series discussing the Apache Tamaya configuration toolkit. So let’s directly have a look at Tamaya and see what it can do for us…

Setting up a minimal project

First we need to dowload and install Tamaya. Fortunately you don’t need any third party libraries. So given you have Java 7 and a reasonable build system such as maven installed you simply add the following dependencies:

<dependency>
  <groupId>org.apache.tamaya</groupId>
  <artifactId>tamaya-core</artifactId>
  <version>0.3-incubating</version>
</dependency>

As a result you will have a small maven project with the following dependencies:

[INFO] org.apache.tamaya.examples:01-minimal:jar:0.3-incubating
[INFO] +- org.apache.tamaya:tamaya-core:jar:0.3-incubating:compile
[INFO] | \- org.apache.tamaya:tamaya-api:jar:0.3-incubating:compile
[INFO] +- org.apache.geronimo.specs:geronimo-annotation_1.2_spec:jar:1.0-alpha-1:compile

Tamaya’s core transitively also requires Tamaya API and the 1.2 annotations package:

  • tamaya-api contain the API you will see in your code.
  • whereas tamaya-core actually implements the API.
  • Since the service location mechanismimplemented by tamaya-core also supports the usage of @Priority annotations the corresponding annotation package is required as well.

Accessing Configuration

So there you go. You are ready to access configuration. Tamaya, by default maps all systemand environment properties, so we can access them easily:

public static void main(String[] args) {
    Configuration cfg = ConfigurationProvider.getConfiguration();

    System.out.println("User Home   :  " + cfg.get("user.home"));
    System.out.println("User Name   :  " + cfg.get("user.name"));
    System.out.println("PATH        :  " + cfg.get("env.PATH"));
}

As expected the output looks somethinglike this:

User Home   :  /home/atsticks
User Name   :  atsticks
PATH        :  /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin ...

This is great, but we want to see a bit more what is going on under the hood, so let’s add our Configuration instance to the output using

System.out.println(cfg);

The output gives us much details about our configuration setup:

Configuration{
 ConfigurationContext{
  Property Sources
  ----------------
  CLASS                           NAME                   SCANNABLE SIZE STATE ERROR

  CLIPropertySource               CLIPropertySource      true         0 OK 
  EnvironmentPropertySource       environment-properties true        69 OK 
  JavaConfigurationPropertySour   resource:META-INF/javaconfiguration.* true 7 OK 
  SystemPropertySource            system-properties      true 52 OK

 Property Filters
 ----------------
 No property filters loaded.

 Property Converters
 -------------------
 CLASS                      TYPE             INFO

 CurrencyConverter          Currency         org.apache.tamaya.core.internal.converters.CurrencyConverter@3fee733d
 LongConverter              Long             org.apache.tamaya.core.internal.converters.LongConverter@5acf9800
 FloatConverter             Float            org.apache.tamaya.core.internal.converters.FloatConverter@4617c264
 BigIntegerConverter        BigInteger       org.apache.tamaya.core.internal.converters.BigIntegerConverter@36baf30c
 NumberConverter            Number           org.apache.tamaya.core.internal.converters.NumberConverter@7a81197d
 URLConverter               URL              org.apache.tamaya.core.internal.converters.URLConverter@5ca881b5
 DoubleConverter            Double           org.apache.tamaya.core.internal.converters.DoubleConverter@24d46ca6
 ClassConverter             Class            org.apache.tamaya.core.internal.converters.ClassConverter@72ea2f77
 IntegerConverter           Integer          org.apache.tamaya.core.internal.converters.IntegerConverter@4517d9a3
 URIConverter               URI              org.apache.tamaya.core.internal.converters.URIConverter@372f7a8d
 ByteConverter              Byte             org.apache.tamaya.core.internal.converters.ByteConverter@2f92e0f4
 ShortConverter             Short            org.apache.tamaya.core.internal.converters.ShortConverter@28a418fc
 BigDecimalConverter        BigDecimal       org.apache.tamaya.core.internal.converters.BigDecimalConverter@5305068a
 PathConverter              Path             org.apache.tamaya.core.internal.converters.PathConverter@1f32e575
 CharConverter              Character        org.apache.tamaya.core.internal.converters.CharConverter@279f2327
 FileConverter              File             org.apache.tamaya.core.internal.converters.FileConverter@2ff4acd0
 BooleanConverter           Boolean          org.apache.tamaya.core.internal.converters.BooleanConverter@54bedef2

 PropertyValueCombinationPolicy: org.apache.tamaya.spi.PropertyValueCombinationPolicy$1
}}

From the output you easily can identify the main abstractions of Tamaya:

  • The Configuration object, which provides the API.
  • The ConfigurationContext, which actually it the container of all artifacts required to provide a Configuration.
    • Property Sources that provide configuration key/value pairs (both as Strings).
    • Property Converters that provide capabilities for converting configuration values to typed instances.
    • Property Filters that allow to add/extend/remove or update configuration String values after evaluation.
    • The PropertyValueCombinationPolicy allows to define the way how entries from less significant property sources are combined with values from property sources with higher significance to a new value. Adapting this policy also allows to combine properties, as it is needed to support collcetion types.

Similarly we see that the following property sources are included in the current configuration:

  • CLI parameters (must be explicitly set, refer to next section)
  • Environment properties as returned by System.getenv().
  • Entries from META-INF/javaconfiguration.* (supported are .properties and .xml property files).
  • System properties as returned by System.getProperties().

The order given also reflects the significance of the different property sources. So system properties override properties from all other property sources. This behaviour can be tweaked in different ways. This will probably be discussed in another blog post.

CLI Properties

Command line parameters cannot be evaluated by default, so they must be passed explicitly to the CLIPropertySource using the static initializer method:

public static void main(String[] args) {
    CLIPropertySource.initMainArgs(args);
    ...
}

Given that configuration also can be passed as main paramters:

java ... TestExampleMain -server-port 800

 

Typed Configuration Access

As we have seen we can also use typed configuration, e.g. let’s access the user.home property as a file:

File homeDir = cfg.get("user.home", File.class);
System.out.println("\tUser Home   :  " + homeDir);

Of course, the output will not change, but we successfully accessed configuration using a target type. The list of converters shown earlier shows the types that are supported by default. With the upcoming version 0.4-incubating Java 8 will be required and additional Java 8 specific types will be supported as well:

  • Optional
  • LocalTime
  • LocalDate
  • LocalDateTime
  • OffsetTime
  • OffsetDateTime
  • Instant

Providing Default Values

In many cases you want to provide default values. Of course, this is also possible with Apache Tamaya:

int port = cfg.getOrDefault("server.port", int.class, 80);
System.out.println("\tServer port :  " + port);

As expected 80 is returned for the configuration value:

Server port : 80

Now let’s define an additional system property: -Dserver.port=889. As expected the value returned has been changed:

Server port : 889

Recap

This blog showed you the minimal API of Apache Tamaya. This is fairly easy and in most real-world scenarious you want probably more features. This is way there is a variety of extensions, which provides additional functionality such as:

  • placeholder and resolution patterns,
  • resource location,
  • additional file formats,
  • property sources for various backend technologies,
  • configuration injection with or without CDI,
  • integration with other frameworks such as Spring, Camel and more.

Also accessing Configuration using a singleton pattern (ConfigurationProvider.getConfiguration();) is known to be rather inflexible. But good news is, that Tamaya has several mechanisms to use your own flexible implementation of a ConfigurationProvider.

Also Apache Tamaya is a toolkit. You don’t have to use CDI, Java EE, Spring for using it. Most extensions provided work seemlessly with almost every Java based framework. You even can programmatically assemble your configuration using a builder pattern and manage configuration instance using your own lifecycle models. So you have full freedom how to use Apache Tamaya. Nevertheless Tamaya offers you a unified configuration model and API. So you don’t have to adapt your code, when changing from one plaform to another.

Subsequent post will discuss the various features. The Apache Tamaya team encourages you to give back any kind of feedback, so they can improve Tamya even more.

Advertisements

About atsticks

Advanced Java Software Engineer and Architect.
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s