IBM Integration Bus, Version 9.0.0.5 Operating Systems: AIX, HP-Itanium, Linux, Solaris, Windows, z/OS

See information about the latest product version

Environment and Local Environment considerations

Individual sections of this Good operating practice have some information about the Environment and Local Environment, however the following recommendations do not fit neatly into those sections.

Do not use the Environment tree to handle local variables

For most circumstances, using local variables with the node is the optimal solution. This section covers the use of Local Environment to store the variables when more than a flat structure is required.

All data that is stored in the Environment tree is stored in memory during the whole message flow, and is not freed after it is out of scope. Even if you delete the fields from the Environment tree, the memory is not freed until the message flow finishes processing the message. The broker uses pool allocation and reuses resources of the Environment Tree. Therefore, if you need space to store local data for node work, then use the LocalEnvironment tree and avoid high memory consumption.

If you create local environment variables, store them in a subtree called Variables. This action provides a work area that you can use to pass information between nodes. This subtree is never inspected or modified by any supplied node.

Variables in the local environment can be changed by any subsequent message processing node, and the variables persist until the node that created them goes out of scope.

Generally, use the Environment for scratchpad work where you need to maintain the content beyond the scope of the current node, and use the LocalEnvironment for larger scratchpad areas that are only required during the current node, and you need to release the memory after use.

The scope of Environment and Local Environment

The following flow diagram demonstrates the use of Environment and Local Environment:

Figure 1. Diagram of a message flow that uses the local environment.

The following table details the contents of the Environment and Local Environment as a message traverses through the flow:

Table 1.
Stage Environment Local Environment
A Empty Empty
B myVar1 = ‘abc’ myVar1 = ‘abc’
C myVar1 = ‘123’ myVar1 = ‘123’

myVar2 = ‘123’

D myVar1 = ‘123’ myVar1 = ‘abc’
E myVar1 = ‘XYZ’ myVar1 = ‘abc’

Environment variables maintain state throughout the flow, and the memory is not released regardless of whether the elements are removed from the environment.

Local Environment variables maintain state only while the flow progresses (along a single propagated path). The Local Environment variables are available to all nodes on the same propagated path, but changes are only passed out of a Computenode if the ComputeMode property includes Local Environment. If the ComputeMode is set to Message, the LocalEnvironment is passed through the node as-is. The Local Environment can still be used within a Computenode (read or written to) when the ComputeMode does not include Local Environment but the scope of these additions and modifications survives this node.

Environment with Domain

Copying a message tree (or a portion of it) into the Environment can be useful for many scenarios, but it is essential that the correct domain is created prior to copying the structure. Forgetting to assign the correct domain to the Environment tree before copying the fragment of the input message causes inflation of the tree to occur before the copy happens. For more information, see Types of parser copy.

Sample with PARSE included:
CREATE LASTCHILD OF Environment DOMAIN 'XMLNSC' PARSE(InputRoot.BLOB.BLOB);
Sample without PARSE included:
CREATE LASTCHILD OF Environment DOMAIN 'XMLNSC';

When the source and target trees have the same domain, it is just a bitstream copy.

Using CREATE with PARSE in the Environment tree

When the subject of a parser is discussed in terms of the broker, then it is seen as a single entity such as the XMLNSC parser. However, this situation is not the case, and many instances of a parser can be created based on the logic implemented in a message flow. A parser is responsible for creating a message tree from a bitstream and vice versa.

Since the introduction of the CREATE with PARSE ESQL statement, the term message tree could apply to a portion of a message tree. In the following example, an XMLNSC parser is created in the CREATE statement, and another is created in OutputRoot message:
CREATE FIELD Environment.Variables;
DECLARE envRef REFERENCE TO Environment.Variables;
DECLARE count INT 0;
WHILE count < 50000 DO
    SET count = count + 1;
    CREATE LASTCHILD OF envRef DOMAIN('XMLNSC')  
    PARSE(InputRoot.DFDL.record[count], .....);
    CALL CopyMessageHeaders();
    SET OutputRoot.XMLNSC = Environment.Variables.XMLNSC[count];
    PROPAGATE;
END WHILE;

This example assumes that the input DFDL tree has 5000 repeating records that contain XML blobs. The XMLNSC parser created in the Environment tree is owned by the Environment tree's message group. Hence all parsers created in the Environment tree are owned by the Input message group, and are not cleared and reused until processing returns to the input node. However the XMLNSC parser created in the OutputRoot message tree, is owned by a sub message group. This parser is cleared, reset, and all parsers are freed for reuse at the end of the PROPAGATE. For more information, see The Splitter pattern.

This ESQL leads to 5001 XML parsers being created. Once created, they exist for the life of the integration server, and are reused throughout. Even modifying the ESQL to the following example makes no difference:
CREATE FIELD Environment.Variables;
DECLARE envRef REFERENCE TO Environment.Variables;
DECLARE count INT 0;
WHILE count < 50000 DO
    SET count = count + 1;
    CREATE LASTCHILD OF envRef DOMAIN('XMLNSC')
    PARSE(InputRoot.DFDL.record[count], .....);
    CALL CopyMessageHeaders();
    SET OutputRoot.XMLNSC = Environment.Variables.XMLNSC[count];
    DELETE FIELD  Environment.Variables.XML[count];
    PROPAGATE;
END WHILE;
The DELETE FIELD statement just deletes all the message tree fields for reuse, but the parsers syntax element pool owns them and gets them ready for reuse. Therefore, the parser must still exist to do this. A parser can be reset and reused when the message tree it is associated with goes out of scope. So when the CREATE with PARSE is used in the OutputLocalEnvironment, this message tree goes out of scope when:
  • Either when returning from a PROPAGTAE statement, or
  • When the Computenode completes and the processing returns to a previous point in the message flow.

Any parsers that are associated with the Environment tree are not be freed and reused until the message flow completes for that message. However if many parsers are created in the Environment tree for one message, then this behaviour might lead to storage exhaustion before the flow completes.

If such conditions are found to be present in a message flow, then the use of OutputLocalEnvironment should be considered along with the PROPAGATE statement.

Tip: Use Environment when the parsed results are required throughout all paths in the flow or need to survive a rollback. But keep in mind the performance implications with loops as described above. Otherwise consider the use of a Local Environment variable where scope can be managed to within a Propagate path.

bj60052_.htm | 
        
        Last updated:
        
        Last updated: 2016-08-12 11:20:23