App Connect

Retrieving project files in message flows in IBM Integration Bus (IIB) and App Connect 

26 days ago

This recipe explains how to read IBM Integration Bus / IBM App Connect BAR files and store them in message flow variables.

Sometimes it may be necessary to package a static file, for example a service description YAML file, and make it accessible to service clients. This recipe explains how it is possible to do that in IBM Integration Bus.

Overview

Skill Level: Intermediate

Requires experience with IBM Integration Bus / IBM App Connect and Java.

Ingredients

This recipe was tested with IBM Integration Bus 10.0.0.7 on Windows Server R2 Standard. It should also work with IBM App Connect and Linux.

Step-by-step

  1. Create a sandbox project

    Create a similar project structure:

    project_structure

    The pets.yaml is defined here: https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v2.0/yaml/petstore.yaml

    The fileResponse message flow is defined as follows:

    message_flow
  2. Define ESQL and Java code

    This step defines the relevant code. Note that the whitespace may be collapsed, depending on the current Recipes framework version.

    setInputVariables.esql

    BROKER SCHEMA SandboxWorkspaceFileResponseSchema


    CREATE COMPUTE MODULE setInputVariables
    CREATE FUNCTION Main() RETURNS BOOLEAN
    BEGIN
    SET OutputLocalEnvironment = InputLocalEnvironment;

    SET OutputLocalEnvironment.SBER.ReadFile.fileName = 'pets.yaml';
    SET OutputLocalEnvironment.SBER.ReadFile.schemaName = 'SandboxWorkspaceFileResponseSchema';
    SET OutputLocalEnvironment.SBER.ReadFile.resourceTypeFolder = 'YAML';
    RETURN TRUE;
    END;
    END MODULE;

    The resourceTypeFolder variable value depends on how Integration Bus / App Connect interprests the file. There are many possible values; to find which one, simply deploy the project and then search the file name on disk. For example, on Windows, pets.yaml can be found here:

    C:\ProgramData\IBM\MQSI\components\<broker>\<euuid>\config\<auuid>\YAML\SandboxWorkspaceFileResponseSchema\pets.yaml

    The entire path is constructed below in the ReadFile.java.

    ReadFile.java:

    package SandboxWorkspaceFileResponseSchema;

    import java.io.BufferedReader;
    import java.io.File;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.util.List;

    import com.ibm.broker.config.proxy.ApplicationProxy;
    import com.ibm.broker.config.proxy.BrokerProxy;
    import com.ibm.broker.config.proxy.ExecutionGroupProxy;
    import com.ibm.broker.javacompute.MbJavaComputeNode;
    import com.ibm.broker.plugin.MbElement;
    import com.ibm.broker.plugin.MbException;
    import com.ibm.broker.plugin.MbExecutionGroup;
    import com.ibm.broker.plugin.MbMessage;
    import com.ibm.broker.plugin.MbMessageAssembly;
    import com.ibm.broker.plugin.MbOutputTerminal;
    import com.ibm.broker.plugin.MbUserException;

    public class ReadFile extends MbJavaComputeNode {

    @SuppressWarnings("unchecked")
    public void evaluate(MbMessageAssembly inAssembly) throws MbException {
    MbOutputTerminal out = getOutputTerminal("out");

    MbMessage env = inAssembly.getLocalEnvironment();
    MbMessage inMessage = inAssembly.getMessage();

    MbMessageAssembly outAssembly = null;

    try {
    // create new message as a copy of the input
    MbMessage outMessage = new MbMessage(inMessage);
    MbMessage newEnv = new MbMessage(env);
    outAssembly = new MbMessageAssembly(inAssembly, newEnv,
    inAssembly.getExceptionList(), outMessage);
    // ----------------------------------------------------------
    // Add user code below

    BrokerProxy bp = null;
    BufferedReader br = null;

    String serverName = MbExecutionGroup.getExecutionGroup().getName();
    String applicationName = getMessageFlow().getApplicationName();
    String fileName = ((List<MbElement>) env.getRootElement()
    .evaluateXPath("SBER/ReadFile/fileName")).get(0)
    .getValueAsString();
    String resourceTypeFolder = ((List<MbElement>) env.getRootElement()
    .evaluateXPath("SBER/ReadFile/resourceTypeFolder")).get(0)
    .getValueAsString();
    String schemaName = ((List<MbElement>) env.getRootElement()
    .evaluateXPath("SBER/ReadFile/schemaName")).get(0)
    .getValueAsString();

    try {
    bp = BrokerProxy.getLocalInstance();
    ExecutionGroupProxy egp = bp
    .getExecutionGroupByName(serverName);
    ApplicationProxy ap = egp.getApplicationByName(applicationName);
    String n = bp.getName();
    String euuid = egp.getUUID();
    String auuid = ap.getUUID();
    String base = System.getenv("MQSI_WORKPATH");
    String s = File.separator;
    String filePath = base + s + "components" + s + n + s + euuid
    + s + "config" + s + auuid + s + resourceTypeFolder + s
    + schemaName + s + fileName;

    byte[] fileContents = Files.readAllBytes(Paths.get(filePath));

    ((List<MbElement>) newEnv.getRootElement()
    .evaluateXPath("SBER/ReadFile")).get(0).createElementAsLastChild(MbElement.TYPE_NAME_VALUE, fileName, fileContents);

    } finally {
    if (br != null)
    br.close();
    if (bp != null)
    bp.disconnect();
    }

    // End of user code
    // ----------------------------------------------------------
    } catch (MbException e) {
    // Re-throw to allow Broker handling of MbException
    throw e;
    } catch (RuntimeException e) {
    // Re-throw to allow Broker handling of RuntimeException
    throw e;
    } catch (Exception e) {
    // Consider replacing Exception with type(s) thrown by user code
    // Example handling ensures all exceptions are re-thrown to be
    // handled in the flow
    throw new MbUserException(this, "evaluate()", "", "", e.toString(),
    null);
    }
    // The following should only be changed
    // if not propagating message to the 'out' terminal
    out.propagate(outAssembly);

    }

    }

     

    setFileResponse.esql:

    BROKER SCHEMA SandboxWorkspaceFileResponseSchema

    CREATE COMPUTE MODULE setFileResponse
    CREATE FUNCTION Main() RETURNS BOOLEAN
    BEGIN
    SET OutputRoot = InputRoot;
    SET OutputLocalEnvironment = InputLocalEnvironment;

    SET OutputRoot.BLOB.BLOB = OutputLocalEnvironment.SBER.ReadFile.{OutputLocalEnvironment.SBER.ReadFile.fileName};
    DELETE FIELD OutputLocalEnvironment.SBER.ReadFile.{OutputLocalEnvironment.SBER.ReadFile.fileName};
    SET OutputRoot.Properties.ContentType = 'text/yaml'; -- Set to application/x-yaml and browsers will download the response as a file

    RETURN TRUE;
    END;
    END MODULE;

     

  3. Deploy and test

    Simply deploy the project to a server, open a browser or SoapUI and invoke the following URL: http://<host>:<port>/SandboxWorkspaceFileResponse

    The browser should return the file specified in the flow variables. Note that while it may be possible to serve files specified by a request parameter, constraints should be placed on possible file names, for security. The described pattern is applicable to small files which won’t cause out of memory problems due to large object allocation failures. Small file responses can also be cached.

  4. Conclusion

    Thanks to Matthew SeGall from IBM Integration Bus / IBM App Connect support team for explaining how to construct the file path of a deployed BAR file.