Authors:
Ankit Mehta, Cille Schliebitz, Anita Gu
Changed on:
4 Feb 2025
In this scenario we will implement a Fraud Check step in the Order Workflow
So, if the total price is greater than the standard value — let's say the standard value is called HighValueThreshold, then create a 'flag' on the order. Based on the client scenario, we will now view the results after a requirements analysis and solution design has been conducted.
Flag the Order as 'HIGH VALUE' when the Order's Total Price is greater than HighValueThreshold
Create a custom Rule in our Workflow with the following specifications:
The next lesson contains exercises to help guide you through the steps for how to create a Rule. In these exercises, you will need to use the results from the requirements analysis and solution design from the above scenario.
But before moving on please take note of some important design principles.
Most of the time, you will be thinking about the Rule in the context of a specific Workflow and Use Case. It is also important to think about your Rule design. Follow the basic design principles when designing your Rule:
To learn more read Rule Development Guidelines & Recommended Practices and Designing Rules.
In this module, you will learn how to create a Rule class in your Plugin Project and create a HighValueThreshold constant. You will also learn how to declare @RuleInfo and @ParamString Annotations to the Rule class.
Remember the client scenario?
The steps below will use the Rule based on the Client Scenario — Implement Fraud Check.
In Steps 1 to 3 below, you will learn to write a Rule based on the solution designed as per the Client's requirement (discussed in the previous section). You will use the (earlier created) plugin project created earlier in the course.
Important: Please import com.fluentretail.rubix.v2.rule.Rule interface.
Please follow the Rule's naming convention on Fluent Docs
This video illustrates:
✅ How to create a Rule Class
✅ Import com.fluentretail.rubix.v2.rule.Rule
✅ How to pass the Context to run method.
To avoid magic Strings, declare your constants in the src/main/java.com/training/util folder.
Define the HighValueThreshold parameter (required in the Solution design) in the util package by using the below code:
`public static final String PARAM_NAME_HIGH_VALUE_THRESHOLD = "highValueThreshold"`
Param parameters are inputs required to configure Rule in the ruleset. These parameters are set for every execution.
Event-based parameters are optional and are Context-specific at run time.
As per the Solution Design, we need to provide the data about the constant "highValueThreshold" to the Rule as below:
`@ParamInteger(name = Constants.PARAM_NAME_HIGH_VALUE_THRESHOLD, description = "The value threshold of which Orders should be marked as High Value")`
Use accepts property to list which Entity type is accepted by the rule. Some Rules can accept only some specific entities if we don't use accepts then Rule can accept any Orchestration entity.
⚠️ After Steps 1- 3 your code should look like given below. Refer to the code below to make sure you have imported correct packages.
1package com.training.rule;
2
3import com.fluentretail.rubix.event.Event;
4import com.fluentretail.rubix.foundation.graphql.type.UpdateOrderInput;
5import com.fluentretail.rubix.rule.meta.EventInfo;
6import com.fluentretail.rubix.rule.meta.ParamInteger;
7import com.fluentretail.rubix.rule.meta.RuleInfo;
8import com.fluentretail.rubix.v2.context.Context;
9import com.fluentretail.rubix.v2.rule.Rule;
10import com.training.util.Constants;
11
12@RuleInfo(name = "MarkOrderHighValueRule"
13 , description = "Mark the Order as HIGH_VALUE when the Order " +
14 "Total Price is greater than {" + Constants.PARAM_NAME_HIGH_VALUE_THRESHOLD + "}"
15 , accepts = {
16 @EventInfo(entityType = "ORDER")
17 }
18 )
19@ParamInteger(name = Constants.PARAM_NAME_HIGH_VALUE_THRESHOLD, description = "The value " +
20 "threshold of which Orders should be marked as High Value", defaultValue = 1000)
21
22
23public class MarkOrderHighValueRule implements Rule
24{
25 @Override
26 public <C extends Context> void run(C context)
27 {
28
29 }
30}
Language: plain_text
Name: MarkOrderHighValueRule.java
Description:
Refer to the code to make sure you have imported the correct packages.
This video illustrates how to:
✅ Create a constant in util folder.
✅ Use @RuleInfo annotation
✅ Use @ParamString annotation
In this lesson, you will learn how to configure the run method in the Rule Class
Remember this client?
In this lesson, you will learn how to configure the run method in the MarkOrderHighValueRule class. You will write the five stages (phases) of the run method to get the desired solution, based on the Client Scenario — Implement Fraud Check covered in the previous lesson.
The Validation stage (phase) lets you validate all the required inputs to the Rule. If parameters or attributes are not provided then you either fail early or exit early. If proper validation is not done then 'NullPointerException' or 'ClassCastException' occurs. If any required Validation fails, your Rule should exit immediately. To do this, you can either:
Note that both options are dependent on the behaviour of the Rule Validation logic.
There is a 'RuleUtils' class in the Plugin project. The class facilitate the validation process by providing boolean responses and exception management
Follow the steps below to validate your rule. Use the checkboxes to track your progress as you complete each step:
You may also choose to watch the Video Demo below to see how each step is performed/executed.
The Retrieve Data / Query stage (phase) is optional and is dependent on business needs. This stage helps you to get additional data that you need to execute your Rule. Please note that you will be using the query created in the 'GraphQL within Java IDE'
Follow the steps below to execute your rule. Use the checkboxes to track your progress as you complete each step:
Reminder: You may also choose to watch the Video Demo below to see how each step is performed/executed.
Given below is the validation method code snippet . This method throws an exception if the retrieved Order or the Order attribute is null.
1 /*
2 * Query Result Validation Code extracted into Private method, but should be a Util method.
3 */
4 private void validateQueryResult(GetOrderByIdQuery.Data data, String orderId, Context context) {
5
6 if (data.orderById() == null) {
7 throw new RuleExecutionException(String.format("Unable to process Rule: %s - No Order Found for Id: %s, Order Ref: %s",this.getName(),orderId, context.getEntity().getRef()), context.getEvent());
8 }
9
10 if (data.orderById().totalPrice() == null) {
11 throw new RuleExecutionException(String.format("Unable to process Rule: %s - No TotalPrice Found for Order Id: %s, Order Ref: %s",this.getName(),orderId, context.getEntity().getRef()), context.getEvent());
12 }
13 }
Language: plain_text
Name: Validation method
Description:
This method throws an exception if the retrieved Order or the Order attribute is null.
This video illustrates how to:
✅ Include validation stage in the run method of the Rule class.
✅ Include stage - Retrieve and validate retrieved in the run method of the Rule class.
This phase performs any conditional logic required before building and producing action. Use a simple if statement to write condition logic.
In the Client Scenario, the Rule's action is executed on the below condition:
'If totalPrice of the Order is greater than a threshold parameter' code snippet:
1// Simple Logic:
2if (data.orderById().totalPrice() <= threshold) {
3return;
4}
Language: plain_text
Name: Rule condition
Description:
If totalPrice of the Order is greater than a threshold parameter.
Reminder: You may also choose to watch the Video Demo below to see how each step is performed/executed.
The data needed for the action is prepared and action is built in this stage. A Rule will produce an output action like:
Reminder: You may choose to watch the Video Demo below to see how each step is performed/executed.
In the Client scenario, let's say we want to save a new attribute to the Order indicating the Order is 'High Value'. To do so we can do the following:
1mutation updateOrderAttributes($input: UpdateOrderInput) {
2 updateOrder(input: $input) {
3 ref
4 }
5}
Language: plain_text
Name: Mutation query
Description:
GQL to run an updateOrder mutation
1/*
2 * Extracted to private method, but should be a Util method.
3 */
4 private List<AttributeInput> createNewAttributeInputAsList(String attrName, Class type, Object attrValue) {
5
6 AttributeInput attrInput = AttributeInput.builder().name(attrName).type(type.getSimpleName().toUpperCase()).value(attrValue).build();
7 List<AttributeInput> attributeInputList = new ArrayList<>();
8 attributeInputList.add(attrInput);
9 return attributeInputList;
10 }
Language: plain_text
Name: Method
Description:
Method to create an attributes list
1// Prepare for Action:
2 List<AttributeInput> attributeInputList = createNewAttributeInputAsList(IS_HIGH_VALUE_ORDER_ATTRIBUTE_NAME, Attribute.Type.BOOLEAN.getValueClass(), Boolean.TRUE);
3
4 UpdateOrderInput updateOrderInput = UpdateOrderInput.builder()
5 .id(orderId)
6 .attributes(attributeInputList)
7 .build();
8 UpdateOrderAttributesMutation updateOrderAttributesMutation = UpdateOrderAttributesMutation.builder().input(updateOrderInput).build();
Language: plain_text
Name: Mutation query object
Description:
Prepare the action by setting the orderId and attributesInputList to the updateOrderInput object
The final stage of the run method is to produce the output action , action which you have built in the Build Action data.
For our example , you can use context.action to produce action and mutate action by using the following code:
`context.action().mutation(updateOrderAttributesMutation);`
This video illustrates how to:
✅ Write the stage - write conditional logic in the run method
✅ Build the action data stage in the run method
✅ Produce the required action in the run method
Copyright © 2025 Fluent Retail Pty Ltd (trading as Fluent Commerce). All rights reserved. No materials on this docs.fluentcommerce.com site may be used in any way and/or for any purpose without prior written authorisation from Fluent Commerce. Current customers and partners shall use these materials strictly in accordance with the terms and conditions of their written agreements with Fluent Commerce or its affiliates.