[[configuration]]

== Configuration

*org.jpos.core.Configuration* is a general purpose property container
extensively used by jPOS components.

The Configuration interface looks like this:

[source,java]
----

   package org.jpos.core;

   public interface Configuration {
     public void put (String name, Object value);
     public String get (String propertyName);
     public String get (String propertyName, String defaultValue);
     public String[] getAll  (String propertyName);
     public int[] getInts  (String propertyName);
     public long[] getLongs (String propertyName);
     public double[] getDoubles (String propertyName);
     public boolean[] getBooleans (String propertyName);
     public int getInt (String propertyName);
     public int getInt (String propertyName, int defaultValue);
     public long getLong (String propertyName);
     public long getLong (String propertyName, long defaultValue);
     public double getDouble (String propertyName);
     public double getDouble (String propertyName, double defaultValue);
     public boolean getBoolean (String propertyName);
     public boolean getBoolean (String propertyName, boolean defaultValue);
   }
----

Having our own Configuration interface lets us implement it in different ways.
We have a very little class called SimpleConfiguration backed by a
java.util.Properties, but nothing prevents us from creating a more
sophisticated Configuration object capable of providing dynamic data (such as
an SQLConfiguration, JavaSpacesConfiguration and the like).

jPOS-EE implements a SysConfigConfiguration that reads objects from its +sysconfig+ SQL table.

We also have a very simple interface called Configurable:

[source,java]
----

   package org.jpos.core;

   public interface Configurable {
     public void setConfiguration (Configuration cfg)
        throws ConfigurationException;
   }

----

Later, while looking at the Q2 application we'll see that Q2 pushes a
configuration object by calling the +setConfiguration+ method on
+Configurable+ objects.

[source,xml]
----
    <object name="myObject" class="com.mycompany.MyObject">
      <property name="myProperty" value="any Value" />
      <property file="cfg/myprops.yml" />
    </object>
----

Should +com.mycompany.MyObject+ implement +Configurable+, Q2 would call its  +setConfiguration()+ method
providing access to the underlying +myProperty+ property.

It's interesting to note that Q2 provides the ability to have array of
properties under the same name, e.g.:

[source,xml]
----

    <object name="myObject" class="com.mycompany.MyObject">
     <property name="myProperty" value="Value A" />
     <property name="myProperty" value="Value B" />
     <property name="myProperty" value="Value C" />
    </object>

----

where one can call handy methods like  +String[] getAll(String)+.

+setConfiguration(Configuration cfg)+ can check the Configuration object and might
throw a +ConfigurationException+ in case a required property is not present or
is invalid.

[TIP]
=====
SimpleConfiguration recognizes and de-references properties with the
format: `${xxx}` and searches for a system property, or operating system
environment variable under the `xxx` name.
As a fallback mechanism of last resort, the property can be resolved from an _environment file_, in
YAML or _properties_ file syntax, found in the `cfg` directory (default filename `default.yml`
or `default.cfg`, which can be overridden by the `jpos.env` system property).

You can add a default value within the expression itself, using the `:` (colon) separator.
For example `${xxx:def_value}`. If the property is not found, the default value will be used.

The format `$sys{xxx}` de-references just from system properties,
`$env{xxx}` just from the operating system environment, and `$cfg{xxx}` just from the environment file (the.


In the rare case where a value with the format `${...}` is required, the
`$verb{${...}}` format (verbatim) can be used.

In addition, a property named `xx.yy.zz` can be overridden by the environment
variable `XX_YY_ZZ` (note that dots are replaced by underscore, and property
name is converted to uppercase.
=====

The jPOS `Environment` has a ServiceLoader based plugin mechanism that support
`EnvironmentProviders`. jPOS comes with two stock providers:

  - `FileEnvironmentProvider` (prefix `file::`).
  - `ObfEnvironmentProvider` (prefix `obf::`).

A YAML file (i.e. `cfg/default.yml`) containing an entry like this:

[source,yaml]
-------------
db:
    pass: file::/var/secure/dbpass.txt
-------------

Would obtain the value of the `${db.pass}` property from the `/var/secure/dbpass.txt` file.

Likewise, an obfuscated entry like this:

[source,yaml]
-------------
db:
    pass: obf::Ir8LYtvCYsaXANchMMrBqq5Gs2DnMEstYAAAAA
-------------

would de-obfuscate the base64 encoded secret.

[WARNING]
=========
Obfuscation is that, just obfuscation, not encryption.
It's used to prevent secrets from leaking to ocassional observers and
to demonstrate the use of the EnvironmentProviders. For production
deployments, HSM based EnvironmentProvider should be used instead.
=========

[TIP]
=====
The `obf` CLI command can be used to create these obfuscated entries.
=====

Since version 2.1.7, jPOS supports the `@Config` annotation that pushes configuration properties (String, int, Integer, long, Long) down to classes
instanciated through QFactory (Qbeans, Transaction Participants, etc.), i.e:

[source,java]
-------------
  public class MyClass {
      @Config("port") int port;
  }
-------------

The 'port' variable would be picked from:


[source,xml]
------------
  ...
     <property name="port" value="1234" />
  ...

------------

from the QBean or participant configuration.

[TIP]
=====
When using multiple environments (i.e. `-Eprod -Enode1`) you can specify

`<property file="cfg/myconfig.yml" env="true" />`

and the system will load the files `myconfig.yml`, `myconfig-prod.yml` and `myconfig-node1.yml`.
=====

