Author:
Lesley Dean
Changed on:
1 July 2024
As with many "Hello World" code examples, we will write the simplest implementation of a Rule that produces a log saying "Hello World".
The following steps will provide a simple rule that simply produces a
`LogAction`
A
`LogAction`
`ORCHESTRATION_AUDIT`
Workflow Rules are written in Java, and implement the Rules SDK's Rule interface. Rules should be annotated with metadata to describe the Rule internally to the Workflow Engine and the Workflow Builder UI.
Rules produce actions. Actions are the outcome of a rule. There are 4 actions supported by the Rules SDK:
Read more about Rule Actions here.
For this example, we will use the simplest action for our rule - LogAction.
`rule`
`src/main/java/com/acme/rule`
`LogHelloWorld.java`
`com.fluentretail.rubix.v2.rule.Rule`
`run`
`run(C context)`
`@RuleInfo`
`com.fluentretail.rubix.rule.meta.RuleInfo`
`name`
`@RuleInfo`
`description`
`run`
`LogAction`
`ActionFactory`
`context`
`context.action().log();`
`message`
`detailedMessage`
`attributes`
`new ArrayList<>()`
1package com.fluentcommerce.rule;
2
3import com.fluentretail.rubix.rule.meta.RuleInfo;
4import com.fluentretail.rubix.v2.context.Context;
5import com.fluentretail.rubix.v2.rule.Rule;
6
7import java.util.ArrayList;
8
9@RuleInfo(name = "LogHelloWorld", description = "Say Hello to the World")
10public class LogHelloWorld implements Rule {
11 @Override
12 public <C extends Context> void run(C context) {
13 context.action().log("Hello World", "This is a log message that says Hello World", new ArrayList<>());
14 }
15}
Language: java
Name: Rule class code LogHelloWorld.java
Description:
LogHelloWorld.java Rule Class
Unit Tests facilitate quality assurance for your rules.
In this example, we will use the Mockito mocking framework together with JUnit to test that the rule successfully produces a LogAction with the "Hello World" message.
`rule`
`src/test/java`
`src/test/java/com/acme/rule`
`LogHelloWorldTest.java`
`private final LogHelloWorld rule = new LogHelloWorld();`
`private AutoCloseable mocks;`
`private Context context;`
`private ActionFactory actionFactory;`
`setUp`
`@Before`
`mocks = MockitoAnnotations.openMocks(this);`
`when(context.action()).thenReturn(actionFactory);`
`tearDown`
`@After`
`mocks.close();`
`run_producesHelloWorldLog`
`@Test public void run_producesHelloWorldLog()`
`run`
`rule.run(context);`
`LogAction`
`verify(actionFactory, times(1)).log(eq("Hello World"), anyString(), anyList());`
1package com.fluentcommerce.rule;
2
3import com.fluentretail.rubix.v2.action.ActionFactory;
4import com.fluentretail.rubix.v2.context.Context;
5import org.junit.After;
6import org.junit.Before;
7import org.junit.Test;
8import org.mockito.Mock;
9import org.mockito.MockitoAnnotations;
10
11import static org.mockito.Mockito.*;
12
13public class LogHelloWorldTest {
14
15 private final LogHelloWorld rule = new LogHelloWorld();
16 private AutoCloseable mocks;
17
18 @Mock
19 private Context context;
20
21 @Mock
22 private ActionFactory actionFactory;
23
24 @Before
25 public void setUp() throws Exception {
26 mocks = MockitoAnnotations.openMocks(this);
27
28 when(context.action()).thenReturn(actionFactory);
29 }
30
31 @After
32 public void tearDown() throws Exception {
33 mocks.close();
34 }
35
36 @Test
37 public void run_producesHelloWorldLog() {
38
39 // arrange:
40
41 // act:
42 rule.run(context);
43
44 // assert:
45 verify(actionFactory, times(1)).log(eq("Hello World"), anyString(), anyList());
46 }
47}
Language: java
Name: Test class code LogHelloWorldTest.java
Description:
LogHelloWorldTest.java Unit Test Class
The Rules SDK provides a TestExecutor which simulates running your rule in a workflow engine on your local development environment.
The TestExecutor provides access to the TestContext which can be used to assert certain outcomes of your rule.
`rule`
`src/test/java`
`src/test/java/com/acme/rule`
`LogHelloWorldExecutorTest.java`
`private static final String ORDER_ID = "123";`
`private static final String ORDER_REF = "HD_123";`
`private TestExecutor executor;`
`private Event event;`
`setUp`
`@Before`
`RubixEntity entity = RubixEntity.builder()`
`.entityType("ORDER")`
`.id(ORDER_ID)`
`.ref(ORDER_REF)`
`.status("BOOKED")`
`.type("HD")`
`.flexType("ORDER::HD")`
`.flexVersion(1)`
`.build();`
`event = Event.builder()`
`.retailerId("1")`
`.entityId(entity.getId())`
`.entityRef(entity.getRef())`
`.entityType(entity.getEntityType())`
`.name("test-event")`
`.build();`
`RuleSet ruleSet = ruleSet(event, ruleInstance(LogHelloWorld.class.getSimpleName()));`
`executor = TestExecutor.builder()`
`.rule(LogHelloWorld.class)`
`.ruleset(ruleSet)`
`.entity(entity)`
`.build();`
`run_producesLogEvent`
`@Test public void run_producesLogEvent()`
`execute`
`TestContext testContext = executor.execute(event);`
`assertEquals(1, testContext.countActionsOfType(TestContext.LogAction.class));`
1package com.fluentcommerce.rule;
2
3import com.fluentretail.api.model.RubixEntity;
4import com.fluentretail.rubix.event.Event;
5import com.fluentretail.rubix.v2.test.TestContext;
6import com.fluentretail.rubix.v2.test.TestExecutor;
7import com.fluentretail.rubix.workflow.RuleSet;
8import org.junit.Before;
9import org.junit.Test;
10
11import static com.fluentretail.rubix.test.TestUtils.ruleInstance;
12import static com.fluentretail.rubix.test.TestUtils.ruleSet;
13import static org.junit.Assert.assertEquals;
14
15public class LogHelloWorldExecutorTest {
16
17 private static final String ORDER_ID = "123";
18 private static final String ORDER_REF = "HD_123";
19
20 private TestExecutor executor;
21
22 private Event event;
23
24 @Before
25 public void setUp() {
26
27 // Setup up an instance of an Orchestrate-able Entity
28 RubixEntity entity = RubixEntity.builder()
29 .entityType("ORDER")
30 .id(ORDER_ID)
31 .ref(ORDER_REF)
32 .status("BOOKED")
33 .type("HD")
34 .flexType("ORDER::HD")
35 .flexVersion(1)
36 .build();
37
38 // Create an Event to trigger the Ruleset
39 event = Event.builder()
40 .retailerId("1")
41 .entityId(entity.getId())
42 .entityRef(entity.getRef())
43 .entityType(entity.getEntityType())
44 .name("test-event")
45 .build();
46
47 // Create an instance of a Ruleset which contains an instance of the Rule configured with the Parameters
48 RuleSet ruleSet = ruleSet(event, ruleInstance(LogHelloWorld.class.getSimpleName()));
49
50 // Set up a TestExecutor to simulate Orchestration Engine
51 executor = TestExecutor.builder()
52 .rule(LogHelloWorld.class)
53 .ruleset(ruleSet)
54 .entity(entity)
55 .build();
56
57 }
58
59 @Test
60 public void run_producesLogEvent() {
61
62 TestContext testContext = executor.execute(event);
63
64 assertEquals(1, testContext.countActionsOfType(TestContext.LogAction.class));
65 }
66}
Language: java
Name: Executor Test class code LogHelloWorldExecutorTest.java
Description:
LogHelloWorldExecutorTest Java Class
You are now ready to Deploy and Run your rule.
Copyright © 2024 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.