orbit-code-ai 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +29 -0
- package/README.md +326 -0
- package/_agent_reference/components/audit-logging.md +129 -0
- package/_agent_reference/components/common-utils.md +146 -0
- package/_agent_reference/components/error-handling.md +117 -0
- package/_agent_reference/components/http-adapters.md +134 -0
- package/_agent_reference/components/input-adapters.md +101 -0
- package/_agent_reference/components/output-adapters.md +124 -0
- package/_agent_reference/components/property-reader.md +100 -0
- package/_agent_reference/components/retry.md +107 -0
- package/_agent_reference/config/naming-conventions.md +188 -0
- package/_agent_reference/config/properties-template.md +158 -0
- package/_agent_reference/config/queue-definition.md +141 -0
- package/_agent_reference/esql-coding-standards.md +112 -0
- package/_agent_reference/msgflow-xml-reference.md +207 -0
- package/_agent_reference/node_types_extended.md +211 -0
- package/_agent_reference/templates/file-flow.md +212 -0
- package/_agent_reference/templates/http-flow.md +185 -0
- package/_agent_reference/templates/mq-flow.md +248 -0
- package/bin/import-specifier.mjs +13 -0
- package/bin/import-specifier.test.mjs +13 -0
- package/bin/orbit +32 -0
- package/dist/cli.mjs +492705 -0
- package/package.json +149 -0
- package/skills/ace-app-http/SKILL.md +523 -0
- package/skills/ace-app-mq/SKILL.md +554 -0
- package/skills/apic-api/SKILL.md +645 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Error Handling
|
|
2
|
+
|
|
3
|
+
Central error handling is provided by `ErrorHandler.subflow` + `ErrorHandler.esql`. Every flow MUST wire its exception terminal to the error handler.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ErrorHandler.subflow
|
|
8
|
+
|
|
9
|
+
**Purpose**: Catches all exceptions, builds a standardized error response, logs it, and routes to dead-letter or returns a business error.
|
|
10
|
+
|
|
11
|
+
**Internal flow**:
|
|
12
|
+
```
|
|
13
|
+
Exception caught
|
|
14
|
+
↓
|
|
15
|
+
ErrorHandler.esql (build error structure)
|
|
16
|
+
↓
|
|
17
|
+
ErrorHandler_IsExceptionCaught.esql (filter: already handled?)
|
|
18
|
+
↓
|
|
19
|
+
LogError subflow (audit the error)
|
|
20
|
+
↓
|
|
21
|
+
[Route based on adapter type]
|
|
22
|
+
├── MQ_Dead_Output_Node (async flows)
|
|
23
|
+
└── MWBusinessErrorResponse (sync/HTTP flows)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**ESQL modules**:
|
|
27
|
+
| Module | Purpose |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `ErrorHandler.esql` | Main: 43KB — builds error structure, maps error codes per backend |
|
|
30
|
+
| `ErrorPoint.esql` | Create error message structure from exception |
|
|
31
|
+
| `ErrorHandler_IsExceptionCaught.esql` | Filter: prevent double-handling |
|
|
32
|
+
| `ErrorHandler_SetExceptionCaught.esql` | Mark exception as handled |
|
|
33
|
+
| `ErrorHandler_IsFileSchemaValidationOccured.esql` | Detect file schema validation errors |
|
|
34
|
+
| `ErrorHandler_PrepareFileDataForAudit.esql` | Prepare file error data for audit |
|
|
35
|
+
| `ESBBusinessErrorResponse.esql` | Build ESB-standard business error response |
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## MWBusinessErrorResponse.subflow
|
|
40
|
+
|
|
41
|
+
**Purpose**: Returns a structured business error response to the caller (used in sync/HTTP flows).
|
|
42
|
+
|
|
43
|
+
**When to use**: REST/HTTP flows where the caller expects a JSON error response.
|
|
44
|
+
|
|
45
|
+
**Response structure**:
|
|
46
|
+
```xml
|
|
47
|
+
<ResponseStatus>
|
|
48
|
+
<Code>XXXXXXXX</Code>
|
|
49
|
+
<Status>Error</Status>
|
|
50
|
+
<EnglishMsg>Human readable message</EnglishMsg>
|
|
51
|
+
</ResponseStatus>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Error Codes by Backend System
|
|
57
|
+
|
|
58
|
+
Defined as constants in `CommonUtils.esql`:
|
|
59
|
+
|
|
60
|
+
| Constant | Value | Backend |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| `ESB_SUCCESS_RESPONSE_CODE` | `'00000000'` | All |
|
|
63
|
+
| `ESB_RUNTIME_TECHNICAL_ERROR_CODE` | `'99999999'` | All (generic) |
|
|
64
|
+
| `ESB_MIDDLEWARE_DATABASE_ERROR_RESPONSE_CODE` | `'E0199998'` | DB errors |
|
|
65
|
+
|
|
66
|
+
Additional backend-specific codes exist for:
|
|
67
|
+
- **T24**: Core banking errors
|
|
68
|
+
- **NIWS**: National Information and Workflow System
|
|
69
|
+
- **ODM**: Operational Decision Manager
|
|
70
|
+
- **Unifonic**: SMS/notification service
|
|
71
|
+
- **MLSD**: Ministry of Labor and Social Development
|
|
72
|
+
- **ICBS**: Core banking system
|
|
73
|
+
|
|
74
|
+
Read `ErrorHandler.esql` directly for the full mapping if you need specific codes.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Wiring the Error Handler in a New Flow
|
|
79
|
+
|
|
80
|
+
Every node that can fail must connect its **failure/exception terminal** to `ErrorHandler`:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
[Any Node]
|
|
84
|
+
│ failure terminal
|
|
85
|
+
↓
|
|
86
|
+
ErrorHandler.subflow
|
|
87
|
+
│
|
|
88
|
+
├──[MQ flow]──→ MQ_Dead_Output_Node
|
|
89
|
+
└──[HTTP flow]─→ MWBusinessErrorResponse
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**ESQL DECLARE for ErrorHandler behavior**:
|
|
93
|
+
```esql
|
|
94
|
+
-- Set which backend adapter this flow uses (controls error code mapping)
|
|
95
|
+
DECLARE IsT24Adapter EXTERNAL BOOLEAN FALSE;
|
|
96
|
+
DECLARE IsODMWSAdapter EXTERNAL BOOLEAN FALSE;
|
|
97
|
+
DECLARE IsFrontEndJSONAdapter EXTERNAL BOOLEAN FALSE;
|
|
98
|
+
DECLARE IsNIWSAdapter EXTERNAL BOOLEAN FALSE;
|
|
99
|
+
DECLARE IsUniFonicAdapter EXTERNAL BOOLEAN FALSE;
|
|
100
|
+
DECLARE IsMLSDAdapter EXTERNAL BOOLEAN FALSE;
|
|
101
|
+
DECLARE IsICBSAdapter EXTERNAL BOOLEAN FALSE;
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Set the appropriate flag to `TRUE` at the node level to get correct error codes for that backend.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## ErrorPoint Usage
|
|
109
|
+
|
|
110
|
+
Use `ErrorPoint.esql` when you need to manually create an error structure (e.g., business validation failure before calling a backend):
|
|
111
|
+
|
|
112
|
+
```esql
|
|
113
|
+
-- Set error details on the Environment before routing to ErrorHandler
|
|
114
|
+
SET Environment.ErrorDetails.Code = 'XXXXXXXX';
|
|
115
|
+
SET Environment.ErrorDetails.EnglishMsg = 'Validation failed: ...';
|
|
116
|
+
-- Then propagate to ErrorHandler via failure terminal
|
|
117
|
+
```
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# HTTP Adapters & Internal Service Caller
|
|
2
|
+
|
|
3
|
+
Used for outbound HTTP calls (to backends or internal services) and for chaining ACE flows together.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## HTTPRequestAdapter.subflow
|
|
8
|
+
|
|
9
|
+
**Purpose**: Makes an outbound HTTP or SOAP call to an external backend system.
|
|
10
|
+
|
|
11
|
+
**Supported backends**: T24, NIWS, ODM, Unifonic, MLSD, ICBS, and any REST/SOAP service.
|
|
12
|
+
|
|
13
|
+
**ESQL helpers**:
|
|
14
|
+
| Module | Purpose |
|
|
15
|
+
|---|---|
|
|
16
|
+
| `HTTPResponseAdapter_CheckCallType.esql` | Determine INTERNAL vs EXTERNAL call |
|
|
17
|
+
| `InternalHTTPRequestAdapter_Remove_MQRFH2.esql` | Strip MQRFH2 headers before HTTP call |
|
|
18
|
+
|
|
19
|
+
**ESQL DECLARE flags** (set at node level):
|
|
20
|
+
```esql
|
|
21
|
+
DECLARE IsT24Adapter EXTERNAL BOOLEAN FALSE;
|
|
22
|
+
DECLARE IsODMWSAdapter EXTERNAL BOOLEAN FALSE;
|
|
23
|
+
DECLARE IsFrontEndJSONAdapter EXTERNAL BOOLEAN FALSE;
|
|
24
|
+
DECLARE IsNIWSAdapter EXTERNAL BOOLEAN FALSE;
|
|
25
|
+
DECLARE IsUniFonicAdapter EXTERNAL BOOLEAN FALSE;
|
|
26
|
+
DECLARE IsMLSDAdapter EXTERNAL BOOLEAN FALSE;
|
|
27
|
+
DECLARE IsICBSAdapter EXTERNAL BOOLEAN FALSE;
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Set exactly ONE of these to `TRUE` to get correct request formatting and error code mapping for that backend.
|
|
31
|
+
|
|
32
|
+
**URL/endpoint**: Set in `Environment.Destination.HTTP.RequestURL` before calling this subflow, or configure in `BankIdForRoutingService` properties group.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## HTTPResponseAdapter.subflow
|
|
37
|
+
|
|
38
|
+
**Purpose**: Processes the HTTP response from a backend call, normalizes it to the standard ESB response structure.
|
|
39
|
+
|
|
40
|
+
**ESQL helper**: `HTTPResponseAdapter_CheckCallType.esql`
|
|
41
|
+
- Routes differently based on whether it was an `INTERNAL` or `EXTERNAL` call
|
|
42
|
+
|
|
43
|
+
**Always pair with** `HTTPRequestAdapter` — use both or neither.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## InternalServiceCaller.subflow
|
|
48
|
+
|
|
49
|
+
**Purpose**: Calls another ACE message flow in the same broker (service-to-service chaining without going through HTTP).
|
|
50
|
+
|
|
51
|
+
**ESQL modules**:
|
|
52
|
+
| Module | Purpose |
|
|
53
|
+
|---|---|
|
|
54
|
+
| `InternalServiceCaller_Compute.esql` | Build the internal call message |
|
|
55
|
+
| `InternalServiceCaller_Filter.esql` | Route based on call success/failure |
|
|
56
|
+
|
|
57
|
+
**Configuration** (from `Variables` group in Properties):
|
|
58
|
+
```xml
|
|
59
|
+
<group name="Variables">
|
|
60
|
+
<property name="callCorrIDOffset" value="1" />
|
|
61
|
+
</group>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`callCorrIDOffset`: Offset added to correlation ID to uniquely identify this leg of the flow chain.
|
|
65
|
+
|
|
66
|
+
**When to use**: When this flow needs to call another ESB service internally, without the overhead of an HTTP round-trip.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## HTTPInternalCaller.subflow
|
|
71
|
+
|
|
72
|
+
**Purpose**: Calls an internal ACE service via HTTP (when the service is exposed as a REST endpoint).
|
|
73
|
+
|
|
74
|
+
**When to use**: Internal HTTP calls where the target flow is REST-exposed. Prefer `InternalServiceCaller` for non-HTTP internal calls.
|
|
75
|
+
|
|
76
|
+
**ESQL module**: `Internal_HTTP_CheckMessageDomain.esql` — checks if the message domain is correct for internal HTTP.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## InternalHTTPRequestAdapter.subflow
|
|
81
|
+
|
|
82
|
+
**Purpose**: Variant of `HTTPRequestAdapter` optimized for internal (within-broker) HTTP calls.
|
|
83
|
+
|
|
84
|
+
**ESQL helper**: `InternalHTTPRequestAdapter_Remove_MQRFH2.esql` — strips MQ headers that shouldn't be forwarded over HTTP.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Call Type Reference
|
|
89
|
+
|
|
90
|
+
| Scenario | Subflow to Use |
|
|
91
|
+
|---|---|
|
|
92
|
+
| Call T24 / NIWS / ODM / external backend | `HTTPRequestAdapter` + `HTTPResponseAdapter` |
|
|
93
|
+
| Chain to another ACE flow (non-HTTP) | `InternalServiceCaller` |
|
|
94
|
+
| Chain to another ACE REST flow | `HTTPInternalCaller` |
|
|
95
|
+
| Internal HTTP (broker-to-broker) | `InternalHTTPRequestAdapter` |
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Wiring Pattern (External Backend Call)
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
[Your flow logic]
|
|
103
|
+
↓
|
|
104
|
+
HTTPRequestAdapter ← set IsT24Adapter=TRUE (or relevant flag)
|
|
105
|
+
↓
|
|
106
|
+
HTTPResponseAdapter ← normalizes response
|
|
107
|
+
↓
|
|
108
|
+
[Continue flow / LogOutgoingAudit / Output Adapter]
|
|
109
|
+
|
|
110
|
+
Error path:
|
|
111
|
+
HTTPRequestAdapter (failure) → ErrorHandler
|
|
112
|
+
HTTPResponseAdapter (failure) → ErrorHandler
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Setting the Target URL
|
|
118
|
+
|
|
119
|
+
Via Properties `BankIdForRoutingService` group (multi-value):
|
|
120
|
+
```xml
|
|
121
|
+
<group name="BankIdForRoutingService">
|
|
122
|
+
<property name="qiwa">
|
|
123
|
+
<value>T24</value> <!-- bank/system ID -->
|
|
124
|
+
<value>SCALNT01</value> <!-- service name -->
|
|
125
|
+
<value>http://host:port/service/endpoint</value> <!-- URL -->
|
|
126
|
+
</property>
|
|
127
|
+
</group>
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Access in ESQL:
|
|
131
|
+
```esql
|
|
132
|
+
DECLARE targetUrl CHARACTER;
|
|
133
|
+
SET targetUrl = Environment.Properties.{AppLabel}.{flowName}.BankIdForRoutingService.qiwa[3];
|
|
134
|
+
```
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Input Adapters
|
|
2
|
+
|
|
3
|
+
All input adapters live in `Qiwa/Framework/Lib/`. Use them as the entry point of every message flow.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## MQ_Input_Node.subflow
|
|
8
|
+
|
|
9
|
+
**Purpose**: MQ asynchronous input. Reads from a queue, loads properties, optionally audits, validates, and supports retry/rollback.
|
|
10
|
+
|
|
11
|
+
**Internal wiring** (what it does inside):
|
|
12
|
+
1. Reads message from MQ queue
|
|
13
|
+
2. Calls `PropertyReader` to load flow config into `Environment.Properties`
|
|
14
|
+
3. Checks `IsPropertiesEnabled` → `IsAuditEnabled` → `IsRetryEnabled` → `IsRollBackEnabled` → `IsSchemaValidationNeeded`
|
|
15
|
+
4. Prepares audit message via `MQ_Input_Node_PrepareAuditMessage.esql`
|
|
16
|
+
5. Routes to `LogAudit` subflow
|
|
17
|
+
|
|
18
|
+
**ESQL helper modules used**:
|
|
19
|
+
| Module | Purpose |
|
|
20
|
+
|---|---|
|
|
21
|
+
| `MQ_Input_Node_IsAuditEnabled.esql` | Filter: check if audit is on |
|
|
22
|
+
| `MQ_Input_Node_IsPropertiesEnabled.esql` | Filter: check if properties loaded |
|
|
23
|
+
| `MQ_Input_Node_IsRetryEnabled.esql` | Filter: check if retry is on |
|
|
24
|
+
| `MQ_Input_Node_IsRollBackEnabled.esql` | Filter: check if rollback is on |
|
|
25
|
+
| `MQ_Input_Node_PrepareAuditMessage.esql` | Compute: build audit payload |
|
|
26
|
+
|
|
27
|
+
**Configuration flags** (set in Properties XML under `Logging` group):
|
|
28
|
+
```
|
|
29
|
+
AuditEnabled TRUE/FALSE
|
|
30
|
+
LogEnabled TRUE/FALSE
|
|
31
|
+
RetryEnabled TRUE/FALSE (also under Retry group)
|
|
32
|
+
ValidationEnabled TRUE/FALSE (under SchemaValidation group)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**ESQL DECLARE for this node**:
|
|
36
|
+
```esql
|
|
37
|
+
DECLARE IsAuditEnabled EXTERNAL BOOLEAN FALSE;
|
|
38
|
+
DECLARE IsRetryEnabled EXTERNAL BOOLEAN FALSE;
|
|
39
|
+
DECLARE IsRollBackEnabled EXTERNAL BOOLEAN FALSE;
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**When to use**: Any flow that reads from an IBM MQ queue asynchronously.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## File_Input_Node.subflow
|
|
47
|
+
|
|
48
|
+
**Purpose**: Reads files from the file system. Supports audit, schema validation, and property loading.
|
|
49
|
+
|
|
50
|
+
**ESQL helper modules used**:
|
|
51
|
+
| Module | Purpose |
|
|
52
|
+
|---|---|
|
|
53
|
+
| `File_Input_Node_IsAuditEnabled.esql` | Filter: audit check |
|
|
54
|
+
| `File_Input_Node_IsPropertiesEnabled.esql` | Filter: properties check |
|
|
55
|
+
| `File_Input_Node_IsSchemaValidationNeeded.esql` | Filter: validate file schema |
|
|
56
|
+
| `File_Input_Node_PrepareAuditMessage.esql` | Compute: build audit payload |
|
|
57
|
+
|
|
58
|
+
**Configuration flags**:
|
|
59
|
+
```
|
|
60
|
+
AuditEnabled TRUE/FALSE
|
|
61
|
+
LogEnabled TRUE/FALSE
|
|
62
|
+
ValidationEnabled TRUE/FALSE
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**When to use**: Any flow triggered by a file drop (batch processing, file-based integration).
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Rest_Input_Node.subflow
|
|
70
|
+
|
|
71
|
+
**Purpose**: HTTP REST input. Accepts JSON requests, loads properties, supports audit.
|
|
72
|
+
|
|
73
|
+
**When to use**: Any flow exposed as a REST endpoint.
|
|
74
|
+
|
|
75
|
+
**Notes**:
|
|
76
|
+
- JSON body is parsed into `XMLNSC` domain internally
|
|
77
|
+
- Standard `Header` structure must be present in the request
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Common Pattern Across All Input Adapters
|
|
82
|
+
|
|
83
|
+
Every input adapter follows this sequence:
|
|
84
|
+
```
|
|
85
|
+
[Input Node]
|
|
86
|
+
↓
|
|
87
|
+
PropertyReader ← load XML config into Environment tree
|
|
88
|
+
↓
|
|
89
|
+
AuditPoint (incoming) ← log request if AuditEnabled=TRUE
|
|
90
|
+
↓
|
|
91
|
+
[Your flow logic]
|
|
92
|
+
↓
|
|
93
|
+
AuditPoint (outgoing) ← log response if AuditEnabled=TRUE
|
|
94
|
+
↓
|
|
95
|
+
[Output Adapter]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Error path from any point:
|
|
99
|
+
```
|
|
100
|
+
[Any Node] → ErrorHandler → LogError → MQ_Dead_Output_Node / MWBusinessErrorResponse
|
|
101
|
+
```
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# Output Adapters
|
|
2
|
+
|
|
3
|
+
All output adapters live in `Qiwa/Framework/Lib/`. Use them as the exit point of every message flow.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## MQ_Output_Node.subflow
|
|
8
|
+
|
|
9
|
+
**Purpose**: Standard MQ output. Writes message to a target queue.
|
|
10
|
+
|
|
11
|
+
**ESQL module**: `MQ_Output_Node.esql`
|
|
12
|
+
- Copies message headers (`CopyMessageHeaders`)
|
|
13
|
+
- Sets MQ destination queue from `Environment.Destination.MQ.DestinationData.queueName`
|
|
14
|
+
|
|
15
|
+
**When to use**: Standard async MQ output for any request or response message.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## MQ_Dead_Output_Node.subflow
|
|
20
|
+
|
|
21
|
+
**Purpose**: Routes failed/unprocessable messages to a backout/dead-letter queue.
|
|
22
|
+
|
|
23
|
+
**ESQL module**: `MQ_OutputNode_IsDeadFlow.esql`
|
|
24
|
+
|
|
25
|
+
**When to use**: Always wire this as the terminal node on the error path of every MQ flow.
|
|
26
|
+
|
|
27
|
+
**Queue naming**: `<ORIGINAL_QUEUE_NAME>.BACKOUT`
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## MQ_Dynamic_Output_Node.subflow
|
|
32
|
+
|
|
33
|
+
**Purpose**: Selects the target queue at runtime (from message content or environment).
|
|
34
|
+
|
|
35
|
+
**When to use**: Flows where the destination queue varies per message (e.g., routing based on `ServiceCode`).
|
|
36
|
+
|
|
37
|
+
**How it works**: Reads queue name from `Environment.Destination.MQ.DestinationData.queueName` — set this dynamically in your compute ESQL before calling this subflow.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## MQ_ReplyToQ_Node.subflow
|
|
42
|
+
|
|
43
|
+
**Purpose**: Sends response back to the `ReplyToQ` specified in the incoming MQ message header.
|
|
44
|
+
|
|
45
|
+
**When to use**: Synchronous request/reply MQ patterns where the caller specifies a reply-to queue.
|
|
46
|
+
|
|
47
|
+
**How it works**: Uses `InputRoot.MQMD.ReplyToQ` automatically.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## File_Output_Node.subflow
|
|
52
|
+
|
|
53
|
+
**Purpose**: Writes output to the file system.
|
|
54
|
+
|
|
55
|
+
**ESQL helper modules**:
|
|
56
|
+
| Module | Purpose |
|
|
57
|
+
|---|---|
|
|
58
|
+
| `File_Output_Node_PrepareData.esql` | Format data for file output |
|
|
59
|
+
| `File_Output_Node_PrepareAuditData.esql` | Prepare audit record for file operations |
|
|
60
|
+
|
|
61
|
+
**When to use**: File-based output (batch export, file drop for downstream systems).
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## HTTPRequestAdapter.subflow
|
|
66
|
+
|
|
67
|
+
**Purpose**: Makes outbound HTTP/SOAP calls to backend services.
|
|
68
|
+
|
|
69
|
+
**ESQL helper**: `HTTPResponseAdapter_CheckCallType.esql`
|
|
70
|
+
- Determines `INTERNAL` vs `EXTERNAL` call type
|
|
71
|
+
|
|
72
|
+
**When to use**: Any flow that calls an external REST or SOAP service (T24, NIWS, ODM, Unifonic, MLSD, etc.).
|
|
73
|
+
|
|
74
|
+
**Call types**:
|
|
75
|
+
- `INTERNAL`: service-to-service within ACE
|
|
76
|
+
- `EXTERNAL`: calls to backend systems outside ACE
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## HTTPResponseAdapter.subflow
|
|
81
|
+
|
|
82
|
+
**Purpose**: Handles and normalizes HTTP responses from backend calls.
|
|
83
|
+
|
|
84
|
+
**ESQL helper**: `HTTPResponseAdapter_CheckCallType.esql`
|
|
85
|
+
|
|
86
|
+
**When to use**: Always paired with `HTTPRequestAdapter`. Handles both success and fault responses.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## FileCopy.subflow
|
|
91
|
+
|
|
92
|
+
**Purpose**: Copies a file from one location to another within a flow.
|
|
93
|
+
|
|
94
|
+
**When to use**: File routing/archival scenarios.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Output Adapter Selection Guide
|
|
99
|
+
|
|
100
|
+
| Scenario | Use |
|
|
101
|
+
|---|---|
|
|
102
|
+
| Async MQ send | `MQ_Output_Node` |
|
|
103
|
+
| Failed message / error terminal | `MQ_Dead_Output_Node` |
|
|
104
|
+
| Queue chosen at runtime | `MQ_Dynamic_Output_Node` |
|
|
105
|
+
| Sync MQ reply | `MQ_ReplyToQ_Node` |
|
|
106
|
+
| Write to file system | `File_Output_Node` |
|
|
107
|
+
| Call backend HTTP/SOAP service | `HTTPRequestAdapter` + `HTTPResponseAdapter` |
|
|
108
|
+
| Copy file | `FileCopy` |
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## ESQL Copy Utilities (used in all adapters)
|
|
113
|
+
|
|
114
|
+
Every output adapter uses these standard procedures from `copy_Compute.esql`:
|
|
115
|
+
|
|
116
|
+
```esql
|
|
117
|
+
-- Copy all MQ and transport headers
|
|
118
|
+
CALL CopyMessageHeaders();
|
|
119
|
+
|
|
120
|
+
-- Copy entire message tree
|
|
121
|
+
CALL CopyEntireMessage();
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Always call `CopyMessageHeaders()` before modifying output to preserve MQ metadata (MQMD, MQRFH2).
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Property Reader
|
|
2
|
+
|
|
3
|
+
`PropertyReader.subflow` loads external XML configuration into the `Environment.Properties` tree at runtime. It MUST be the first subflow called in every message flow.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Components
|
|
8
|
+
|
|
9
|
+
| Component | Type | Purpose |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| `PropertyReader.subflow` | subflow | Load XML config file into Environment tree |
|
|
12
|
+
| `PropertyReader_LoadProperties.esql` | esql | Parse properties XML and build Environment tree |
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## How It Works
|
|
17
|
+
|
|
18
|
+
1. Reads the XML properties file (e.g., `ACCOUNT-PROPERTIES.xml`)
|
|
19
|
+
2. Parses the hierarchical group structure
|
|
20
|
+
3. Builds the `Environment.Properties` tree matching the XML hierarchy
|
|
21
|
+
4. Substitutes runtime variables: `${broker.name}`, `${execution.group}`, `${flow.name}`, etc.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Accessing Properties in ESQL
|
|
26
|
+
|
|
27
|
+
Properties are accessed via the path:
|
|
28
|
+
```
|
|
29
|
+
Environment.Properties.{ApplicationLabel}.{FlowName}.{Group}.{PropertyName}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Examples:
|
|
33
|
+
```esql
|
|
34
|
+
-- Check if audit is enabled
|
|
35
|
+
Environment.Properties.BS_Account.GetAccountDetails.Logging.AuditEnabled
|
|
36
|
+
|
|
37
|
+
-- Get retry max count
|
|
38
|
+
Environment.Properties.BS_Account.GetAccountDetails.Retry.maxRetryCount
|
|
39
|
+
|
|
40
|
+
-- Get a routing service URL
|
|
41
|
+
Environment.Properties.BS_Account.GetAccountDetails.BankIdForRoutingService.qiwa[1]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Properties File Structure
|
|
47
|
+
|
|
48
|
+
See `config/properties-template.md` for the full XML template.
|
|
49
|
+
|
|
50
|
+
**Key groups** available for every flow:
|
|
51
|
+
|
|
52
|
+
| Group | Properties |
|
|
53
|
+
|---|---|
|
|
54
|
+
| `Logging` | `LogEnabled`, `AuditEnabled`, `MaskingEnabled`, `key1-key10`, `value1-value10`, `maskingIn`, `maskingOut` |
|
|
55
|
+
| `Retry` | `RetryEnabled`, `maxRetryCount`, `minWaitDurationSec` |
|
|
56
|
+
| `Variables` | `callCorrIDOffset` |
|
|
57
|
+
| `SchemaValidation` | `ValidationEnabled` |
|
|
58
|
+
| `Priority` | `Priority` (MQ message priority 0-9) |
|
|
59
|
+
| `BankIdForRoutingService` | Multi-value: bank ID, routing service name, URL |
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Runtime Variable Substitution
|
|
64
|
+
|
|
65
|
+
These tokens in property values are replaced at runtime:
|
|
66
|
+
|
|
67
|
+
| Token | Replaced With |
|
|
68
|
+
|---|---|
|
|
69
|
+
| `${broker.name}` | ACE broker/integration node name |
|
|
70
|
+
| `${execution.group}` | Execution group / integration server name |
|
|
71
|
+
| `${flow.name}` | Message flow name |
|
|
72
|
+
| `${application.name}` | Application name |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## ESQL Node Properties for PropertyReader
|
|
77
|
+
|
|
78
|
+
```esql
|
|
79
|
+
-- Required EXTERNAL declarations in the module using PropertyReader
|
|
80
|
+
DECLARE ApplicationLabel EXTERNAL CHARACTER '';
|
|
81
|
+
DECLARE PropertiesFileName EXTERNAL CHARACTER '';
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Set `ApplicationLabel` and `PropertiesFileName` at the node level in the flow:
|
|
85
|
+
- `ApplicationLabel`: e.g., `BS_Account`
|
|
86
|
+
- `PropertiesFileName`: e.g., `ACCOUNT-PROPERTIES.xml`
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Wiring
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
[Input Node]
|
|
94
|
+
↓
|
|
95
|
+
PropertyReader ← ALWAYS first
|
|
96
|
+
↓
|
|
97
|
+
[rest of flow]
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Never call `AuditPoint`, `RetryPoint`, or any other framework component before `PropertyReader` — they all depend on `Environment.Properties` being populated.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Retry Mechanism
|
|
2
|
+
|
|
3
|
+
The framework provides configurable retry for MQ-based flows using `RetryPoint.subflow`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Components
|
|
8
|
+
|
|
9
|
+
| Component | Type | Purpose |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| `RetryPoint.subflow` | subflow | Re-queue message after failure with delay |
|
|
12
|
+
| `SetRetryProperties.esql` | esql | Set retry tracking headers on MQRFH2 |
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## How It Works
|
|
17
|
+
|
|
18
|
+
1. On failure, message is caught by `ErrorHandler`
|
|
19
|
+
2. `ErrorHandler` checks `RetryEnabled` from Properties
|
|
20
|
+
3. If enabled, routes to `RetryPoint`
|
|
21
|
+
4. `SetRetryProperties.esql` increments retry count in `MQRFH2.usr.retry`
|
|
22
|
+
5. Message is re-queued to `MQRFH2.usr.sourceQueue` after `minWaitDurationSec`
|
|
23
|
+
6. When `maxRetryCount` is reached → route to `MQ_Dead_Output_Node`
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Configuration (Properties XML)
|
|
28
|
+
|
|
29
|
+
Under the `Retry` group for each flow:
|
|
30
|
+
|
|
31
|
+
```xml
|
|
32
|
+
<group name="Retry">
|
|
33
|
+
<property name="RetryEnabled" value="TRUE" />
|
|
34
|
+
<property name="maxRetryCount" value="5" />
|
|
35
|
+
<property name="minWaitDurationSec" value="60" />
|
|
36
|
+
</group>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
| Property | Default | Description |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `RetryEnabled` | `FALSE` | Enable/disable retry |
|
|
42
|
+
| `maxRetryCount` | `5` | Max attempts before dead-lettering |
|
|
43
|
+
| `minWaitDurationSec` | `60` | Seconds to wait before re-queue |
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## MQRFH2 Headers Used
|
|
48
|
+
|
|
49
|
+
| Header | Purpose |
|
|
50
|
+
|---|---|
|
|
51
|
+
| `MQRFH2.usr.retry` | Current retry attempt count |
|
|
52
|
+
| `MQRFH2.usr.sourceQueue` | Original queue to re-queue to |
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## ESQL for Retry Check
|
|
57
|
+
|
|
58
|
+
```esql
|
|
59
|
+
-- Check current retry count
|
|
60
|
+
DECLARE retryCount INT;
|
|
61
|
+
SET retryCount = InputRoot.MQRFH2.usr.retry;
|
|
62
|
+
|
|
63
|
+
-- Get max from properties
|
|
64
|
+
DECLARE maxRetry INT;
|
|
65
|
+
SET maxRetry = Environment.Properties.{AppLabel}.{flowName}.Retry.maxRetryCount;
|
|
66
|
+
|
|
67
|
+
IF retryCount >= maxRetry THEN
|
|
68
|
+
-- route to dead letter
|
|
69
|
+
ELSE
|
|
70
|
+
-- increment and re-queue
|
|
71
|
+
SET OutputRoot.MQRFH2.usr.retry = retryCount + 1;
|
|
72
|
+
END IF;
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Wiring in a Flow
|
|
78
|
+
|
|
79
|
+
Retry is an alternative path to dead-letter on the error route:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
[Failure]
|
|
83
|
+
↓
|
|
84
|
+
ErrorHandler
|
|
85
|
+
↓
|
|
86
|
+
[RetryEnabled=TRUE AND retryCount < maxRetryCount]
|
|
87
|
+
↓
|
|
88
|
+
RetryPoint ← re-queue with delay
|
|
89
|
+
|
|
90
|
+
[RetryEnabled=FALSE OR retryCount >= maxRetryCount]
|
|
91
|
+
↓
|
|
92
|
+
MQ_Dead_Output_Node ← permanent failure
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## When to Enable Retry
|
|
98
|
+
|
|
99
|
+
Enable retry for:
|
|
100
|
+
- Backend service temporarily unavailable
|
|
101
|
+
- Database connectivity issues
|
|
102
|
+
- Transient network failures
|
|
103
|
+
|
|
104
|
+
Do NOT enable retry for:
|
|
105
|
+
- Business validation failures (bad input data won't get better)
|
|
106
|
+
- Schema validation failures
|
|
107
|
+
- Security/authorization errors
|