Quotes

Thursday, July 20, 2017

ESQL code to create mail with attachments using broker events


In this post I will provide an example on how to process events generated by a flow using the default IBM Integration Bus monitoring event capability.

The example will show how

  • to serialize a tree into BLOB using ESQL
  • how to send a mail with attachment
  • How to create/prepare the LocalEnvironment and Root for the EmailOutput node
  • The usage of the business event capabilities provided by IIB


The principle is simple:

  1. Configure a flow to generate an IIB event
  2. Create a subscription to this event with a WMQ Queue as endpoint
  3. Create a flow that consumes these events and send an email with attachments

The example in this post shows how to create mail with attachments using ESQL but this could be easily made using Java as well.

Configure a flow to generate an IIB event


The event generated as a well defined structure and the schema can be imported into a library using new model -> IBM predefined model.

Any nodes in a flow can be configured to generate events (Generating events in WebSphere Message Broker) that may contain context information and payload.

It is for example possible to configure a node to include the localEnvironment, ExceptionList and Message tree structure (under Root). These information will be placed into the IIB events under the folder "complexContent".
Note that the LocalEnvironment is reset when an exception occurs, so the data that would have been stored in this tree would be wiped when the message is propagated to the catch terminal of the input node (will be covered in a future post).

Finally it is also possible to include the full payload (as it was received) by selecting in the monitoring node properties "include payload as bitstream". The payload will then be included into the IIB events under "BistreamData".

Create a subscription

The IIB runtime is publishing the IIB events on the WMQ topic "$SYS/Broker/IBMIBus/Monitoring/#".
Using the WMQ Explorer you create a subscription to these events and select a destination queue:

 The flow that sends email

The flow is very simple: MQInput -> ComputeNode -> EmailOutput node
The compute node is used to create and configure the message that will be send using the emailoutput node. 
The node it self is configured the minimum properties: server:port, email to, from and security.
The rest will be provided by the code in ESQL (subject, body content and attachments).

In this example the complexContent included in the incoming business event is serialized into bitstream and will be send by mail as attachment.
The payload if present is also send as attachment.
The body of the mail is made of event origin data and using a DFDL to have a text document separated with CRLF.

The code is provided here after:

CALL CopyMessageHeaders();
-- CALL CopyEntireMessage();
/*
emailoutput node requires the following (with attachments):
- LocalEnvironment->Destination->Email->Attachment
-- Attachment -> Content (BLOB)/ContentType (CHAR)/ContentName(CHAR)/ContentEncoding (CHAR)
- Root -> EmailOutput -> Subject (if you would like to be overriden at runtime
- Root -> BLOB (this is the actual body of the mail
*/
-- Create the LocalEnvironment folders
DECLARE ptrMail REFERENCE TO OutputLocalEnvironment;
CREATE LASTCHILD OF ptrMail AS ptrMail TYPE Name NAME 'Destination';
CREATE LASTCHILD OF ptrMail AS ptrMail TYPE Name NAME 'Email';
DECLARE ptrAttachment REFERENCE TO ptrMail;
-- Get the information from the broker events
DECLARE ptrEvents REFERENCE TO InputRoot.XMLNSC.ns:event.ns:applicationData.ns:complexContent;
WHILE LASTMOVE(ptrEvents) DO
CREATE LASTCHILD OF ptrMail AS ptrAttachment TYPE Name NAME 'Attachment';
SET OutputRoot.XMLNSC.Data = ptrEvents;
-- Content has to be BLOB to be taken as an attachment.
-- Serialize the broker event payload available as complexContent
SET ptrAttachment.Content = ASBITSTREAM(OutputRoot.XMLNSC.Data OPTIONS FolderBitStream);
SET ptrAttachment.ContentType = 'text/xml';
-- Specify the attanchment name
SET ptrAttachment.ContentName = ptrEvents.ns:elementName;
-- Set as binary
SET ptrAttachment.ContentEncoding = 'binary';
DELETE FIELD OutputRoot.XMLNSC;
-- move to the next complexContent
MOVE ptrEvents NEXTSIBLING REPEAT NAME;
END WHILE;
MOVE ptrEvents TO InputRoot.XMLNSC.ns:event.ns:bitstreamData.ns:bitstream;
IF LASTMOVE(ptrEvents) THEN
-- If there is the bitstream available, send it over as attachment
CREATE LASTCHILD OF ptrMail AS ptrAttachment TYPE Name NAME 'Attachment';
--bitstream is base64 encoded, so first we need to decode it
-- ** the node allows to encode the data in Base64, it doesn't allows to provide a already base64 data though
SET ptrAttachment.Content =
BASE64DECODE(InputRoot.XMLNSC.ns:event.ns:bitstreamData.ns:bitstream);
SET ptrAttachment.ContentType = 'text/plain';
SET ptrAttachment.ContentName = 'payload';
-- ask the node to convert it into Base64
SET ptrAttachment.ContentEncoding = 'Base64';
END IF;
-- Set the subject
SET OutputRoot.EmailOutputHeader.Subject = 'Mail Service info';
-- In order to have a pretty message layout, a DFDL is used with CRLF terminator.
SET OutputRoot.Properties.MessageFormat = 'DFDL';
SET OutputRoot.Properties.MessageType = '{}:mailMessage';
SET OutputRoot.DFDL.mailMessage.Header.MessageType = 'INFO';
MOVE ptrEvents TO InputRoot.XMLNSC.ns:event.ns:eventPointData.ns:messageFlowData;
SET OutputRoot.DFDL.mailMessage.Header.Origin = ptrEvents.ns:node.ns:nodeLabel || ptrEvents.ns:node.ns:terminal;
SET OutputRoot.DFDL.mailMessage.Header.Server = ptrEvents.ns:messageFlow.ns:uniqueFlowName;
SET OutputRoot.DFDL.mailMessage.Header.MessageId = InputRoot.XMLNSC.ns:event.ns:eventPointData.ns:eventData.ns:eventCorrelation.ns:localTransactionId;
SET OutputRoot.DFDL.mailMessage.Messages.Message = 'simple content';
-- Serialize the DFDL into BLOB for the OutputMail node.
-- This will be the mail body.
SET OutputRoot.BLOB.BLOB = ASBITSTREAM(OutputRoot.DFDL.mailMessage OPTIONS RootBitStream);
DELETE FIELD OutputRoot.DFDL;
RETURN TRUE;

No comments:

Post a Comment