Manage Configuration
As a Bloomreach Experience Manager developer, we want implementation-specific configuration (and potentially content) to be bootstrapped into the repository. For this to happen in Bloomreach Experience Manager, we must specify
-
When our configuration should be added during bootstrapping, and
-
Where it should be added/removed/changed.
These two aspects of contributing configuration to the repository are cleanly separated in the YAML resources. Let’s address them one by one.
Expressing Dependencies
Concept
In order to specify when a specific set of configuration should be merged into the Configuration Model, we must be able to express what dependencies our configuration has, i.e. what other configuration needs to be in place before we can successfully add our piece of configuration. For this, Bloomreach Experience Manager implements a 3-level dependency model, consisting of Groups (top), Projects (middle) and Modules (bottom)1.
All configuration must be part of exactly one Module, which belongs to exactly one Project, which in turn belongs to exactly one Group. At each level, we specify after which sibling(s) our configuration must be contributed. These dependencies are expressed using dashed arrows in the drawing above. Dependencies must only be specified between siblings, i.e Module 1aY declares its dependency on Module 1aX, but Module 1bX must not declare a dependency on Module 1aX, as they are not siblings. Instead, Project 1b must declare its dependency on Project 1a. All Groups are considered siblings.
As a best practice, the granularity of Modules, Projects and Groups should be chosen such that Modules and Projects match their counterparts in Maven terminology: i.e. typically, a Module’s scope is similar to the scope of a Maven module and a Project’s scope to that of a Maven project. As such, a Module is typically represented by a JAR file at runtime.
The Group level is primarily used to separate Bloomreach Experience Manager-based configuration from custom implementation configuration.
hcm-module.yaml
Each Module must specify these dependencies in its hcm-module.yaml2 file. When packaged into the module’s JAR, the file must be located at the root level of the archive, and typically, it lives under /src/main/resources/hcm-module.yaml in our Maven module.
An example hcm-module.yaml file looks like this:
group: name: custom after: hippo-cms project: mywebsite module: name: extra after: [base, config]
This YAML example specifies that our Module should be added to the Configuration Model by the name extra, and that it should be added after the sibling Modules base and config have been added. Furthermore, the example specifies that the Module is part of the Project mywebsite, and that - within the scope of our Module - Project mywebsite does not depend on other Projects inside the custom Group. However, since the Module also depends on configuration contributed by Bloomreach Experience Manager, it specifies that the custom Group depends on the hippo-cms Group.
Like this, our Module specifies when its configuration should be merged into the Configuration Model.
Contributing configuration
Concept
As stated previously, all configuration is contributed by a Module. For optimal maintainability, the configuration provided by a Module can be grouped into / distributed over multiple YAML Sources, which in turn can refer to (not YAML) resources. There are few restrictions to the ways in which this grouping can be done, and typically, grouping is applied semantically, i.e. based on the meaning or purpose of the configuration.
Each Source is represented by a YAML file. The Sources of a Module are associated with that Module when they are located inside the hcm-config folder of the Module. In other words, when Bloomreach Experience Manager finds a hcm-module.yaml file at the location described previously, it will check if there is a hcm-config folder in that same directory, and scan its content for files with a *.yaml extension. All found YAML files are then considered Sources of that Module.
There is no explicit link between hcm-module.yaml and the related Source YAML files, nor any ordering between Source YAML files, such that you can rearrange Sources of a Module freely and easily, as long as they stay inside the hcm-config folder.
Resources are a means to contribute content outside of a Source’s YAML format. Keeping content such as CND files, JSON, binaries etc. outside YAML Sources helps to make the YAML Source more concise and maintainable, and allows using appropriate editor support (syntax highlighting, formatting, custom operations) per type of resource data.
Sources
Sources of configuration are represented by YAML files. As described above, the exact name of a Source doesn’t matter, as long as it has a *.yaml extension.
A configuration Source supports up to 3 types of definitions:
-
namespace
These definitions are used to define namespaces (a mapping of prefixes to URIs) to be used in the repository. Namespace definitions are processed first, across all modules, in module dependency order and in the order in which they appear in the Source. All namespace definitions of a Module must be specified in a single Source, typically in a Source named main.yaml.
A namespace definition may, and typically will, also define a CND resource. A CND resource is a file used to define node types with which configuration and content can be stored in the repository. CND resources are processed second, in the same order as their namespace definitions. -
config
With the namespaces and node types in place, config definitions are used to contribute actual configuration to the repository, structured as nodes and properties. The exact format and all capabilities are described in a separate, later section. -
webfilebundle: most web applications use some static web resources, such as CSS and Javascript files, images, fonts, and templates. Using a webfilebundle definition, all resources within a directory are stored inside the repository, making the resources less static as they can be modified or replaced without redeployment of the web application.
Here is a simple example YAML Source file:
definitions: namespace: foo: uri: http://www.example.com/foo/nt/1.0 cnd: cnd/foo.cnd bar: uri: http://www.example.com/bar/nt/2.4 cnd: cnd/bar.cnd config: /hippo:configuration/hippo:modules/foo: bar: test webfilebundle: site
Above example Source defines two namespaces foo and bar, as well as their node type definitions (CNDs). The exact definitions are specified in the external resources, found in the cnd sub-folder of the folder in which this Source file resides. We include a minimalistic config definition and web file bundle to show how they exist beside the namespace definitions.
Footnotes
1 Before Bloomreach Experience Manager 12, these dependencies were implicitly expressed by using appropriate ranges of sequence numbers for the initialize items. Making them explicit in Bloomreach Experience Manager 12+ improves the understanding and maintenance of these dependencies.
2 Before Bloomreach Experience Manager 12, hippoecm-extension.xml used to be the entry point for bootstrapping configuration contributed from a JAR file. Similarly, hcm-module.yaml is the entry point for contributing configuration as of Bloomreach Experience Manager 12.