Page tree
Skip to end of metadata
Go to start of metadata

Overview

FIX Edge Java provides a RoutingRule unit as an abstraction for internal message routing element. FEJ supports pure Java and Groovy implementations for routing rules.

Groovy routing rules are flexible mechanism that allows to implement custom logic for messages transformation and handling events. 

The rules can be embedded in a rules.groovy file:

rules.groovy
[
         messageRule(
                // rule description
                "some Rule",
                //source filter - ignore for this rule
                null,
                // context filter - apply this rule for New Order - Single (D) messages
                { ctx -> ctx.getMessage().getTagValueAsString(35) == "D" } as RuleCondition,
                // action for rule - resend message to all session within same group
                // and stop message processing
                { ctx ->
                    routingContext.getDestinationsByGroup(ctx.sourceParams.groups).each { adapter ->
                        adapter.send(ctx.message)
                        ctx.exit()
                    }
                } as RuleAction),
		eventRule("Catching session events", FIXSessionStateEvent.class, {
                appEvent ->
                    return true//do nothing but there can be additional logic
            	},
            	{
                	sessionStateEvent ->
                    	def sessionName = sessionStateEvent.getSessionId()
                    	logger.info("Session '{}' has been started.", sessionName)
            	}
        )
        // append system rejection rules for not processed messages
        getRejectionRule(routingContext)
]

The example represents two different types of rules - MessageRoutingRule and EventRoutingRule.

Groovy message routing rules syntax

messageRule helps to build a rule for message processing. It requires a few components for its instantiation:

messageRule(String description, SourceCondition sourceCondition, RuleCondition condition, RuleAction action)
  • description - String with free text description of rule

  • source filter - check if this rule should be applied to messages from certain source. This filter was added as a separate with propose of optimization process. Such filter can by applied on static basis without addition affect in runtime. Source filter is  SourceCondition implementation and can be null if you’d like to ignore it.

  • context filter - dynamic filter, which can check in the same time appliance of this rule depends on message content and source attributes. Context filter is RuleCondition implementation and can be null if you’d like to ignore it.

  • action - implementation of RuleAction which describes the main goal of this rule. It can be transformation, modification or just resending to required destination.

It is also possible to use "helper" method in case when one of several sections are not implemented

messageRule(description)
.action(msgCtx -> {....})
.build()

RuleDescription

Free text description of rule.

			// rule description
                "some Rule",


SourceCondition

It returns True or False.

 			//source filter - ignore for this rule
                null,


Possible values:

ParameterType
getId()String
getSource();Object
getTargetCompId()String
getTargetLocationId()String
getTargetSubId()String
getSenderCompId()String
getSenderLocationId()String
getSenderSubId()String


RuleCondition

Returning value is True or False, according to this value code in action section is called. Rule condition is usually used as a filter for routing rule.

Example bellow demonstrate a filter by message type. Action section will be called only for Order (D) messages in the example. 

{ ctx -> ctx.getMessage().getTagValueAsString(35) == "D" } as RuleCondition

The variable ctx here is used to access to the context of the message, it has the following methods

MethodsDescription

FIXFieldList getMessage()

FIX message

MessageEvent getMessageEvent()


EndpointParams getSourceParams()

Parameters of endpoint which received the message.

void exit()

Specifies not to execute any rules after execution current one.

boolean isExit()


StorageManager getContextManager()


RuleAction

Defines the actions that will apply to the messages that correspondes to the SourceCondition and RuleCondition filters. 

Example:

			// action for rule - resend message to all session within same group
            // and stop message processing
                { ctx ->
                    rc.getDestinationsByGroup(ctx.sourceParams.groups).each { adapter ->
                        adapter.send(ctx.message)
                        ctx.exit()
                    }
                } as RuleAction),

ctx variable here is the same as for RuleCondition.

Groovy event routing rules syntax

eventRule method helps to build a rule for event processing. It requires a few components for its instantiation:

eventRule(String description, Class<AppEvent> eventType, Predicate<AppEvent> ruleCondition, Consumer<AppEvent> ruleAction)
  • description - string with free test description of rule

  • event type - type or subtype of event for which the rule is applied.
  • rule condition - dynamic filter, which can check in the same time appliance of this rule depends on event content and source attributes. Context filter can be null if you’d like to ignore it.
  • rule action - describes the main goal of this rule.

EventType

Type of the events for which the rule is applied. Subtype or general type can be specified.

Available list of types and their methods

Event categoryClass of eventMethodsDescription
General 



BasicAppEvent

The basic class of all events, can be used for handling all the events system throws.
Application



ServerStateEvent

getSource(): STARTED

Notifies about the changes in state of the FIX server.
Session



FIXSessionStateEvent

getSessionState(): CONNECTING, WAITING_FOR_LOGON, CONNECTED, WAITING_FOR_LOGOFF, DISCONNECTED, LOGON_RECEIVED, DEAD, DISCONNECTED_ABNORMALLY, RECONNECTING, WAITING_FOR_FORCED_LOGOFF, WAITING_FOR_FORCED_DISCONNECT

getSessionId(): String

Notifies about the changes in state of the FIX sessions.

NewSessionEvent

SessionParameters getSessionParameters()

reject(String reason)

reject(String reason, boolean quiet)

The event is intended for accepting or rejecting new incoming session. The session will be rejected if reject method is called or accepted if not.

note: if reject method is called, the next rule for the event will not be processed.

Scheduler



SchedulerEvent
getId(): StringEvent that is created by scheduler when the trigger executes.
SnF



SnFEventgetSource(): MESSAGE_WAS_QUEUED, MESSAGE_WAS_SKIPPED
Rule events



RuleErrorEvent

getException(): Exception

getMessage(): FIXFieldList

getRuleDescription(): String

Notifies that there is an exception in some of the rule processed.

UnprocessedMessageEvent
getMessage(): FIXFieldListNotifies that there are no acceptable rules defined for the specified message.

note: If BasicAppEvent is specified in eventRule method as a event type parameter, all the events above will be trigger the rule.

Examples

import com.epam.fej.server.fix.event.ServerStateEvent
import com.epam.fej.server.fix.event.SessionStateEvent
import com.epam.fej.scheduling.event.SchedulerEvent

[
        eventRule("Catching session events", SessionStateEvent.class, {
                appEvent ->
                    return true//do nothing but there can be additional logic
            },
            {
                sessionStateEvent ->
                    def sessionName = sessionStateEvent.getSessionId()
                    logger.info("I'm rule for session events, I was called because session '{}' has been started.", sessionName)
            }
        ),
        eventRule("Catching server events", ServerStateEvent.class, {
                appEvent -> return true//do nothing but there can be additional logic
            },
            {
                serverStateEvent ->
                    String state = String.valueOf(serverStateEvent.getSource())
                    logger.info("I'm rule for server events, I was called because server has {}.", state)
            }
        ),
        eventRule("Catching scheduler events", SchedulerEvent.class, {
                appEvent -> return true//do nothing but there can be additional logic
            },
            {
                schedulerEvent ->
                    logger.info("I'm rule for schedule events, id - {}.", schedulerEvent.getId())
            }
        ),
		eventRule("Custom accepting of FIX sessions", NewSessionEvent.class, null,
                {
                    newSessionEvent ->
                        boolean accepted = true
                        def sessionParameters = newSessionEvent.getSessionParameters()
                        if (sessionParameters.getIncomingUserName() != "User1" || sessionParameters.getIncomingPassword() != "Password1") {
                            newSessionEvent.reject("Wrong username or/and password")
                            accepted = false
                        }
                        logger.info("Session {} is {}", sessionParameters.getSessionID(), accepted ? "accepted" : "declined")
                }
        )
]

Example of scheduler settings - an event SchedulerEvent will be published every 10 seconds. 

<schedule id="every10Seconds">
        <task name="event" timeZone="Europe/Samara">
            <event cron="*/10 * * ? * *"/>
        </task>
</schedule>

Groovy routing rules "helpers" methods

There is a static class with methods which name "helpers", they help end-user make logic shorter by encapsulating the details inside the methods.

NameDefinitionDescription
generateUniqueIdString generateUniqueId()

returns UUID that is generated using a cryptographically strong pseudo random number generator.

Example:

def id = generateUniqueId()

stringValueString stringValue(FIXFieldList msg, int tag)

returns string representation of value by provided tag

Example:

def destination = stringValue(msg, Header.DeliverToCompID)

messageRule

RoutingRule messageRule(String description, SourceCondition sourceCondition, RuleCondition condition, RuleAction action)

short version for creating MessageRoutingRule

messageRule

RoutingRuleBuilder messageRule(String description)


rule builder for creating MessageRoutingRule

messageRule(description)
.sourceCondition(params -> {....})
.condition(msgCtx -> {....})
.action(msgCtx -> {....})
.build()

eventRule

EventRoutingRuleBuilder eventRule(String description)


rule builder for creating EventRoutingRule

eventRule(description)
.eventType(eventType)
.condition(event -> {....})
.action(event -> {....})
.build()

eventRuleRoutingRule eventRule(String description, Class<AppEvent> eventType,
Predicate<AppEvent> ruleCondition, Consumer<AppEvent> ruleAction)

short version for creating EventRoutingRule

removeRepGroupvoid removeRepGroup(FIXFieldList msg, int leadingTag, int groupTags[])

removes the list of tags that corresponds to the repeating group. 

Example:

removeRepGroup(msg, 453, [452, 448, 447])

sendvoid send(RoutingContext rc, RuleContext ruleContext, String targetCompId)

sends a message to the session by provided targetCompId

Example:

send(routingContext, msgCtx, destination)

sendvoid send(RoutingContext rc, RuleContext ruleContext, String targetCompId, String qualifier)

sends a message to the session by provided targetCompId and sessionQualifier

Example:

send(routingContext, ctx, destination, qualifier)

Import of the classes

It is not necessary to import classes directly in the groovy.rules file. The classes are described in the fej-routing.xml. The values bellow are predefined and can be extended by custom ones not to specify imports in rules.

fej-routing.xml
	<util:list id="imports" value-type="java.lang.String">
        <value>com.epam.fej.context.Storage</value>
        <value>com.epam.fej.context.StorageManager</value>
        <value>com.epam.fej.routing.RoutingContext</value>
        <value>com.epam.fej.routing.MessageEventPool</value>
        <value>com.epam.fej.routing.rules.RoutingRule</value>
        <value>com.epam.fej.routing.rules.RuleAction</value>
        <value>com.epam.fej.routing.rules.RuleCondition</value>
        <value>com.epam.fej.routing.rules.SourceCondition</value>
        <value>com.epam.fej.server.fix.event.FIXSessionStateEvent</value>
        <value>com.epam.fej.server.fix.event.NewSessionEvent</value>
        <value>com.epam.fej.routing.event.RuleErrorEvent</value>
        <value>com.epam.fej.scheduling.event.SchedulerEvent</value>
        <value>com.epam.fej.server.fix.event.ServerStateEvent</value>
        <value>com.epam.fej.routing.endpoint.snf.events.SnFEvent</value>
        <value>com.epam.fej.routing.event.UnprocessedMessageEvent</value>
    </util:list>

Injected properties

This properties available for use in groovy rule.

fej-routing.xml
<property name="additionalProperties">
	<map key-type="java.lang.String">
    	<entry key="routingContext" value-ref="routingContext"/>
        <entry key="storageManager" value-ref="storageManager"/>
        <entry key="storageManager" value-ref="messageEventPool"/>
	</map>
</property>
  • No labels