Chapter 8. The ConfigurationBuilder API
8.1. The ConfigurationBuilder API
The ConfigurationBuilder API is a programmatic configuration API in Red Hat JBoss Data Grid.
The ConfigurationBuilder API
is designed to assist with:
- Chain coding of configuration options in order to make the coding process more efficient
- Improve the readability of the configuration
In Red Hat JBoss Data Grid, the ConfigurationBuilder API is also used to enable CacheLoaders and configure both global and cache level operations.
Programmatic configuration can only be accomplished in Red Hat JBoss Data Grid’s Library Mode.
8.2. Using the ConfigurationBuilder API
8.2.1. Programmatically Create a CacheManager and Replicated Cache
Programmatic configuration in Red Hat JBoss Data Grid almost exclusively involves the ConfigurationBuilder API and the CacheManager. The following is an example of a programmatic CacheManager configuration:
Configure the CacheManager Programmatically
EmbeddedCacheManager manager = new DefaultCacheManager("my-config-file.xml"); Cache defaultCache = manager.getCache(); Configuration c = new ConfigurationBuilder().clustering().cacheMode(CacheMode.REPL_SYNC) .build(); String newCacheName = "repl"; manager.defineConfiguration(newCacheName, c); Cache<String, String> cache = manager.getCache(newCacheName);
- Create a CacheManager as a starting point in an XML file. If required, this CacheManager can be programmed in runtime to the specification that meets the requirements of the use case.
Create a new synchronously replicated cache programmatically.
Create a new configuration object instance using the ConfigurationBuilder helper object:
In the first line of the configuration, a new cache configuration object (named
c
) is created using the ConfigurationBuilder . Configurationc
is assigned the default values for all cache configuration options except the cache mode, which is overridden and set to synchronous replication (REPL_SYNC
).Define or register the configuration with a manager:
In the third line of the configuration, the cache manager is used to define a named cache configuration for itself. This named cache configuration is called
repl
and its configuration is based on the configuration provided for cache configurationc
in the first line.-
In the fourth line of the configuration, the cache manager is used to obtain a reference to the unique instance of the
repl
that is held by the cache manager. This cache instance is now ready to be used to perform operations to store and retrieve data.
8.2.2. Cluster-Wide Dynamic Cache Creation
When using the getCache()
method, like in the above example, a cache will be created only on a single node. If the cache needs to be created dynamically on any new nodes that join the cluster, use the createCache()
method instead:
Cache<String, String> cache = manager.administration().createCache("newCacheName", "newTemplate");
While a cache created this way will be available on all nodes in the cluster, it will also be ephemeral: shutting down the entire cluster and restarting it will not automatically recreate the caches. To make the caches persistent, use the PERMANENT
flag as follows:
Cache<String, String> cache = manager.administration().withFlags(AdminFlag.PERMANENT).createCache("newCacheName", "newTemplate");
In order for the above to work, global state must be enabled and a suitable configuration storage selected. The available configuration stores are:
-
VOLATILE
: as the name implies, this configuration storage does not supportPERMANENT
caches. -
OVERLAY
: this stores configurations in the global shared state persistent path in a file named caches.xml. -
MANAGED
: this is only supported in server deployments, and will storePERMANENT
caches in the server model. -
CUSTOM
: a custom configuration store.
8.2.3. Create a Customized Cache Using the Default Named Cache
The default cache configuration (or any customized configuration) can serve as a starting point to create a new cache.
As an example, if the infinispan-config-file.xml specifies the configuration for a replicated cache as a default and a distributed cache with a customized lifespan value is required. The required distributed cache must retain all aspects of the default cache specified in the infinispan-config-file.xml file except the mentioned aspects.
Customize the Default Cache
String newCacheName = "newCache"; EmbeddedCacheManager manager = new DefaultCacheManager("infinispan-config-file.xml"); Configuration dcc = manager.getDefaultCacheConfiguration(); Configuration c = new ConfigurationBuilder().read(dcc).clustering() .cacheMode(CacheMode.DIST_SYNC).l1().lifespan(60000L).enable() .build(); manager.defineConfiguration(newCacheName, c); Cache<String, String> cache = manager.getCache(newCacheName);
-
Read an instance of a default
Configuration
object to get the default configuration. -
Use the
ConfigurationBuilder
to construct and modify the cache mode and L1 cache lifespan on a new configuration object. - Register/define your cache configuration with a cache manager.
-
Obtain a reference to
newCache
, containing the specified configuration.
8.2.4. Create a Customized Cache Using a Non-Default Named Cache
A situation can arise where a new customized cache must be created using a named cache that is not the default. The steps to accomplish this are similar to those used when using the default named cache for this purpose.
The difference in approach is due to taking a named cache called replicatedCache
as the base instead of the default cache.
Creating a Customized Cache Using a Non-Default Named Cache
String newCacheName = "newCache"; EmbeddedCacheManager manager = new DefaultCacheManager("infinispan-config-file.xml"); Configuration rc = manager.getCacheConfiguration("replicatedCache"); Configuration c = new ConfigurationBuilder().read(rc).clustering() .cacheMode(CacheMode.DIST_SYNC).l1().lifespan(60000L).enable() .build(); manager.defineConfiguration(newCacheName, c); Cache<String, String> cache = manager.getCache(newCacheName);
-
Read the
replicatedCache
to get the default configuration. -
Use the
ConfigurationBuilder
to construct and modify the desired configuration on a new configuration object. - Register/define your cache configuration with a cache manager.
-
Obtain a reference to
newCache
, containing the specified configuration.
8.2.5. Using the Configuration Builder to Create Caches Programmatically
As an alternative to using an xml file with default cache values to create a new cache, use the ConfigurationBuilder API to create a new cache without any XML files. The ConfigurationBuilder API is intended to provide ease of use when creating chained code for configuration options.
The following new configuration is valid for global and cache level configuration. GlobalConfiguration objects are constructed using GlobalConfigurationBuilder while Configuration objects are built using ConfigurationBuilder.
8.2.6. Global Configuration Examples
8.2.6.1. Globally Configure the Transport Layer
A commonly used configuration option is to configure the transport layer. This informs Red Hat JBoss Data Grid how a node will discover other nodes:
Configuring the Transport Layer
GlobalConfiguration globalConfig = new GlobalConfigurationBuilder() .transport().defaultTransport() .build();
8.2.6.2. Globally Configure the Cache Manager Name
The following sample configuration allows you to use options from the global JMX statistics level to configure the name for a cache manager. This name distinguishes a particular cache manager from other cache managers on the same system.
Configuring the Cache Manager Name
GlobalConfiguration globalConfig = new GlobalConfigurationBuilder() .globalJmxStatistics() .cacheManagerName("SalesCacheManager") .mBeanServerLookup(new JBossMBeanServerLookup()) .enable() .build();
8.2.6.3. Globally Configure JGroups
Red Hat JBoss Data Grid must have an appropriate JGroups configuration in order to operate in clustered mode; the following sample configuration demonstrates how to pass a predefined JGroups configuration file into the configuration:
JGroups Programmatic Configuration
GlobalConfiguration gc = new GlobalConfigurationBuilder() .transport() .defaultTransport() .addProperty("configurationFile","jgroups.xml") .build();
Red Hat JBoss Data Grid will first search for jgroups.xml in the classpath; if no instances are found in the classpath it will then search for an absolute path name.
8.2.7. Cache Level Configuration Examples
8.2.7.1. Cache Level Configuration for the Cluster Mode
The following configuration allows the use of options such as the cluster mode for the cache at the cache level rather than globally:
Configure Cluster Mode at Cache Level
Configuration config = new ConfigurationBuilder() .clustering() .cacheMode(CacheMode.DIST_SYNC) .sync() .l1().lifespan(25000L).enable() .hash().numOwners(3) .build();
8.2.7.2. Cache Level Eviction and Expiration Configuration
Use the following configuration to configure expiration or eviction options for a cache at the cache level:
Configuring Expiration and Eviction at the Cache Level
Configuration config = new ConfigurationBuilder() .memory() .size(20000) .expiration() .wakeUpInterval(5000L) .maxIdle(120000L) .build();
8.2.7.3. Cache Level Configuration for JTA Transactions
To interact with a cache for JTA transaction configuration, configure the transaction layer and optionally customize the locking settings. For transactional caches, it is recommended to enable transaction recovery to deal with unfinished transactions. Additionally, it is recommended that JMX management and statistics gathering is also enabled.
Configuring JTA Transactions at Cache Level
Configuration config = new ConfigurationBuilder() .locking() .concurrencyLevel(10000).isolationLevel(IsolationLevel.REPEATABLE_READ) .lockAcquisitionTimeout(12000L).useLockStriping(false).writeSkewCheck(true) .transaction() .transactionManagerLookup(new GenericTransactionManagerLookup()) .recovery().enable() .jmxStatistics().enable() .build();
8.2.7.4. Cache Level Configuration Using Chained Persistent Stores
The following configuration can be used to configure one or more chained persistent stores at the cache level:
Configuring Chained Persistent Stores at Cache Level
Configuration conf = new ConfigurationBuilder() .persistence() .passivation(false) .addSingleFileStore() .location("/tmp/firstDir") .persistence() .passivation(false) .addSingleFileStore() .location("/tmp/secondDir") .build();
8.2.7.5. Cache Level Configuration for Advanced Externalizers
An advanced option such as a cache level configuration for advanced externalizers can also be configured programmatically as follows:
Configuring Advanced Externalizers at Cache Level
GlobalConfiguration globalConfig = new GlobalConfigurationBuilder() .serialization() .addAdvancedExternalizer(new PersonExternalizer()) .addAdvancedExternalizer(999, new AddressExternalizer()) .build();
8.2.7.6. Cache Level Configuration for Partition Handling (Library Mode)
In the event of a split brain scenario a partition handling strategy can be selected to provide either consistency or availability of data. If availability is chosen and data becomes inconsistent a merge policy can also be selected to define how data is merged upon node rejoins. An example configuration is shown below.
ConfigurationBuilder dcc = new ConfigurationBuilder(); dcc.clustering().partitionHandling() .whenSplit(PartitionHandling.DENY_READ_WRITES) .mergePolicy(MergePolicies.REMOVE_ALL);
Additional information regarding partition handling is found in the Administration and Configuration Guide.
To configure Partition Handling in Client-Server Mode it must be enabled declaratively as described in the Administration and Configuration Guide.