App Connect

App Connect

Join this online user group to communicate across IBM product users and experts by sharing advice and best practices with peers and staying up to date regarding product enhancements.


#Applicationintegration
#App Connect
#AppConnect
 View Only

Stop Copying Messages into the Environment: Use Context Tree in ACE 13.0.4.0+

By Matthias Blomme posted Fri August 29, 2025 10:31 AM

  

Stop Copying Messages into the Environment: Use Context Tree in ACE 13.0.4.0+

Putting the Message Aside

Imagine this: it’s Friday afternoon, and you need to build a flow that forwards JSON messages to an OAuth-protected REST API. You think, “I’ll need to build the OAuth request message, so let’s just set the input aside into the Environment and pick it up later.” You wire up the flow, test with some dummy data, and everything looks fine. Time for the weekend.

But you missed something.

Flow Setup 1: Using the Environment

Copying an incoming message into the Environment feels like the easiest trick in the book. One line of ESQL—job done. But here’s the catch: it’s not parser-aware. In some cases you get away with it, but when JSON arrays are involved, things get messy fast. Arrays collapse into objects, metadata disappears, and suddenly your “quick fix” becomes a late-night debugging session.

Case in point: our demo flow.

The input message is stored in the Environment, specifically Environment.Variables.InputMessage. The actual message is restored at the end.

If we then compare the input vs the output message:

The token has been added (to the message, for visibility inside the flow exerciser), but you can see that the items array has collapsed into a single field containing the last array element.

Want to know more about those troubling JSON arrays? Have a look at another blog of mine Create JSON Arrays in ESQL and Java.

Copying message data into the Environment is fragile. A solution that works most of the time isn’t really a solution.

Flow Setup 1b: Using a BLOB

Sure, you could play it safe by serializing the whole message to a BLOB, stash it in Environment, and then reparse it when you need it. That works—but it uses a lot of resources. You receive and parse the input message to JSON, reserialize it to BLOB and write it to the Environment, then later read and reparse it from BLOB to send it out again. There are less resource-intensive ways to achieve the same result.

Flow Setup 2: Using the FlowOrder Node

Up until recently, using the FlowOrder node was the only way I knew that gave consistent results. The setup is rather simple if you think about it. Instead of doing everything serially, FlowOrder allows you to define different logical processing branches. Take the flow below as an example.

This flow has two branches: the top handles token requests, the bottom calls the API. Think of them as two separate functions working in sequence, which means they need a way to pass information between them. The cleanest approach is to put the token into the Environment, since it’s just plain values without parser context attached. I have no issue using the Environment,it’s a solid place to keep state, just not for anything that depends on the parser.

The top branch prepares the OAuth request (or it would, if this were not a dummy setup) and stores the received token in the Environment.

The bottom branch starts from the original input message, adds the token to the Authorization header (and to the body for debugging purposes), and sends the message to the API endpoint.

If we then compare the input vs the output message:

You can clearly see the intact input message with the added token.

This setup may look a bit more complex, but that’s only on the canvas. In reality, FlowOrder keeps the logic clean: token handling in one branch, the original message untouched in the other, with a simple Environment hand-off in between.

Flow Setup 3: Using Context Trees

FlowOrder works, but ACE 13.0.4.0 introduced something cleaner: the Context tree. It was originally designed to support discovery connectors, but it also gives you a sharp way to handle message data in classic ACE flows.

Let’s give you some context (pun intended) first. The Context tree is a read-only logical structure that grows as your message passes through the flow. At the start it only knows about the input node, but each node adds its own payload and metadata. By the end you have a complete picture, parser context included. The important bit for us: the original payload is always available.

In practice, you don’t need to configure or enable anything special. As soon as you reference the Context tree in ESQL, ACE populates it at runtime. That means you can simply grab the payload from the input node and copy it back into OutputRoot, then add your token. The flow looks very much like the one we started with:

The difference is in the Compute nodes. The PrepareRequest Node generates the token request—nothing more.

The RestoreMsg Node is the one that calls upon the Context Tree.

Finally, let’s compare the input and the output message:

Proper JSON with the added token.

To show how the Context tree builds up, I added a Trace node. I wired it to the Input and last Compute nodes to capture the tree at different stages.

The Trace node configuration:

Immediately after the HTTP Input node, the Context tree only contains information about the Input node.

Further down the flow, you can see the tree filling up with each node:

The green blocks show the nodes you already passed with their metadata. The blue Payload blocks show the messages the RestRequest node received. The Context tree keeps on building until processing in your flow stops, giving you context about all the nodes that came before.

That’s it. No detours, no reparsing, no lost metadata. It gives you the original payload exactly as it came in, parser context included. Instead of juggling copies and fighting the toolkit, you just point at the Context tree and move on. That is, if you are using ACE 13.0.4.0 or later.

Choosing the Right Approach

Here’s the deal: each option solves the problem, but not all of them age well.

  • Environment copy: quick hack, but parser context gets lost. JSON arrays don’t survive.
  • BLOB copy: technically safe, but you pay for it in extra parsing and CPU cycles.
  • FlowOrder: keeps the input message intact and gives you transactional control. Slightly busier on the canvas.
  • Context tree: the cleanest option if you’re on 13.0.4.0 or later. Parser-aware, lightweight, no juggling, no surprises.

Closing

Copying messages into the Environment is a habit that causes more trouble than it solves. Between arrays breaking and extra reparsing, you end up with fragile flows that are harder to scale. Better options exist, so why not use them?

The FlowOrder approach gives you transactional control without mangling the payload. And if you’re on ACE 13.0.4.0 or newer, the Context tree is the clear winner: parser-aware, lightweight, and even useful outside the shiny discovery connectors it was designed for.

So next time you need to hold onto the original message, don’t dump it into Environment. Use the tools that actually keep your data intact.


For more integration tips and tricks, visit Integration Designers and check out our other blog posts.


References


Written by Matthias Blomme

#IBMChampion

#AppConnectEnterprise(ACE)

#HowTo

2 comments
30 views

Permalink

Comments

11 days ago

Thanks for writing this blog post and it is good to see a detailed example of one of the main uses of context trees in ACE flows outside of designer connector functionality.   It is worth noting that when a message flow deals with subflows then the ESQL Context correlation name is scoped to the nodes within the subflow. This means if the input node is outside of the subflow then trying to access it using the Correlation name will not work. So in the example on this post the path: 

SET OutputRoot.JSON.Data = Context.Nodes."HTTP Input".Payload.Data;

would not reference the "HTTP Input" node outside of a subflow. For this reason ESQL also has a CONTEXTREFERENCE function which can access Context content outside of a current subflow. So changing the ESQL to be:

SET OutputRoot.JSON.Data = CONTEXTREFERENCE("HTTP Input").Payload.Data;

Would access an input node even if called within a subflow.

In ACE 13.0.5.0 (which has just been released) we have extended the CONTEXTREFERENCE function to also take keywords such as:

SET OutputRoot.JSON.Data = CONTEXTREFERENCE("HTTP Input" PAYLOAD).Data;

We have also added the CONTEXTINVOCATIONNODE function that can access the input payload from the input node without needing to know its name. So the following ESQL can now be used:

SET OutputRoot.JSON.Data = CONTEXTINVOCATIONNODE().Payload.Data;

Or 

SET OutputRoot.JSON.Data = CONTEXTINVOCATIONNODE(PAYLOAD).Data;

If the input node itself is inside a subflow and the flow propagates out of that subflow then the input node context tree section will not be visible to the Context correlation name or the CONTEXTREFERENCE function. This is because on exit of a subflow the Tree passed to the subflow output terminal node is now associated with the subflow node that is being propagated out of. So such a flow would have a Context Tree that starts with the subflow node. In this case the new CONTEXTINVOCATIONNODE function can always access the input nodes Context tree section.

In 13.0.5.0 we have made further context tree enhancements which include:

1) A JavaCompute node can now access the read-only Context Tree content.

2) The Flow debugger will now show Context Trees if they are enabled.

3) The Flow Exerciser will also show the Context Tree if they are enabled.

24 days ago

Hi Matthias, Thank you and nice blog write up.  I have definitely used #1 and #2 prior to ACE 13.0.4 and the introduction of context trees.   In my use of #1, I have specifically ran into the JSON issue a few times (although caught it in my unit testing, but can see how that can happen at the worst possible times).   Since then, when I use #1, I do it in a slightly hybrid way by doing something like the following:

CREATE LASTCHILD OF Environment.Variables.InputMessage DOMAIN 'JSON';

CREATE FIELD Environment.Variables.InputMessage.JSON.Data IDENTIFY (JSON.Object)Data

SET Environment.Variables.InputMessage.JSON.Data = InputRoot.JSON.Data;

Thanks again for this and your other blogs (very informative).   I'm looking forward to using the Context Tree more when needed.