How to exploit events based on a classifier attribute

Learn how to exploit events based on a classifier attribute with this concrete tutorial.


Context

 I want to send an email whenever the failureRiskStatus attribute of a Cutoff instance reaches an abnormal state.

Event generation

To access the Events tab, on the main menu, click the cog icon > Data integration. On the left menu, click Events

Click the New Event button, and configure your event to have the following characteristics:

  • Name: cutoffFailureRiskStatus
  • Entity: Cutoff
  • when Event target type drop-down: Attribute
  • Attribute name : failureRiskStatus

 

(info) With this configuration, updates of failureRiskStatus of Payment will be broadcast to routes that listen to tnd-event:failureRiskStatus, and are registered on the same space.

Create query

In data integration menu, open the Queries tab.

(info) The queries must be in the same space as the event you've just created.

Cutoff details

Create a new query:

  • NamegetCutoffDetails
  • Add a Cutoff_instanceParameter parameter on the Cutoff entity. 
  • Dimensions: Cutoff
  • Edit the Cutoff dimension to filter this dimension by the Cutoff_instanceParameter parameter.
  • Inputs: nameprocessingDeadline, durationToDeadline

Save this new query:

Enable use of Camel MAIL component

See Library in Camel MAIL component documentation

Enable result formatting

To format the result of the query in a mail we will use the templating engine called stringtemplate. The template will be saved as a new Ressource.

You need to create a new Resource that will build the mail message from the result:

  • Name : mail_content
    Type : Text
    Charset : UTF-8
    Content : 

    <style>
        td{padding-left:20px;}
        th{padding-left:1px; padding-right:1px;}
    </style>
    A cutoff failure risk status has become abnormal:
    <br/>
    <br/>
    <table>
        <tr>
            <th align="left">Cutoff name</th> 
            <td>$headers.cutoffName$</td>
        </tr>
        <tr>
            <th align="left">Failure risk status</th> 
            <td>$headers.cutoffFailureRiskStatusLabel$</td>
        </tr>
        <tr>
            <th align="left">Processing deadline</th> 
            <td>$headers.cutoffProcessingDeadline$</td>
        </tr>
        <tr>
            <th align="left">Duration to deadline</th>
            <td>$headers.cutoffDurationToDeadline$</td>
        </tr>
        <tr>
            <th align="left">Transition time</th>
            <td>$headers.queryTimeDisplay$</td>
        </tr>
    </table>
    
    

Route configuration

The route we will be using to send the email will contain a number of properties to define the receiver, the sender, the server url and the password of the email account.

Create route properties

Go to the Properties tab and define the following properties

  • emailReceiver: the email of the person who will receive the email
  • mailServerHost: the host name of the mail server
  • emailSender: the login used to send the mail.
  • emailPassword: the password of the account used to send the mail.

How to determine the classifier rank

Step 1: determine what kind of classifier the attribute is based on

Go to the attribute list, find your attribute and read the type. In this example, the classifier that is used is the Risk classifier:

Step 2: find the corresponding ranks

Using the classifier editor

On the main menu, click the cog icon > Model & configuration. On the left menu, click Classifiers, then in the Classifiers area select Risk. The classifier instance that has the lowest risk rank (i.e. 0) is the uppermost one in the list:

Using the 2 methods describes above, you can see that for the Risk classifier the corresponding ranks are:

  • NORMAL: rank = 0
  • WARNING: rank = 1
  • CRITICAL: rank = 2

Create the route

In the data integration menu, open the Routes tab and create a new route:

  • name : sendCutoffDetails
  • definition : 

    <?xml version="1.0" encoding="UTF-8"?>
    <routes xmlns="http://camel.apache.org/schema/spring" xmlns:u="http://www.systar.com/aluminium/camel-util">
        <route>
            <!-- This route receives a new message each time the failureRiskStatus of a cutoff is updated -->
            <from uri="tnd-event:cutoffFailureRiskStatus"/>
            <!-- We store the instanceId of the cutoff in a header to be used later on -->
            <setHeader headerName="cutoffInstanceId">
                <simple>body.instanceId</simple>
            </setHeader>
            <!-- We extract the changes made to failureRiskStatus of Cutoff -->
            <setBody>
                <u:extract-vtAxisTransitions ignoreSuccessiveIdentical="true"/>
            </setBody>
            <split>
                <simple>${body}</simple>
                <!-- For each change, we execute a sub-routine -->
                <to uri="direct:line"/>
            </split>
        </route>
        <route>
            <from uri="direct:line"/>
            <log loggingLevel="INFO" message="New transition: ${body}"/>
            <choice>
                <when>
                    <simple>${body.newValueByIndicatorDataName[Value]} != null</simple>
                    <choice>
                        <when>
                            <!-- The NORMAL status rank is 0. We only want to be warned about the cutoff that have a status greater than NORMAL -->
                            <simple>${body.newValueByIndicatorDataName[Rank]} > 0</simple>
                            <log loggingLevel="INFO" message="A cutoff with a status greater than NORMAL has been identified."/>
                            <setHeader headerName="cutoffFailureRiskStatusLabel">
                                <simple>${body.newValueByIndicatorDataName[Label]}</simple>
                            </setHeader>
                            <setHeader headerName="queryTime">
                                <simple>${body.vt}</simple>
                            </setHeader>
                            <setHeader headerName="queryTimeDisplay">
                                <u:date-format pattern="yyyy-MM-dd 'at' HH:mm:ss Z">
                                    <!-- Expression to use in order to retrieve the date -->
                                    <simple>${body.vt}</simple>
                                </u:date-format>
                            </setHeader>
    						<!-- Retrieve relevant information about the cutoff -->
                            <!-- Build the parameter map for the query -->
                            <setProperty propertyName="tnd-query.parameters">
                                <u:map-create>
                                    <u:map-entry key="ReferenceTime">
                                        <simple resultType="org.joda.time.ReadableInstant">header.queryTime</simple>
                                    </u:map-entry>
                                    <u:map-entry key="Cutoff_instanceParameter">
                                        <header>cutoffInstanceId</header>
                                        <!-- filter by instance id -->
                                    </u:map-entry>
                                </u:map-create>
                            </setProperty>
                            <to uri="tnd-query:getCutoffDetails"/>
                            <!-- Since query is filtered, there is only one line -->
                            <setBody>
                                <simple>${body.rows[0]}</simple>
                            </setBody>
                            <!-- Store data in header for later usage -->
                            <setHeader headerName="cutoffName">
                                <simple>${body[name].value}</simple>
                            </setHeader>
                            <setHeader headerName="cutoffProcessingDeadline">
                                <u:date-format pattern="yyyy-MM-dd 'at' HH:mm:ss Z">
                                    <!-- Expression to use in order to retrieve the date -->
                                    <simple>${body[processingDeadline].value}</simple>
                                </u:date-format>
                            </setHeader>
                            <setHeader headerName="cutoffDurationToDeadline">
    							<u:number-format pattern="# s">
    								<u:number-parse pattern="PT#S">
    									<simple>${body[durationToDeadline].value}</simple>
    								</u:number-parse>
    							</u:number-format>
                            </setHeader>
    						<to uri="string-template:tnd-resource:mail_content?delimiterStart=$&amp;delimiterStop=$"/>
    						<setHeader headerName="subject">
    							<constant>Cutoff details</constant>
    						</setHeader>
    						<setHeader headerName="to">
    							<constant>{{emailReceiver}}</constant>
    						</setHeader>
    						<!--Send the email -->
    						<to uri="smtps://{{mailServerHost}}?contentType=text/html&amp;username={{emailSender}}&amp;password={{emailPassword}}"/>
                        </when>
                    </choice>
                </when>
            </choice>
        </route>
    </routes>
    
    

Save and then launch the route. Each time the failureRiskStatus of a Cutoff reaches an abnormal state: 

To see this example in action, you can use this application containing the example.

Related Links