Skip to main content
Version: Current

Server Developer Training - Day two

This day covers:

Notify

The Genesis platform includes a notification module called GENESIS_NOTIFY by default. The package for this is genesis-notify. It does not run automatically.

As you have already cloned the Server Developer Training starting repository from here, you have everything you need to run it.

The manual steps to use the genesis-notify package are not difficult:

  1. Add a reference to your server/jvm/alpha-dictionary-cache build.gradle.kts file, such as this.

  2. Add a reference to your server/jvm/alpha-deploy build.gradle.kts file, like this.

  3. Finally, include a variable indicating the genesis-notify version, as demonstrated here.

Now you need to reload the gradle project, and run build and deploy tasks to verify that the new process works as expected.

If everything works, you will see a new process called GENESIS_NOTIFY in the mon tab.

tip

if you build using the genesisInstall command with the --compactProcesses option, the GENESIS_NOTIFY process will be running under GENESIS_COMPACT_PROCESS.

Set up GENESIS_NOTIFY

First, we need to create the gateway. To do that, create a new file called genesis-notify.kts under your server/jvm/alpha-site-specific/src/main/resources/scripts/ and add the following information, including the details of the the SMTP server you are using.

notify {
gateways {
email(id = "email") {
smtpHost =
smtpPort =
smtpUser =
smtpPw =
smtpProtocol =
systemDefaultUserName =
systemDefaultEmail =
}
}
}

Insert NOTIFY_ROUTE

Create a file NOTIFY_ROUTE.csv as shown below, then insert it in the table NOTIFY_ROUTE using the command SendIt.

NOTIFY_ROUTE_ID,TOPIC_MATCH,GATEWAY_ID
TRAINING_NOTIFY_01,NOTIFY_EMAIL,email
Add connection details to the system definition

You need to add the details using new item statements in the system definition. Open the alpha-system-definition.kts file and use the code below, adding the details of your SMTP server connection:

...
systemDefinition {
global {
...
item(name = "SYSTEM_DEFAULT_USER_NAME", value = "" )
item(name = "SYSTEM_DEFAULT_EMAIL", value = "" )
item(name = "EMAIL_SMTP_HOST", value = "" )
item(name = "EMAIL_SMTP_PORT", value = "" )
item(name = "EMAIL_SMTP_USER", value = "" )
item(name = "EMAIL_SMTP_PW", value = "" )
item(name = "EMAIL_SMTP_PROTOCOL", value = "SMTP")
}
...
}

Once this is in place, you can use systemDefinition["{NAME_OF_THE_ITEM}"].get() to get access to its value.

Insert EMAIL_DIST_NOTIFY_ROUTE_EXT

Finally, create the EMAIL_DIST_NOTIFY_ROUTE_EXT.csv as shown below. This creates the distribution email that will be used when the topic NOTIFY_EMAIL is used. Run the command SendItto insert the details in the table EMAIL_DIST_NOTIFY_ROUTE_EXT.

NOTIFY_ROUTE_ID,EMAIL_TO,EMAIL_CC,EMAIL_BCC
TRAINING_NOTIFY_01,email@host.com,email@host.com,,
caution

All fields are mandatory, so if you are not CCing or BCCing anyone, you need to leave these fields blank, so the platform understands that they are null. This is what we did with the EMAIL_BCC field in the previous example.

Switch on data dumps

Data dumps need to be switched on for EVALUATOR so we can see some additional data in the logs.

Run the LogLevel command to do this:

LogLevel -p ALPHA_EVALUATOR -DATADUMP_ON -l DEBUG

And then to see the logs run:

cd $L
tail -f ALPHA_EVALUATOR.log
tip

$L is an alias to the logs folder (~/run/runtime/logs) provided by the Genesis platform. Feel free to use your favourite command to view logs, such as tail, less etc.

Dynamic rules

In system terms, Evaluators enable you to connect Event Handlers to two different kinds of event: dynamic and static (cron rules):

  • Cron Rules are scheduling rules; these are defined as quartz cron expressions.
  • Dynamic Rules, also known as Dynamic Events, are defined as groovy expression, which respond to changes to database table entries.

In both cases, you define the rule in a table in the database:

  • CRON_RULES for static rules
  • and DYNAMIC_RULES for dynamic rules

Assuming we have already set up the Evaluator, our extended application should be able to create reports daily.

Now you are going to use the Evaluator again to set up dynamic rules. In this case, you want to send an email automatically if a specified limit has been breached.

Preparation

First, check that you have the Evaluator running. If it is not, check the procedure at the beginning of the exercise on setting up a cron rule.

You need to create three csv files for this. The first is the file with your rule in the correct format, similar to the static cron rule in the previous exercise. Call the file DYNAMIC_RULE.csv.

ID,NAME,DESCRIPTION,RULE_TABLE,RULE_STATUS,RULE_EXPRESSION,USER_NAME,PROCESS_NAME,MESSAGE_TYPE,RESULT_EXPRESSION
99,MY_RULE,It’s a rule,POSITION,ENABLED,(QUANTITY > 500),JaneDee,ALPHA_EVENT_HANDLER,EVENT_POSITION_CANCEL,((QUANTITY = 0) && (POSITION_ID = POSITION_ID))

The second csv file relates the dynamic with with a specific topic and route in the notify. Create a file called DYNAMIC_NOTIFY_RULE.csv with the following content:

DYNAMIC_NOTIFY_RULE_ID,DYNAMIC_RULE_ID,MESSAGE,TOPIC
1,99,Testing,NOTIFY_EMAIL

The third csv file enables you to test the rule. Create a file called POSITION.csv with the following data:

POSITION_ID,INSTRUMENT_ID,COUNTERPARTY_ID,QUANTITY,NOTIONAL
,2,2,600,1100000

Now you are ready to begin setting up your dynamic rule.

Exercise 2.1 Trigger the event to test the rule

ESTIMATED TIME

15 mins

So, let's see if that has worked.

Insert the file POSITION.csv into the database. This is the file that you prepared earlier; it contains a value that breaches a limit, so it should trigger our event.

You can see that when the limit is breached, you receive an email automatically.

Advanced views

Views enable you join related tables to create a single holistic view. In short, Views are the genesis equivalent of SQL select queries. Views are defined in the file application-name-view-dictionary.kts. If your application is called rubicon, then the file name will be rubicon-view-dictionary.kts.

Unlike tables, views do not have any data of their own, they are read-only, but present a view based on one or more tables. We saw basic concepts and common usages of views in the Developer Training. Now we are exploring advanced concepts for views, such as INNER vc OUTER joins, Parameterised joins, and Dynamic joins.

INNER and OUTER joins

Available join types are INNER and OUTER. If you do not specify the type, it defaults to OUTER.

  • INNER joins require all joins to match exactly; if one single join fails to match, the row will be discarded.
joining(INSTRUMENT, JoinType.INNER) {
on(TRADE { INSTRUMENT_ID } to INSTRUMENT { INSTRUMENT_ID })
  • OUTER joins provide null references for failed joins and will still allow the row to be built.

Dictionary-joined tables

When tables are joined in the dictionary, for example, when you create a subtable in the tables definition, you are able to join to those tables in views directly, without having to specify the fields on which to join. This does not currently work with aliased tables.

Joining on fields:

joining(TRADE_TO_SIDE) {
on(TRADE { TRADE_ID } to TRADE_TO_SIDE { TRADE_ID })

Joining using join:

joining(TRADE.JOIN_TRADE_TO_SIDE)

Parameterised joins

Some join operations require external parameters that are not available in the context of the table-join definition, but will be available when the view repository is accessed (e.g. client enriched definitions), so an option exists to create parameterised joins.

These are typically used in Request Server queries:

view("INSTRUMENT_PARAMETERS", INSTRUMENT) {
joins {
joining(ALT_INSTRUMENT_ID, JoinType.INNER) {
on(INSTRUMENT.ID to ALT_INSTRUMENT_ID.INSTRUMENT_ID)
.and(ALT_INSTRUMENT_ID.ALTERNATE_TYPE.asParameter())
}
}
fields {
ALT_INSTRUMENT_ID {
ALTERNATE_CODE withAlias "INSTRUMENT_CODE"
}
INSTRUMENT {
NAME withPrefix INSTRUMENT
}
}
}

So for the above, if we had a Request Server using the view, it would make ALTERNATE_TYPE available as a field input parameter.

Exercise 2.2 Changing TRADE_VIEW JOINs

ESTIMATED TIME

15 mins

Change the TRADE_VIEW JOINs types to INNER. Make sure the syntax uses curly brackets to link fields, and that the JOINs statements are simplified with Dictionary-joined.