Configuration Model

This page provides a conceptual overview of how Talon microservices are configured, including the Domain Descriptor Language (DDL) and global environment properties.

Overview

Talon microservices don't interact directly with infrastructure components. Configuration separates business logic from operational concerns like messaging, storage, and high availability. Talon provides two complementary configuration mechanisms for configuring microservices:

  1. DDL (Domain Descriptor Language): XML-based configuration for components (buses, applications, XVMs)

  2. Global Environment: Property-based configuration for runtime behavior (statistics, optimization, trace levels)

Two Configuration Mechanisms

DDL (Domain Descriptor Language)

DDL is an XML-based configuration schema that defines microservice components and their settings. It is primarily used to configure:

  • Message buses and channels

  • Applications (event handlers, storage, high availability)

  • XVMs (execution containers)

  • System details and metadata

  • And more...

Example DDL:

Accessing DDL Configuration in User Code:

User code accesses DDL configuration through component descriptors that are populated from the DDL:

Talon Runtime Usage: The Talon runtime uses the same mechanism internally - it creates component descriptors from the DDL to configure buses, stores, engines, and other components.

Global Environment

The global environment provides property-based configuration for Talon runtime behavior. It is primarily used to configure:

  • Statistics collection settings

  • Optimization modes (latency vs throughput)

  • Trace logging levels

  • Discovery configuration

  • Platform-wide defaults

  • And more...

Global Environment Sources (in order of increasing precedence):

  1. System Properties (lowest precedence)

  2. App Property File

    Specify file via System property: java -Dnv.app.propfile=app.properties ...

    Or via environment variable: export nv_app_propfile=app.properties

  3. Environment Variables

  4. DDL <env> Section (highest precedence)

Precedence: Properties in the DDL <env> section override all other sources. System properties have the lowest precedence.

Accessing Global Environment in User Code:

The preferred mechanism is to use the @Configured annotation to inject properties from the DDL <env> section:

Alternatively, use the XRuntime API for programmatic access:

Talon Runtime Usage: The Talon runtime uses XRuntime and UtlEnv APIs internally to access global configuration properties for statistics collection, optimization, trace levels, and other runtime behavior.

DDL vs Global Environment

Aspect
DDL
Global Environment

Format

XML elements and attributes

Property key-value pairs

Configures

Components (buses, apps, xvms, channels)

Runtime behavior (stats, optimization, trace)

Accessed In User Code

Via component descriptors

Via @Configured annotation or XRuntime API

Accessed By Platform

Via component descriptors

Via XRuntime and UtlEnv APIs

Example

<captureTransactionLatencyStats>true</captureTransactionLatencyStats>

nv.msg.latency.stats=true

Typical Use

Configure bus connections, app settings, XVM heartbeats

Enable stats, set optimization mode, configure trace levels

When to Use Each

Use DDL when:

  • Configuring message bus connections and channels

  • Configuring application messaging, storage, and HA settings

  • Configuring XVM heartbeats and managed applications

  • Setting component-specific parameters

  • Configuration is specific to a component instance

Use Global Environment when:

  • Enabling runtime statistics collection

  • Setting optimization modes (latency vs throughput)

  • Configuring trace logging levels

  • Setting platform-wide defaults

  • Configuration applies globally across the runtime

Note: Some configuration settings can be specified using either mechanism. For example, trace levels for certain AEP engine loggers can be set via DDL or via global environment properties. When both mechanisms are available, using DDL is recommended as it keeps configuration centralized in the DDL file.

Complete Configuration Example

Here's a complete example showing both mechanisms working together:

Accessing the configuration in user code:

Configuration Architecture

Now that we understand the two configuration mechanisms at a high level, let's dive into the architectural details of how Talon processes and stores configuration.

Configuration Repository

Internally, Talon uses a configuration repository to store component configuration parsed from the DDL. The repository is an internal platform component that developers don't interact with directly.

Key characteristics:

  • The repository stores configuration in a proprietary format keyed by hierarchical names

  • Components are uniquely identified by hierarchical names comprised of their type and unique name

    • Example: An AEP engine named "order-processor" has the repository name /aep/engines/order-processor

  • The Talon runtime uses these hierarchical names internally when loading descriptors from the repository

  • The repository implements the com.neeve.config API (internal to Talon runtime)

Note: Developers never directly interact with the configuration repository. Platform components and user code interact with higher-level descriptor objects, not the repository itself.

Global Environment Storage

The global environment is stored in a map-like structure maintained by the Talon runtime. It is populated from multiple sources during initialization and provides a unified view of all runtime properties.

Characteristics:

  • Assembled from System properties, app propfile, environment variables, and DDL <env> section

  • DDL <env> properties have highest precedence

  • XVM-specific <env> sections are merged with the global <env> section

  • Accessed via XRuntime.getValue() and UtlEnv APIs

Environment Sources and Precedence

The global environment is populated from multiple sources. When the same property is defined in multiple sources, the source with higher precedence wins.

Sources in increasing precedence order (lowest to highest):

  1. System Properties (lowest precedence)

    • Java system properties (-Dproperty=value)

  2. App Propfile

    • Properties file specified via nv_app_propfile or -Dnv.app.propfile

    • Overrides System properties

  3. Environment Variables

    • OS-level environment variables

    • Override App propfile

  4. DDL <env> Section (highest precedence)

    • Properties specified in the <env> element

    • Union of global <env> and XVM-specific <env> sections

    • Highest precedence (overrides all other sources)

Example showing precedence:

Result: nv.optimizefor will be none because DDL <env> has highest precedence.

How DDL and Global Environment Interact

Both mechanisms work together during application initialization:

  1. Assemble Global Environment: The Talon runtime collects properties from System properties, app propfile, environment variables, and merges them (with appropriate precedence)

  2. Parse DDL File: The Talon runtime reads and parses the XML configuration file

  3. Merge DDL <env> Section: Properties from the DDL <env> section are merged into the global environment (with highest precedence)

  4. Variable Substitution: During DDL parsing, variable references like ${VARNAME::DEFAULT} are substituted from the global environment

  5. Populate Repository: Component configuration from DDL elements (<buses>, <apps>, <xvms>) is stored in the configuration repository

  6. Create Components: The Talon runtime creates components by loading descriptors from the repository and using global environment for runtime configuration

Example showing interaction:

In this example:

  • ${solace.host} is substituted with 192.168.1.100 from the global environment

  • ${solace.vpn} is substituted with trading from the global environment

  • nv.msg.latency.stats configures runtime statistics collection

  • The <bus> element populates the configuration repository for component creation

Configuration Lifecycle

The configuration of Talon components is tied closely to the application lifecycle. Understanding this lifecycle helps clarify when and how configuration is applied.

Configure Phase

When an application is launched, the first task is to populate both the configuration repository and global environment before any Talon runtime machinery is invoked. This ensures the runtime machinery picks up the correct configuration.

Steps:

  1. Assemble the global environment from System properties, app propfile, environment variables, and DDL <env> section (with DDL <env> having highest precedence)

  2. Parse the DDL file and populate the configuration repository

  3. Use the environment for variable substitution during DDL parsing

Run Phase

Once the configuration repository and environment are populated, the application can create and use platform components.

Steps for creating a component:

  1. Create an instance of the component descriptor (e.g., AepEngineDescriptor)

  2. Load the descriptor contents from the configuration repository using its load() method

  3. The descriptor initializes itself using configuration from the repository (keyed by the component's hierarchical name)

  4. Create the component using the loaded descriptor

Note: The hierarchical naming and repository access happen internally. Developers work with descriptor objects, not the repository directly.

Populating Configuration from DDL

How the DDL populates the configuration repository depends on whether Talon is used in an embedded or non-embedded manner.

Embedded Use

Talon should be used in an embedded manner when the application's main entry point is in the application code.

Talon allows applications to describe configuration in XML form (DDL) and programmatically initialize the repository using the XML descriptor.

  • Schema: Configuration is defined by the Domain Descriptor Language (DDL) schema, x-ddl.xsd

  • Configuration Class: Use VMConfigurer to configure the Talon runtime from an XML descriptor

  • Recommendation: This is the recommended mechanism if configuration can be stored in or converted to XML form

Example:

Component Descriptors (PROGRAMMATIC)

Each Talon component has a companion configuration descriptor for programmatic configuration. Descriptors implement setters/getters for configuration attributes and can save properties to the repository.

This mechanism is suited when configuration cannot be easily transformed to XML form.

Component Descriptors:

Component
Descriptor Class
Description

SMA Bus

Configures a message bus

SMA Channel

Configures a bus channel

ODS Store

Configures the store for an engine (providing HA)

ODS Store Replicator

Configures store replication to backup members

ODS Persister

Configures store disk persistence

ODS ICR

Configures store inter-cluster replication (e.g., remote data center)

AEP Engine

Configures the application's AepEngine

XVM (Talon XVM)

Configures an XVM

Example (augmenting XML configuration programmatically):

Tip: With the exception of SrvConfigDescriptor, applications can augment configuration seeded by the XML descriptor programmatically using component descriptors.

Configuration Script (INTERNAL)

Talon supports an internal scripting format for configuration. This format is not recommended for external use and is listed for informational purposes only.

Non-Embedded Use

Talon is used in a non-embedded manner when the application's main entry point is in the Talon XVM.

In this mode:

  • The configuration repository is initialized from external storage via a persistence plugin

  • The recommended approach is to use deployment tools like Robin for configuration, deployment, and management

  • Robin processes the same XML descriptor but materializes it from external storage rather than the filesystem

Accessing Environment Properties in Application Code

The preferred mechanism for accessing user-defined properties from the global environment is to declare them in the DDL <env> section and inject them using the @Configured annotation:

See Injecting Configuration for complete details on using @Configured.

Alternative programmatic access is available via the XRuntime API:

Note: The UtlEnv API is also available but should only be used when directed by Neeve support.

DDL Features

The DDL provides several powerful features for managing configuration:

Variable Substitution

DDL supports variable substitution using the syntax ${VARNAME::DEFAULT} where:

  • VARNAME is the property name to substitute

  • DEFAULT is an optional default value if the property is not found

Variables are substituted from the global environment (System properties, app propfile, environment variables, DDL <env>).

Example:

If solace.host is not defined, the substitution fails. If solace.port is not defined, it defaults to 55555.

Substitution Sources (in precedence order):

  1. System properties

  2. App propfile

  3. Environment variables

  4. DDL <env> section (highest precedence)

Special Characters in Property Names:

  • . (period) is used as a hierarchical separator in XML

  • - (dash) and _ (underscore) are allowed in property names

Example with hierarchical properties:

This creates the property nv.msg.latency.stats=true.

DDL Overrides

Any DDL attribute or element value can be set or overridden at runtime using specially-named system properties. DDL overrides serve two purposes:

  1. Set values - Provide configuration values for elements not present in the DDL XML

  2. Override values - Change configuration values that are present in the DDL XML

This allows configuration to be externalized without modifying the DDL file, which is particularly useful for environment-specific configuration, runtime tuning, and CI/CD deployments where the same DDL is used across environments.

Override Property Naming Pattern

DDL override properties follow a hierarchical naming pattern that mirrors the XML structure:

Components:

  • Prefix: x. (default, configurable via nv.ddl.override.prefix system property)

  • Section: Top-level DDL section (busProviders, buses, apps, xvms)

  • Instance Key: The name attribute value of the instance (e.g., bus name, app name, XVM name)

  • Path: Dot-separated path following the XML hierarchy to the target element or attribute

Basic Examples

Example 1: Override an existing value

Override a bus descriptor defined in DDL:

Example 2: Set a value not in DDL

Set storage configuration without it being in the DDL:

The above creates the storage configuration as if it were present in the DDL.

Example 3: Override nested settings:

Change an existing nested value in the DDL:

Example 4: Set XVM heartbeat settings:

Set heartbeat configuration that doesn't exist in DDL:

Example 5: Override existing XVM heartbeat settings:

Change an existing heartbeat interval value:

Special Cases

1. Key Attributes (Not Overridable)

Attributes that serve as keys (typically name attributes) cannot be overridden because they uniquely identify instances:

2. Environment Properties

Properties in the <env> section use the x.env. prefix for DDL overrides but are accessed directly (without prefix) in code:

The x.env.* pattern allows you to set environment properties that aren't in the DDL <env> section, or override ones that are.

3. Template Configuration

Template properties use a special pattern with the templates keyword:

4. Nested Keyed Elements

When child elements have their own name attribute, include it in the path:

Setting Override Properties

Override properties can be set via multiple mechanisms:

1. System Properties (command line):

2. Environment Variables:

3. App Properties File:

Specify the properties file via: -Dnv.app.propfile=app.properties

Override Precedence

When both DDL and override properties are specified:

  1. DDL Override properties (highest precedence)

  2. DDL XML values (lowest precedence)

This allows runtime values to override static configuration.

Pattern Construction Examples

XML Element Path
Override Property

<busProviders><provider name="custom">

x.busProviders.custom.*

<buses><bus name="mkt-data" descriptor="...">

x.buses.bus.mkt-data.descriptor

<buses><bus name="mkt-data"><channels><channel name="orders">

x.buses.mkt-data.orders.*

<apps><app name="myapp" mainClass="...">

x.apps.myapp.mainClass

<apps><app name="myapp"><storage><persistence enabled="true">

x.apps.myapp.storage.persistence.enabled

<xvms><xvm name="myxvm"><heartbeats interval="5">

x.xvms.myxvm.heartbeats.interval

For complete override property documentation for all DDL elements, see the Configuration Reference.

DDL Templates

Since 3.8: DDL templates reduce configuration repetition by allowing you to define reusable configuration blocks.

Example:

Templates are applied first, then bus-specific settings override template values.

DDL Profiles

Since 3.8: DDL profiles enable environment-specific configuration within a single DDL file.

Example:

Activating a profile:

When a profile is activated, its configuration overrides the default configuration.

DDL Processing Order

The DDL is processed in the following order:

  1. Parse DDL file: Read and validate XML structure

  2. Assemble global environment: Merge System properties, app propfile, environment variables, DDL <env> (with precedence)

  3. Apply active profile: If a profile is specified, merge profile configuration

  4. Perform variable substitution: Replace ${VARNAME::DEFAULT} references from environment

  5. Apply DDL overrides: Apply command-line x.* overrides

  6. Populate repository: Store component configuration in repository

Troubleshooting Configuration

Enabling DDL Trace

To troubleshoot configuration issues, enable DDL trace logging:

This outputs detailed information about:

  • Variable substitution

  • Profile activation

  • DDL parsing and validation

  • Property precedence resolution

DDL trace output goes to the nv.ddl logger at INFO level.

Common Issues

Variable substitution fails:

  • Check that the property is defined in one of the environment sources

  • Verify property name spelling (case-sensitive)

  • Enable DDL trace to see substitution details

Property has wrong value:

  • Check precedence order (DDL <env> has highest precedence)

  • Enable DDL trace to see which source provided the value

  • Verify profile activation if using profiles

Property cannot be set in <env> section:

  • Some properties (like nv.ddl.trace) must be set via System property because they're needed before DDL parsing

  • See Configuration Reference for the "Can Set in <env>?" indicator

Next Steps

  1. Understand the difference between DDL (component configuration) and Global Environment (runtime properties)

  2. Review the Configuration Reference for complete DDL syntax and global properties

  3. Learn how to use DDL templates and profiles for environment portability

  4. Use Injecting Configuration to access configuration in your application code

  5. Enable DDL trace logging to troubleshoot configuration issues

Last updated