Tamaya Configuration Server (Extension Module)

Overview

The Tamaya server module provides support for providing scoped configuration using a http server serving JSON formatted configuration properties.

Compatibility

The module is based on Java 7, so it will not run on Java 7 and beyond.

Installation

To benefit from configuration server support you only must add the corresponding dependency to your module:

<dependency>
  <groupId>org.apache.tamaya.ext</groupId>
  <artifactId>tamaya-server</artifactId>
  <version>{tamayaVersion}</version>
</dependency>

Providing configuration using the Tamaya Built-in Configuration Server

THe most simple way for providing onfiguration ist to start the internal server:

Server server = org.apache.tamaya.server.ConfigServer.createServer();
server.start(port);

This will start a simple server instance that serves the following URL patterns:

  • GET /config provides access to the full configuration tree.

  • GET /config/filtered/${path} let you filter the configuration returned using regular expression (comma separated). E.g. /config/filtered/java,sun will return all configuration entries starting with java and sun.

Additionally the server module has the following options implemented, which can be passed as additional, optional parameters:

  • format allows to define the target format. By default the ACCEPT header of the http request is checked, but this setting can be explicitly controlled by passing tis parameter explicitly. The value is the expected MIME type to be returned. By default the service supports the following types (refer to the SPI section later in this document for options to adapt this):

    • text/html

    • text/plain

    • application/xml

    • text/json

  • scope,scopeId allows to use a server-side preconfigured filter/combination policy to be applied for evaluating the entries to be returned. Hereby the scopeId paramter allows to address a certain scope. As an example think of a scope ?scope=CLIENT&scopeId=client1 to be passed as request parameters. This tells the server module to lookup a configured scope named 'CLIENT' and access a ConfigOperator for the given scopeId 'client1'. The returned operator then can filter and combine any kind of entries to the required client configuration (for client1). Refer to the scopes section for more details.

Using the Configuration Servlets

Additionally to the fully built-in solution, it is also possible to integrate the Tamaya server module with a standard Java EE servlet container. Tamaya provides 2 servlet implementations:

  • the servlet org.apache.tamaya.server.FilteredConfigServlet can be used to register access to configurations that also support filtering of the keys. The URL looks like

http(s)://HOST/SERVLET_CONTEXT/PATHS?params

where
  HOST            = host name incl port, e.g. 127.0.0.2:234
  SERVLET_CONTEXT = the base context and servlet context, e.g. /client/config/filtered
  PATHS           = A comma separated number of key paths to be filtered for being returned, e.g.
                    java,sun,client
  params          = the optional parameters (scope, scopeId and format)
  • the servlet org.apache.tamaya.server.FullConfigServlet can be used to register access to configurations that alwyas returns all items known. The URL looks like

http(s)://HOST/SERVLET_CONTEXT?params

where
  HOST            = host name incl port, e.g. 127.0.0.2:234
  SERVLET_CONTEXT = the base context and servlet context, e.g. /client/config/filtered
  params          = the optional parameters (scope, scopeId and format)

Formatting used by Default

The server module formats the configuration returned by default in thw following variants:

Formatting for text/json
{
  "java.vendor.url": "http://java.oracle.com/",
  "java.vendor.url.bug": "http://bugreport.sun.com/bugreport/",
  "java.vm.info": "mixed mode",
  "java.vm.name": "Java HotSpot(TM) 64-Bit Server VM",
  "java.vm.specification.name": "Java Virtual Machine Specification",
  "java.vm.specification.vendor": "Oracle Corporation",
  "java.vm.specification.version": "1.8",
  "java.vm.vendor": "Oracle Corporation",
  "java.vm.version": "25.45-b02",
  "sun.arch.data.model": "64",
  "sun.boot.class.path": "C:\apps\jdk18\jre\lib\resources.jar;C:\apps\jdk18\jre\lib\rt.jar;C:\apps\jdk18\jre\lib\sunrsasign.jar;C:\apps\jdk18\jre\lib\jsse.jar;C:\apps\jdk18\jre\lib\jce.jar;C:\apps\jdk18\jre\lib\charsets.jar;C:\apps\jdk18\jre\lib\jfr.jar;C:\apps\jdk18\jre\classes",
  "sun.boot.library.path": "C:\apps\jdk18\jre\bin",
  "sun.cpu.endian": "little",
  "sun.cpu.isalist": "amd64",
  "sun.desktop": "windows",
  "sun.io.unicode.encoding": "UnicodeLittle",
  "sun.java.command": "com.intellij.rt.execution.application.AppMain org.apache.tamaya.examples.remote.server.Start",
  "sun.java.launcher": "SUN_STANDARD",
  "sun.jnu.encoding": "Cp1252",
  "sun.management.compiler": "HotSpot 64-Bit Tiered Compilers",
  "sun.os.patch.level": "",
  "{meta}class": "org.apache.tamaya.functions.FilteredConfiguration",
  "{meta}info.filter": "java.v,sun",
  "{meta}info.format": "application/json",
  "{meta}info.timestamp": "1441463200571",
  "{meta}timestamp": "1441463200571",
  "{meta}type": "Configuration"
}
Formatting for application/xml
<configuration>
  <entry key="java.vendor.url">http://java.oracle.com/</entry>
  <entry key="java.vendor.url.bug">http://bugreport.sun.com/bugreport/</entry>
  <entry key="java.vm.info">mixed mode</entry>
  <entry key="java.vm.name">Java HotSpot(TM) 64-Bit Server VM</entry>
  <entry key="java.vm.specification.name">Java Virtual Machine Specification</entry>
  <entry key="java.vm.specification.vendor">Oracle Corporation</entry>
  <entry key="java.vm.specification.version">1.8</entry>
  <entry key="java.vm.vendor">Oracle Corporation</entry>
  <entry key="java.vm.version">25.45-b02</entry>
  <entry key="sun.arch.data.model">64</entry>
  <entry key="sun.boot.class.path">C:\apps\jdk18\jre\lib\resources.jar;C:\apps\jdk18\jre\lib\rt.jar;C:\apps\jdk18\jre\lib\sunrsasign.jar;C:\apps\jdk18\jre\lib\jsse.jar;C:\apps\jdk18\jre\lib\jce.jar;C:\apps\jdk18\jre\lib\charsets.jar;C:\apps\jdk18\jre\lib\jfr.jar;C:\apps\jdk18\jre\classes</entry>
  <entry key="sun.boot.library.path">C:\apps\jdk18\jre\bin</entry>
  <entry key="sun.cpu.endian">little</entry>
  <entry key="sun.cpu.isalist">amd64</entry>
  <entry key="sun.desktop">windows</entry>
  <entry key="sun.io.unicode.encoding">UnicodeLittle</entry>
  <entry key="sun.java.command">com.intellij.rt.execution.application.AppMain org.apache.tamaya.examples.remote.server.Start</entry>
  <entry key="sun.java.launcher">SUN_STANDARD</entry>
  <entry key="sun.jnu.encoding">Cp1252</entry>
  <entry key="sun.management.compiler">HotSpot 64-Bit Tiered Compilers</entry>
  <entry key="sun.os.patch.level"></entry>
  <entry key="{meta}class">org.apache.tamaya.functions.FilteredConfiguration</entry>
  <entry key="{meta}info.filter">java.v,sun</entry>
  <entry key="{meta}info.format">application/xml</entry>
  <entry key="{meta}info.timestamp">1441463383687</entry>
  <entry key="{meta}timestamp">1441463383687</entry>
  <entry key="{meta}type">Configuration</entry>
</configuration>
Formatting for text/plain
Configuration:
  java.vendor.url: http://java.oracle.com/,
  java.vendor.url.bug: http://bugreport.sun.com/bugreport/,
  java.vm.info: mixed mode,
  java.vm.name: Java HotSpot(TM) 64-Bit Server VM,
  java.vm.specification.name: Java Virtual Machine Specification,
  java.vm.specification.vendor: Oracle Corporation,
  java.vm.specification.version: 1.8,
  java.vm.vendor: Oracle Corporation,
  java.vm.version: 25.45-b02,
  sun.arch.data.model: 64,
  sun.boot.class.path: C:\apps\jdk18\jre\lib\resources.jar;C:\apps\jdk18\jre\lib\rt.jar;C:\apps\jdk18\jre\lib\sunrsasign.jar;C:\apps\jdk18\jre\lib\jsse.jar;C:\apps\jdk18\jre\lib\jce.jar;C:\apps\jdk18\jre\lib\charsets.jar;C:\apps\jdk18\jre\lib\jfr.jar;C:\apps\jdk18\jre\classes,
  sun.boot.library.path: C:\apps\jdk18\jre\bin,
  sun.cpu.endian: little,
  sun.cpu.isalist: amd64,
  sun.desktop: windows,
  sun.io.unicode.encoding: UnicodeLittle,
  sun.java.command: com.intellij.rt.execution.application.AppMain org.apache.tamaya.examples.remote.server.Start,
  sun.java.launcher: SUN_STANDARD,
  sun.jnu.encoding: Cp1252,
  sun.management.compiler: HotSpot 64-Bit Tiered Compilers,
  sun.os.patch.level: ,
  {meta}class: org.apache.tamaya.functions.FilteredConfiguration,
  {meta}info.filter: java.v,sun,
  {meta}info.format: text/plain,
  {meta}info.timestamp: 1441463082020,
  {meta}timestamp: 1441463082021,
  {meta}type: Configuration
Formatting for application/html
<html>
<head><title>System Configuration</title></head>
<body>
<h1>Sysem Configuration</h1>
<p>This view shows the system configuration of devbox-win at Sat Sep 05 16:30:59 CEST 2015.</p><pre>
Configuration:
  java.vendor.url: http://java.oracle.com/,
  java.vendor.url.bug: http://bugreport.sun.com/bugreport/,
  java.vm.info: mixed mode,
  java.vm.name: Java HotSpot(TM) 64-Bit Server VM,
  java.vm.specification.name: Java Virtual Machine Specification,
  java.vm.specification.vendor: Oracle Corporation,
  java.vm.specification.version: 1.8,
  java.vm.vendor: Oracle Corporation,
  java.vm.version: 25.45-b02,
  sun.arch.data.model: 64,
  sun.boot.class.path: C:\apps\jdk18\jre\lib\resources.jar;C:\apps\jdk18\jre\lib\rt.jar;C:\apps\jdk18\jre\lib\sunrsasign.jar;C:\apps\jdk18\jre\lib\jsse.jar;C:\apps\jdk18\jre\lib\jce.jar;C:\apps\jdk18\jre\lib\charsets.jar;C:\apps\jdk18\jre\lib\jfr.jar;C:\apps\jdk18\jre\classes,
  sun.boot.library.path: C:\apps\jdk18\jre\bin,
  sun.cpu.endian: little,
  sun.cpu.isalist: amd64,
  sun.desktop: windows,
  sun.io.unicode.encoding: UnicodeLittle,
  sun.java.command: com.intellij.rt.execution.application.AppMain org.apache.tamaya.examples.remote.server.Start,
  sun.java.launcher: SUN_STANDARD,
  sun.jnu.encoding: Cp1252,
  sun.management.compiler: HotSpot 64-Bit Tiered Compilers,
  sun.os.patch.level: ,
  {meta}class: org.apache.tamaya.functions.FilteredConfiguration,
  {meta}info.filter: java.v,sun,
  {meta}info.format: text/html,
  {meta}info.timestamp: 1441463459653,
  {meta}timestamp: 1441463459654,
  {meta}type: Configuration

</pre>
</body>
</html>

SPI

Scopes

As mentioned earlier in this document scopes can be used to define the exact configuration tree to be returned, e.g. as a result of combining multiple sub trees. Following an example of the code to be written to return a configuration that combines common client default entries with client specific entries:

public class ClientScopeProvider implements ScopeProvider{

    /**
     * Access the unique scope name.
     * @return the unique scope name.
     */
    public String getScopeType(){
            return "CLIENT";
    }

    @Override
    public ConfigOperator getScope(String scopeId) {
        return c ->
                ConfigurationFunctions.combine("Scoped Config CLIENT="+scopeId,
                        c.with(ConfigurationFunctions.sectionRecursive(true, "client.default")),
                        c.with(ConfigurationFunctions.sectionRecursive(true, "client." + scopeId))
                );
    }
}

This class can be registered using the ServiceContext in place. By default the ServiceLoader is used, so you will have to add the following to META-INF/services/org.apache.tamaya.server.spi.ScopeProvider:

my.full.packagename.ClientScopeProvider

Adapting the Way Configuration is Derived

Finally the effective readong and configuration handling logic can also be replaced or improved. This can be done by registering your own implementation of the interface ConfigProviderService:

public interface ConfigProviderService {
    String getConfigurationWithPath(String path, String format, String scope, String scopeId, HttpServletRequest request);
    String getConfiguration(String format, String scope, String scopeId, HttpServletRequest request);
    void updateConfiguration(String payload, HttpServletRequest request);
    void deleteConfiguration(String paths, HttpServletRequest request);
}

By default the ServiceContextManager uses the java.util.ServiceLoader for component loading, so to replace the default server code you must register a higher @Priority implementation.

Replacing the Built-In Server

We have seen earlier that starting a configuration server is pretty easy:

Server server = org.apache.tamaya.server.ConfigServer.createServer();
server.start(port);

Nevertheless one may want to replace the used implementation of Server. This can be done easily by simply registering an overriding implementation if the corresponding interface:

public interface Server {
    void start(int port);
    boolean isStarted();
    void stop();
    void destroy();
}

The ScopeManager Singleton

Finally whe implementing your own server, you might also benefit from the ScopeManager singleton. Basically this class loads all registered ScopeProvider and manages the configured scope instances:

public final class ScopeManager {
    ...

    private ScopeManager(){}

    /**
     * Get the scope given its name.
     * @param scopeId the scope name
     * @return the scope matching
     * @throws ConfigException, if nos such scope is defined.
     */
    public static ConfigOperator getScope(String scopeId, String target);

    /**
     * Get the defined scope names.
     * @return the defined scope names, never null.
     */
    public static Set<String> getScopes();

}
Last updated 2016-07-13 23:26:00 +02:00

Back to top

Version: 0.3-incubating-SNAPSHOT. Last Published: 2016-07-13.

Reflow Maven skin by Andrius Velykis.