Introduction

A global cache stores reusable data, enabling sharing within and between integration servers, eliminating the need for alternatives like databases. You can store data in the cache with one message flow node and retrieve it with another. Data caching can be configured with an external WebSphere® eXtreme Scale grid, local embedded cache, or global embedded cache. This post focuses on the global embedded cache option.

Key Terminologies to Understand Before We Start

Before diving into configuration, it’s essential to understand a few key caching terminologies:

  • Catalog Server:
    The catalog server is an embedded component in an integration server. It manages the placement of cache data and monitors the health of container servers. Every global cache must include at least one catalog server.
  • Container Servers:
    These are embedded components within the integration server that store subsets of the cache data.
  • GRID:
    The catalog servers and container servers in the IBM App Connect Enterprise global cache work together to form a WebSphere eXtreme Scale grid.
  • Maps:
    Data is stored in maps, which are data structures that associate keys with values. While the global cache has a default map, it can also include multiple maps.
  • Catalog Domain Name:
    Catalog servers and container servers within a grid use the same catalog domain name to collaborate. Servers with different domain names cannot work together within the same grid.

Configuring the embedded global cache

We will configure a basic topology where a single integration server hosts both a catalog server and a container server. For high availability, other topologies can also be used, such as 1 catalog server with 4 container servers or 2 catalog servers with 4 container servers. Follow below steps to enable cache.

  • Step 1: Create an integration server named CatalogAndContainerServer.
  • Step 2: Open the server configuration file (CatalogAndContainerServer\server.conf.yaml) using any text editor.
  • Step 3: Update the GlobalCache section within the server.conf.yaml file to set the required properties. (see below)
  • Step 4: Restart the integration server to apply the changes.
  • Upon restarting, CatalogAndContainerServer will function as both a catalog server and a container server. Now embedded global cache is ready to hold the data.

For step 3, update below properties as follow.

GlobalCache:
cacheOn: true
cacheServerName: 'MyCatalogServer1'
catalogServiceEndPoints: 'localhost:2800'
catalogDomainName: 'WMB_MyCacheDomain'
catalogClusterEndPoints: 'MyCatalogServer1:localhost:2803:2801'
clientsDefaultToSSL: false
deploymentPolicyCustomFile: ''
enableCatalogService: true
enableContainerService: true
enableJMX: true
listenerHost: 'localhost'
listenerPort: 2800

Interaction with the global cache

We can use Mapping node or Java Compute node to store and retrieve data in a map in the global cache. in this post we will use Java Compute node to interact with global cache. Create an application with following message flows in it.

Application Structure

create a getCache message flow with following nodes, HTTP Input, Java Compute, and HTTP Reply node.

Get Cache message flow

double click Java Compute node and paste the following code within “Add user code below” section.

   // ----------------------------------------------------------
// Add user code below
String Lookup_Type = null;
String key = null;
String value = null;
Lookup_Type = inputLocalEnv.getFirstElementByPath("/HTTP/Input/QueryString/Lookup_Type").getValueAsString();
key = inputLocalEnv.getFirstElementByPath("/HTTP/Input/QueryString/Key").getValueAsString();

MbGlobalMap globalmap;
globalmap = MbGlobalMap.getGlobalMap(Lookup_Type);
try {
value = globalmap.get(key).toString();
} catch (NullPointerException e) {
value = "not found";
}


MbElement outRoot = outMessage.getRootElement();
MbElement outJsonRoot = outRoot.createElementAsLastChild(MbJSON.PARSER_NAME);
MbElement outJsonData = outJsonRoot.createElementAsLastChild(MbElement.TYPE_NAME, MbJSON.DATA_ELEMENT_NAME, null);

outJsonData.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "statusCode", (value == "not found")? "404": "200");
outJsonData.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Description", (value == "not found")? "cache value not found": "cache value found");
//MbElement Detal = outJsonData.getLastChild().getFirstChild();
MbElement Details = outJsonData.createElementAsLastChild(MbElement.TYPE_NAME, "Details", null);
Details.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Lookup_Type", Lookup_Type);
Details.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Key", key);
Details.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Value", (value == "not found")? "" : value);
outAssembly = new MbMessageAssembly(inAssembly, outMessage);
// End of user code
// ----------------------------------------------------------

create putCache message flow with following nodes, HTTP Input, Java Compute, and HTTP Reply node.

Put Cache message flow

double click Java Compute node and paste the following code within “Add user code below” section.

   // ----------------------------------------------------------
// Add user code below
MbElement inputLocalEnv = inAssembly.getLocalEnvironment().getRootElement();

Lookup_Type = inputLocalEnv.getFirstElementByPath("/HTTP/Input/QueryString/Lookup_Type").getValueAsString();
key = inputLocalEnv.getFirstElementByPath("/HTTP/Input/QueryString/Key").getValueAsString();
value = inputLocalEnv.getFirstElementByPath("/HTTP/Input/QueryString/Value").getValueAsString();

//Set the key & value is cache
MbGlobalMap globalMap = MbGlobalMap.getGlobalMap(Lookup_Type);

if(globalMap.containsKey(key)) {
globalMap.update(key, value);
}else {
globalMap.put(key, value);
}

MbElement outRoot = outMessage.getRootElement();
MbElement outJsonRoot = outRoot.createElementAsLastChild(MbJSON.PARSER_NAME);
MbElement outJsonData = outJsonRoot.createElementAsLastChild(MbElement.TYPE_NAME, MbJSON.DATA_ELEMENT_NAME, null);

outJsonData.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "statusCode", "200");
outJsonData.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Description", "Data has been added in global cache");

MbElement Details = outJsonData.createElementAsLastChild(MbElement.TYPE_NAME, "Details", null);
Details.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Lookup_Type", Lookup_Type);
Details.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Key", key);
Details.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Value", (value == "not found")? "" : value);

outAssembly = new MbMessageAssembly(inAssembly, outMessage);
// End of user code
// ----------------------------------------------------------

save and deploy the application by drag and drop on integration server.

Deployed Application

Now test the flows using any random lookup_Type and Key. Since the map currently has no data, you will receive a “cache value not found” response.

Cache value not found

Let’s add some data to the map by calling putCache message flow and then call the getCache message flow to retrieve the data from map.

Put cache message flow

Calling the getCache message flow again, this time we receive a “cache value found” response along with the actual data value we were looking for.

Cache value found

Important Notes!!

  • Increase JVM Heap Size: When using the global cache, ensure the JVM heap size is increased for integration servers hosting cache components.
  • Handling Integration Server Restarts: If the integration server hosting the catalog server stops, the cache becomes unavailable. Restarting it will break communication with container servers in other integration servers, leading to data loss. To restore functionality, restart the container integration servers as well.
  • Compatibility with Containerized (CP4i) Environments: The global cache uses WebSphere® eXtreme Scale, which relies on a fixed topology of catalog and container servers. This design is incompatible with dynamic containerized environments like Kubernetes, Docker, or Podman. As a result, IBM App Connect Enterprise does not support the embedded global cache in such environments.

Conclusion

Configuring the embedded global cache in IBM App Connect Enterprise enhances data sharing and integration performance. However, it’s important to consider factors like JVM heap size, the need to restart both catalog and container servers, and the incompatibility with containerized environments. By keeping these in mind, you can effectively manage and utilize the global cache in your integration setups.


https://www.ibm.com/docs/en/app-connect/12.0?topic=overview-embedded-global-cache

https://www.ibm.com/docs/en/app-connect/12.0?topic=cegc-global-cache-sample-configuring-one-catalog-one-container