This concept is valid from ICM 11.0. Information on previous versions can be found in Concept - Configuration (valid from 7.10.12).
The configuration framework is designed to let the administrator and the developer decide from where to read a configuration. The purpose of the configuration framework is to have the ability to ask one manager for a property, but to read, if necessary, from multiple sources. Due to its extendable framework it can easily be customized.
The terms property and preference are used as synonyms in this context. The term configuration source is a placeholder for anything that can be a source for configurations, e.g., a file, a database table, an external resource, etc.
The heart of the configuration are the configuration.xml files located in the core and configuration cartridge. These files include the configuration of the configuration engine instance used at ConfigurationMgr.
The following examples illustrate how to use the configuration framework. Every access is started at the ConfigurationMgr
(which starts a configuration engine and loads the configuration.xml of each cartridge).
We recommend to extract the retrieval of configuration to context-specific configuration classes.
Providing a context-specific configuration interface and implementation has several advantages:
better documentation capabilities on configuration “getter” methods
better testability of business logic using different configuration values (mocking or providing different configurations to logic)
centralized access to configuration framework (less dependencies in business logic to platform)
In previous versions it was helpful to have different configurations on different application servers (e.g., for JobServer). In K8s all application servers should behave the same. So @ClusterConfiguration fits best for global or application server configuration.
It is recommended to provide a default configuration. This will lead to consistent behavior of “not-configured” values. Otherwise, handling “null” values can be different at different implementation classes.
import com.intershop.beehive.core.capi.configuration.Configuration; import com.intershop.beehive.core.capi.configuration.ServerConfiguration; import com.intershop.beehive.core.capi.configuration.ClusterConfiguration; public class BusinessConfigurationImpl implements BusinessConfiguration { @Inject @ClusterConfiguration Configuration clusterConfig; @Inject @ServerConfiguration Configuration serverConfig; public boolean isFeatureEabled() { return serverConfig.getBoolean("config.key.boolean", true); } public boolean getGlobalMaxSize() { return clusterConfig.getInteger("config.key.integer", 42); } }
Business configurations are mostly related to an organization, channel, or other context. Domain-specific configuration fits to most of these requirements.
// via domain configuration public Integer getMaxSize(Domain domain) { return domain.getConfiguration().getInteger("config.key.integer", 24); }
For the rare cases in which injection is not available, the ConfigurationMgr provides a static method getInstance() to provide full access the the configuration framework.
@Inject ConfigurationMgr configMgr; # or via static (avoid static class members for assignment) ConfigurationMgr configMgr = ConfigurationMgr.getInstance(); // get a configuration for scope=instance Configuration configInstance = configMgr.getInstanceConfiguration(); // get a configuration for scope=cluster Configuration configCluster = configMgr.getClusterConfiguration(); // full definition of configuration context Configuration yourConfig = configMgr.getConfiguration(String scope, ConfigurationContext context); // configuration manager provides more capabilities to define the configuration context String configDomainString = configMgr.getConfiguration(eTest).getString("config.key.string", "defaultValue");
The object path is often used in templates and queries. It is possible to access the configuration via the object path notation. The domain (#CurrentSite) has a method getConfiguration(), which is used for that example.
<isprint value="#CurrentSite:Configuration:String("<parameter>")#" /> <isprint value="#CurrentSite:Configuration:Integer(<group>.<subgroup>.<parameter-of-subgroup>)#" />
Beside the configuration files of the core and configuration cartridge, all cartridges can define their own configuration.xml to extend the lookup and behavior of the configuration framework. The file has a predefined location at the cartridge resource folder /resources/${CartridgeName}/config/configuration.xml. Important declarations take place in the following cartridges:
configuration: system scopes and finder
orm: finder declaration to find/declare orm.properties
core: main declarations of property files, readers and scopes
bc_service: service-specific configuration
The file contains any:
reader - can read a configuration file or resource from URI locations
finder - providing a lookup in the system to find URIs (which can be read by the “readers”)
writer - can write adapted configuration to a resource (URI) - is the opposite of reader
scope - define which sets belongs together
set - declares scope/finder/writer combination and represent the loaded properties
<configuration-setup> <readers> <reader class="..." /> </readers> <finders> <finder name="..." class="..." /> </finders> <writers> <writer name="..." class="..." /> </writers> <scopes> <scope name="..." depends="..." /> </scopes> <sets> <set finder="..." scope="..." writer="..." defaultWriter="..." writableKeys="..." /> </sets> </configuration-setup>
The readers section defines the readers to use:
class: the class name of the reader; if no class is found, an exception will be thrown
The finders section defines the finders to use:
name: the name by which this finder will be registered
class: the class name of the finder to use; if no class is found, an exception will be thrown
The writers section defines the writers to use:
name: the name by which this writer will be registered
class: the class name of the writer to use; if no class is found, an exception will be thrown
The scopes section defines the different scopes for which configurations will be created:
name: the name of the scope
depends: if a scope depends on the existence of other scopes
The set section defines the configuration sets that will be found and read:
finder: the finder to use to find an URI a proper reader can read and provide a configuration set
scope: the comma-separated list of scopes for which this configuration set is intended
writer: the name of a writer to use if this set should also be written
defaultWriter: used if the writer of this set is the default writer
writableKeys: the comma-separated list of keys the writer can write
any other attribute of this tag will be treated as a bean property if the defined finder and a setter method with the given attribute name will be triggered; e.g., <set fileName="..."/>
will trigger the setFileName(...)
method
The order of the configuration sets (and associated writers) in this file is important. If you have to read from two different configuration sources, the property of the first will be returned as defined in the file.
The configuration engine can provide different configurations for different purposes. Therefore, the concept of scopes was introduced. A scope is a logical structuring of configurations that are needed for this purpose.
Stating that a scope depends on (an)other scope(s), means that in order to load configurations for this scope (e.g., instance), you initially have to load all configurations on which this scope depends (startup). Since startup uses the system configuration that provides you with all system properties (intershop.HomeDirectory
), the instance scope cannot be loaded properly as long as it depends on values from the startup scope.
The fact that one scope depends on another scope does not automatically mean that if you request a configuration for this scope, you will also have configuration sets of the dependent scopes in it. That is, if you request a configuration for the scope instance which depends on startup, any startup configuration set is not necessarily in the instance scope.
The following picture outlines the currently used scopes:
The system properties include all properties defined for the scope system
. This includes:
VM properties (command line argument -Dproperty=value)
System environment variables
System environment properties take preference over Java VM properties.
Those properties will be available inside the configuration framework using the following keys:
Original key of the property (e.g., PATH
)
'system.'
plus the original key of the property (e.g., system.PATH
)
As operation systems like Linux and Windows have restrictions with environment variables, the final property lookup via the configuration framework executes the following steps for the system scope:
Transform the key as follows:
Make the key uppercase.
Replace each dot ('.') by an underscore ('_').
Replace each dash ('-') by an underscore ('_').
Transformation example: intershop.jdbc.dataSourceName
→ INTERSHOP_JDBC_DATASOURCENAME
Try a lookup using the transformed key.
If this is a success, the value is returned.
If this is a failure, try another lookup using the original key.
This allows to override properties defined in a scope below the system scope using system environment properties that are restricted by the OS.
In rare cases the property key is required to follow a strict naming (e.g., camel case). So there is another option to add properties to the system scope: there are properties supported that follow the naming scheme ISH_ENV_*
(* can be anything supported by the OS). The values of all these properties have to follow a special syntax:
key0=value0[,key1=value1[,...keyN=valueN]]
For instance there may be two ISH_ENV
_* properties that may be defined like:
ISH_ENV_DB=intershop.databaseType=mssql,intershop.jdbc.dataSourceName=defaultDB,intershop.jdbc.driverType=thin ISH_ENV_STATING=staging.process.NrOfParallelProcessors=2
If these properties are defined in this way, the following properties will be defined inside the configuration framework:
Key | Value |
---|---|
intershop.databaseType | mssql |
intershop.jdbc.dataSourceName | defaultDB |
intershop.jdbc.driverType | thin |
system.intershop.databaseType | mssql |
system.intershop.jdbc.dataSourceName | defaultDB |
system.intershop.jdbc.driverType | thin |
staging.process.NrOfParallelProcessors | 2 |
system.staging.process.NrOfParallelProcessors | 2 |
When working with system properties, be aware of the following restrictions for Windows or Linux:
OS | Supports minus ('-') | Supports dot ('.') | Supports case sensitivity |
---|---|---|---|
Windows | |||
Linux |
There is an implicit list of finders which provide URIs that can be read by the readers below.
Finder scheme | Attributes | Notes |
---|---|---|
system | Read system and environment variables. All system variables will be prefixed with | |
app-folder |
| The folder is predefined with ${IS_SHARE}/system/config/apps. The file name must match the |
cartridge |
| The folder is predefined with ${IS_TARGET}/<cartridge-name>/release/config. The file name must match the The folder can be part of each source cartridge ${IS_SOURCE}/<cartridge-name>/staticfiles/cartridge/config and will be deployed automatically. |
cartridge-folder |
| The folder is predefined with ${IS_SHARE}/system/config/cartridges. |
defaultprefs | Default values from PreferenceDefinitionPO | |
domain-folder |
| The folder is predefined with ${IS_SHARE}/system/config/domains. |
instance |
| Read network interfaces to define instance-specific file: |
preference | Preference values from PreferencePO | |
resource |
| Read a single properties file as resource using the System-ClassLoader or the cartridge-specific resource-ClassLoader |
property|file |
| Read a single properties file |
xml |
| Read a single XML file |
The configuration set will be configured with a finder and specific attribute values for this finder. Each attribute value can use the placeholder "${key}"
to reference an existing property of an upper scope. For example, the sets for domain scope can use "cluster"
scoped configuration values.
The standard configuration.xml contains placeholders for system-specific folders and environments. The way it works, e.g., for environments is shown below:
The environment is defined in environment.properties (e.g., "environment=PRD"
), which is defined in scope "instance"
first.
All "PRD"-specific configurations can be placed in PRD.properties if the configuration.xml contains:
<set finder="property" scope="cluster,server,domain" fileName="${IS_CLUSTER_CONFIG}/system/config/cluster/${environment}.properties"/>
The domain-specific configuration is more complex since a regular expression is used to check the matched files (e.g., PRD_uri.properties).
<set finder="domain-folder" scope="domain" matches="^${environment}_[\w&&[^_]]*$" fileExtensions="properties,xml"/>
In case domain properties should be environment and staging type dependent (staging.system.type
mostly defined at staging.properties
), an additional line in the configuration.xml will load such property files (e.g., PRD_editing_uri.properties).
<set finder="domain-folder" scope="domain" matches="^${environment}_${staging.system.type}_[\w&&[^_]]*$" fileExtensions="properties,xml"/>
Sets support an attribute priority that is used for sorting (default: 50). This example declares a resource based property file inside cartridge “demo” with a high priority.
<set finder="resource" scope="cluster,server,domain" cartridge="demo" resourceName="config/cluster/demo.properties" priority="100"/>
This is the list of currently available readers (package names are abbreviated):
Reader (read URI) | Notes |
---|---|
ish-system | Reads system environment |
ish-transient | Provides access to the transient configuration set |
*.properties | Only returns a configuration set for files ending with .properties |
*.xml | Only returns a configuration set for files ending with .xml |
ish-preference | Provides a configuration set that reads from preferences tables |
ish-defaultPreference | Provides a configuration set that reads from preference definitions tables |
ish-domainFolder | Provides a combined configuration set that has instances of configuration sets read from a folder that corresponds to the domain name (e.g., from ${IS_SHARE}/system/config/domains/<domain-name>_) |
ish-siteCartridge | Provides a combined configuration set with instances of configuration sets for configuration files from ${IS_SHARE}/system/config/cartridges/_ for cartridges that are assigned to the current site |
The following writers are currently used:
Writer | Notes |
---|---|
transient | Immediately updates the given configuration set, does not write the configuration to another place |
property | Writes the given configuration set to the given URI as a property file, updates the given configuration set afterwards |
There should be at least one default writer in your system that will get any values set to the configuration framework - and does not lose them. Therefore, the transient writer has been created which updates the transient configuration set.
A writer will only be used to write keys it is allowed to write. To this end, the getWritableKeys()
function is used to check whether a writer can write these keys. If no writer is found to write a key, the default writer will be used (if one is given).
The environment.properties file contains the default environment name “production”.
The environment name should only contain word- and number characters, normally one of these: production, int, dev, development, uat, uat1, etc.
The deployment configuration will declare a specific value via the ENVIRONMENT environment variable.
For development purposes, a reloading mechanism of property files has been implemented. It can be enabled by setting intershop.configuration.CheckSource
in icm.properties to true
. The delay for checking (and necessarily reloading) the property files can be set using intershop.configuration.CheckSourceInterval
(which specifies the reloading interval in milliseconds).
Who should store configuration values and where?
A developer wants to open up an implementation for configuration values. So the developer has to include a line to get the configuration from the framework.
String value = ConfigurationMgr.getString(key, defaultValue);
Providing a default value in here is the direct and best way to do it, because the code does not depend on a further configuration step.
A developer of an application type can override this defaultValue
via a cartridge property file, located in the cartridge source directory resources/resources/<cartridge>/config. These configurations are included in the configuration finder "cartridge".
An administrator can declare configuration values via environment variables.
Configuration values of business users should be stored in the database. For this purpose, two possibilities are available at the moment:
Application preferences (for functionality and behavior) and
Domain preferences (for data-related configuration)
The developer of the business management application is responsible for deciding on the correct location of the property.
The developers often define configuration values for different environments and domain. This can be reached by own configuration.xml declaration, which can provide domain- and environment-specific configuration values.
There is another scope named service with finder, reader, and writer. This scope is used for the Managed Service Framework.
The finder creates URIs for the service scope which only the reader can read and for which only the writer is allowed to write.
The reader creates configuration sets which look at the ServiceConfigurationPOAttributeValuePO
table using the ServiceConfigurationPO
which has to be provided in the context used to get the configuration values from the set.
The writer, on the other hand, writes in the same table, also using the ServiceConfigurationPO
provided in the context.
The service scope is somehow a standalone scope. If someone requests configurations from this scope, only one reader is triggered returning only one type of configuration set. Currently this scope does not contain other properties than properties from the ServiceConfigurationPOAttributeValuePO
table. Values from the appserver.properties or PreferencePO
table are not included, for instance. But of course, this can be changed any time by creating an own configuration.xml file.
The information provided in the Knowledge Base may not be applicable to all systems and situations. Intershop Communications will not be liable to any party for any direct or indirect damages resulting from the use of the Customer Support section of the Intershop Corporate Web site, including, without limitation, any lost profits, business interruption, loss of programs or other data on your information handling system.