Archives

Configure the message flow nodes that are converted from the IBM App Connect Professional Archive and Unarchive activities.

About this task

You converted your orchestration into a message flow. See Table 1, for information on which nodes are used for each of the activities.

Steps are split into sections and are intentionally brief to get you started quickly on configuring the nodes in your message flow. See linked topics in the table for more comprehensive information on configuring the nodes.

Table 1. IBM App Connect Professional Archives activities and the corresponding IBM App Connect Enterprise message flow nodes
IBM App Connect Professional activity IBM App Connect Enterprise node
Archive activity

JavaCompute node

Unarchive activity

JavaCompute node

JavaCompute node for Archive and Unarchive activities

About this task

Use the JavaCompute node to compress and decompress message data using different formats, for example ZIP and GZIP.

Procedure

JavaCompute node functionality for Archive and Unarchive activities:

  • Compresses/decompresses the message content by using specified archive formats such as ZIP or GZIP.
  • Supports handling of multiple files in formats: ZIP or a single file in GZIP.
  • Extracts the content and adds it to the message tree for further processing.
Supported archive formats:
  • ZIP: Supports file names with directory structures.
  • GZIP: Handles single files.
  • TAR or TAR+GZIP: Requires third-party libraries like Apache Commons Compress.
Input:
  • fileName and fileContent - can be hardcoded or dynamically retrieved from the environment, XML, or JSON.
Output:
  • Archive - The compressed archive is Base64-encoded and added to the message tree before propagation.
  • Unarchive - The decompressed content is added to the message tree for propagation.

  1. Implement the Archive logic by following this example:
    Example: Archive in JavaCompute Node
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.util.Base64;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipOutputStream;
    import java.util.zip.GZIPOutputStream;
    
    import com.ibm.broker.javacompute.MbJavaComputeNode;
    import com.ibm.broker.plugin.MbElement;
    import com.ibm.broker.plugin.MbException;
    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 Archive_JavaCompute extends MbJavaComputeNode {
    
        public void evaluate(MbMessageAssembly inAssembly) throws MbException {
            // Get the output terminal
            MbOutputTerminal out = getOutputTerminal("out");
    
            // Create the output message assembly by copying the input message
            MbMessage inMessage = inAssembly.getMessage();
    
            //If want to Retrieve from the Environment
            //MbElement envRoot = inAssembly.getGlobalEnvironment().getRootElement();
    
            //If want to Retrieve from the xml
    	    //MbElement inRoot = inMessage.getRootElement();        
    
            //If want to Retrieve from the json
            //MbElement jsonDataElement = inMessage.getRootElement().getFirstElementByPath("JSON/Data");
    
            MbMessageAssembly outAssembly = new MbMessageAssembly(inAssembly, new MbMessage(inMessage));
    
            // Inputs for the compression logic
            String fileName = "folder/file.txt";           // File name (can include directory structure)
    
           //If want to Retrieve from the Environment
           // String fileName = envRoot.getFirstElementByPath("Variables/FileName").getValueAsString();
    
           //If want to Retrieve from the xml
           // String fileName = inRoot.getFirstElementByPath("XMLNSC/Root/FileName").getValueAsString();
    
          //If want to Retrieve from the json
          // byte[] fileContent = jsonDataElement.getFirstElementByPath("FileName").getValueAsString(); 
            String archiveType = "zip";                    // Archive type (e.g., zip, gzip)
            byte[] fileContent = "abcdef".getBytes();       // File content as byte array
    
           //If want to Retrieve from the Environment
           // byte[] fileName = envRoot.getFirstElementByPath("Variables/Content").getValueAsString().getBytes();
    
           //If want to Retrieve from the xml
           // byte[] fileContent = inRoot.getFirstElementByPath("XMLNSC/Root/Content").getValueAsString().getBytes();
    
          //If want to Retrieve from the json
          // byte[] fileContent = jsonDataElement.getFirstElementByPath("content").getValueAsString();.getBytes(); 
            byte[] archiveOutput;
            try 
                // Archive based on the specified type
                switch (archiveType.toLowerCase()) {
                    case "gzip":
                        archiveOutput = gzipArchive(fileContent);
                        break;
                    case "zip":
                        archiveOutput = zipArchive(fileName, fileContent);
                        break;
                    default:
                        throw new MbUserException(this.getClass().getName(), "evaluate", "Unsupported archive type", archiveType, "Supported types: gzip, zip", null);
                }
            } catch (IOException e) {
                throw new MbUserException(this.getClass().getName(), "evaluate", "Archiving failed", e.getMessage(), "", null);
            }
    
            // Encode the compressed output as a Base64 string
            String base64EncodedOutput = Base64.getEncoder().encodeToString(archiveOutput);
    
            // Add the Base64-encoded archive output to the message tree
            MbElement outRoot = outAssembly.getMessage().getRootElement();
            MbElement outputStream = outRoot.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "OutputParameterStream", null);
            outputStream.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "Archive", base64EncodedOutput);
    
            // Propagate the message to the next node in the flo
            out.propagate(outAssembly);
        }
        private byte[] gzipArchive(byte[] content) throws IOException {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            try (GZIPOutputStream gos = new GZIPOutputStream(baos)) {
                gos.write(content);
            }
            return baos.toByteArray();
        }
    
        private byte[] zipArchive(String fileName, byte[] content) throws IOException {
            // Initialize a byte array output stream to hold the ZIP data
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            try (ZipOutputStream zos = new ZipOutputStream(baos)) {
                // Check if the file name indicates a directory
                boolean isDirectory = fileName.endsWith("/");
    
                // Create a new ZIP entry with the provided file name
                ZipEntry entry = new ZipEntry(fileName);
                zos.putNextEntry(entry);
    
                // Write content only if it's not a directory
                if (!isDirectory) {
                    zos.write(contnt);
                }
    
                // Close the current ZIP entry
                zos.closeEntry();
            }
            // Return the compressed data as a byte array
            return baos.toByteArray();
        }
    }
  2. Implement the Unarchive logic by following this example:
    Example Implementation: Unarchive in JavaCompute Node
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.util.Base64;
    import java.util.zip.GZIPInputStream;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipInputStream;
    import com.ibm.broker.javacompute.MbJavaComputeNode;
    
    import com.ibm.broker.plugin.MbElement;
    import com.ibm.broker.plugin.MbException;
    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 Unarchive_JavaCompute extends MbJavaComputeNode {
    
        public void evaluate(MbMessageAssembly inAssembly) throws MbException {
            MbOutputTerminal out = getOutputTerminal("out");
            MbMessage inMessage = inAssembly.getMessage();
            MbMessageAssembly outAssembly = new MbMessageAssembly(inAssembly, new MbMessage(inMessage));
    
            try {
                // Retrieve the Base64-encoded archive content
                MbElement inputRoot = inMessage.getRootElement();
                String base64EncodedArchive = inputRoot.getFirstElementByPath("InputParameterStream/Archive").getValueAsString();
                byte[] archiveContent = Base64.getDecoder().decode(base64EncodedArchive);
    
                // Retrieve the archive type
                String archiveType = inputRoot.getFirstElementByPath("InputParameterStream/ArchiveType").getValueAsString();
    
                // Unarchive the content
                String extractedContent = unarchiveContent(archiveContent, archiveType);
    
                // Set the extracted content in the output message
                MbElement outRoot = outAssembly.getMessage().getRootElement();
                MbElement outputStream = outRoot.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "OutputParameterStream", null);
                outputStream.createElementAsLastChild(MbElement.TYPE_NAME_VALUE, "UnarchivedContent", extractedContent);
                out.propagate(outAssembly);
    
            } catch (Exception e) {
                throw new MbUserException(this.getClass().getName(), "evaluate", "Unarchiving failed", e.getMessage(), "", null);
            }
    
        }
    
        private String unarchiveContent(byte[] archiveContent, String archiveType) throws IOException, MbUserException {
            switch (archiveType.toLowerCase()) {
                case "gzip":
                    return new String(unarchiveGZIP(archiveContent));
                case "zip":
                    return unarchiveZIP(archiveContent);
                default:
                    throw new MbUserException(this.getClass().getName(), "unarchiveContent", "Unsupported archive type", archiveType, "Supported types: gzip, zip", null);
            }
        }
    
        private byte[] unarchiveGZIP(byte[] gzipContent) throws IOException {
            ByteArrayInputStream bais = new ByteArrayInputStream(gzipContent);
    
            try (GZIPInputStream gis = new GZIPInputStream(bais)) {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len;
                while ((len = gis.read(buffer)) > 0) {
                    baos.write(buffer, 0, len);
                }
                return baos.toByteArray();
            }
        }
    
        private String unarchiveZIP(byte[] zipContent) throws IOException {
            ByteArrayInputStream bais = new ByteArrayInputStream(zipContent);
            StringBuilder extractedContent = new StringBuilder();
            try (ZipInputStream zis = new ZipInputStream(bais)) {
                ZipEntry entry;
                while ((entry = zis.getNextEntry()) != null) {
                    if (!entry.isDirectory()) {
                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = zis.read(buffer)) > 0) {
                            baos.write(buffer, 0, len);
                        }
                        extractedContent.append("File: ").append(entry.getName()).append("\n");
                        extractedContent.append("Content: ").append(new String(baos.toByteArray())).append("\n");
                    }
                }
            }
            return extractedContent.toString();
        }
    }