@sfdxy/mule-lint 1.20.0 → 1.22.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/README.md +63 -17
- package/dist/package.json +1 -1
- package/dist/src/core/XPathHelper.d.ts.map +1 -1
- package/dist/src/core/XPathHelper.js +8 -0
- package/dist/src/core/XPathHelper.js.map +1 -1
- package/dist/src/engine/LintEngine.d.ts +22 -0
- package/dist/src/engine/LintEngine.d.ts.map +1 -1
- package/dist/src/engine/LintEngine.js +105 -18
- package/dist/src/engine/LintEngine.js.map +1 -1
- package/dist/src/mcp/prompts/index.d.ts +1 -1
- package/dist/src/mcp/prompts/index.d.ts.map +1 -1
- package/dist/src/mcp/prompts/index.js +62 -1
- package/dist/src/mcp/prompts/index.js.map +1 -1
- package/dist/src/mcp/resources/index.js +114 -16
- package/dist/src/mcp/resources/index.js.map +1 -1
- package/dist/src/mcp/tools/getRuleDetails.d.ts.map +1 -1
- package/dist/src/mcp/tools/getRuleDetails.js +30 -1
- package/dist/src/mcp/tools/getRuleDetails.js.map +1 -1
- package/dist/src/rules/api-led/ApikitConsoleProductionRule.d.ts +22 -0
- package/dist/src/rules/api-led/ApikitConsoleProductionRule.d.ts.map +1 -0
- package/dist/src/rules/api-led/ApikitConsoleProductionRule.js +43 -0
- package/dist/src/rules/api-led/ApikitConsoleProductionRule.js.map +1 -0
- package/dist/src/rules/api-led/ApikitMainFlowStructureRule.d.ts +24 -0
- package/dist/src/rules/api-led/ApikitMainFlowStructureRule.d.ts.map +1 -0
- package/dist/src/rules/api-led/ApikitMainFlowStructureRule.js +53 -0
- package/dist/src/rules/api-led/ApikitMainFlowStructureRule.js.map +1 -0
- package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.d.ts +25 -0
- package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.d.ts.map +1 -0
- package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.js +59 -0
- package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.js.map +1 -0
- package/dist/src/rules/connector/EventListenerNullGuardRule.d.ts +24 -0
- package/dist/src/rules/connector/EventListenerNullGuardRule.d.ts.map +1 -0
- package/dist/src/rules/connector/EventListenerNullGuardRule.js +58 -0
- package/dist/src/rules/connector/EventListenerNullGuardRule.js.map +1 -0
- package/dist/src/rules/connector/ReplayChannelConfigRule.d.ts +23 -0
- package/dist/src/rules/connector/ReplayChannelConfigRule.d.ts.map +1 -0
- package/dist/src/rules/connector/ReplayChannelConfigRule.js +52 -0
- package/dist/src/rules/connector/ReplayChannelConfigRule.js.map +1 -0
- package/dist/src/rules/dataweave/DataWeaveRules.d.ts +11 -4
- package/dist/src/rules/dataweave/DataWeaveRules.d.ts.map +1 -1
- package/dist/src/rules/dataweave/DataWeaveRules.js +20 -20
- package/dist/src/rules/dataweave/DataWeaveRules.js.map +1 -1
- package/dist/src/rules/dataweave/DuplicateTransformLogicRule.d.ts +25 -0
- package/dist/src/rules/dataweave/DuplicateTransformLogicRule.d.ts.map +1 -0
- package/dist/src/rules/dataweave/DuplicateTransformLogicRule.js +63 -0
- package/dist/src/rules/dataweave/DuplicateTransformLogicRule.js.map +1 -0
- package/dist/src/rules/error-handling/CatchAllLastRule.d.ts +24 -0
- package/dist/src/rules/error-handling/CatchAllLastRule.d.ts.map +1 -0
- package/dist/src/rules/error-handling/CatchAllLastRule.js +65 -0
- package/dist/src/rules/error-handling/CatchAllLastRule.js.map +1 -0
- package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.d.ts +28 -0
- package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.d.ts.map +1 -0
- package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.js +70 -0
- package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.js.map +1 -0
- package/dist/src/rules/error-handling/ErrorResponseStructureRule.d.ts +23 -0
- package/dist/src/rules/error-handling/ErrorResponseStructureRule.d.ts.map +1 -0
- package/dist/src/rules/error-handling/ErrorResponseStructureRule.js +73 -0
- package/dist/src/rules/error-handling/ErrorResponseStructureRule.js.map +1 -0
- package/dist/src/rules/error-handling/GenericErrorRule.d.ts +15 -3
- package/dist/src/rules/error-handling/GenericErrorRule.d.ts.map +1 -1
- package/dist/src/rules/error-handling/GenericErrorRule.js +58 -18
- package/dist/src/rules/error-handling/GenericErrorRule.js.map +1 -1
- package/dist/src/rules/error-handling/GlobalErrorHandlerRule.d.ts +14 -15
- package/dist/src/rules/error-handling/GlobalErrorHandlerRule.d.ts.map +1 -1
- package/dist/src/rules/error-handling/GlobalErrorHandlerRule.js +59 -38
- package/dist/src/rules/error-handling/GlobalErrorHandlerRule.js.map +1 -1
- package/dist/src/rules/error-handling/TryScopeRule.d.ts +5 -0
- package/dist/src/rules/error-handling/TryScopeRule.d.ts.map +1 -1
- package/dist/src/rules/error-handling/TryScopeRule.js +30 -7
- package/dist/src/rules/error-handling/TryScopeRule.js.map +1 -1
- package/dist/src/rules/http/ConnectionIdleTimeoutRule.d.ts +27 -0
- package/dist/src/rules/http/ConnectionIdleTimeoutRule.d.ts.map +1 -0
- package/dist/src/rules/http/ConnectionIdleTimeoutRule.js +46 -0
- package/dist/src/rules/http/ConnectionIdleTimeoutRule.js.map +1 -0
- package/dist/src/rules/index.d.ts +1 -1
- package/dist/src/rules/index.d.ts.map +1 -1
- package/dist/src/rules/index.js +50 -8
- package/dist/src/rules/index.js.map +1 -1
- package/dist/src/rules/logging/LoggerPayloadRule.d.ts +15 -0
- package/dist/src/rules/logging/LoggerPayloadRule.d.ts.map +1 -1
- package/dist/src/rules/logging/LoggerPayloadRule.js +48 -4
- package/dist/src/rules/logging/LoggerPayloadRule.js.map +1 -1
- package/dist/src/rules/operations/FlowRefTargetExistsRule.d.ts +23 -0
- package/dist/src/rules/operations/FlowRefTargetExistsRule.d.ts.map +1 -0
- package/dist/src/rules/operations/FlowRefTargetExistsRule.js +58 -0
- package/dist/src/rules/operations/FlowRefTargetExistsRule.js.map +1 -0
- package/dist/src/rules/operations/UnusedFlowRule.d.ts +20 -0
- package/dist/src/rules/operations/UnusedFlowRule.d.ts.map +1 -1
- package/dist/src/rules/operations/UnusedFlowRule.js +73 -7
- package/dist/src/rules/operations/UnusedFlowRule.js.map +1 -1
- package/dist/src/rules/operations/UnusedVariableRule.d.ts +31 -0
- package/dist/src/rules/operations/UnusedVariableRule.d.ts.map +1 -0
- package/dist/src/rules/operations/UnusedVariableRule.js +103 -0
- package/dist/src/rules/operations/UnusedVariableRule.js.map +1 -0
- package/dist/src/rules/performance/ListenerReconnectForeverRule.d.ts +28 -0
- package/dist/src/rules/performance/ListenerReconnectForeverRule.d.ts.map +1 -0
- package/dist/src/rules/performance/ListenerReconnectForeverRule.js +56 -0
- package/dist/src/rules/performance/ListenerReconnectForeverRule.js.map +1 -0
- package/dist/src/rules/performance/ReconnectionStrategyRule.d.ts +7 -4
- package/dist/src/rules/performance/ReconnectionStrategyRule.d.ts.map +1 -1
- package/dist/src/rules/performance/ReconnectionStrategyRule.js +44 -24
- package/dist/src/rules/performance/ReconnectionStrategyRule.js.map +1 -1
- package/dist/src/rules/security/ConnectorCredentialsSecuredRule.d.ts +36 -0
- package/dist/src/rules/security/ConnectorCredentialsSecuredRule.d.ts.map +1 -0
- package/dist/src/rules/security/ConnectorCredentialsSecuredRule.js +124 -0
- package/dist/src/rules/security/ConnectorCredentialsSecuredRule.js.map +1 -0
- package/dist/src/rules/security/HardcodedCredentialsRule.d.ts +4 -0
- package/dist/src/rules/security/HardcodedCredentialsRule.d.ts.map +1 -1
- package/dist/src/rules/security/HardcodedCredentialsRule.js +15 -0
- package/dist/src/rules/security/HardcodedCredentialsRule.js.map +1 -1
- package/dist/src/rules/security/SecurePropertiesEncryptionRule.d.ts +25 -0
- package/dist/src/rules/security/SecurePropertiesEncryptionRule.d.ts.map +1 -0
- package/dist/src/rules/security/SecurePropertiesEncryptionRule.js +59 -0
- package/dist/src/rules/security/SecurePropertiesEncryptionRule.js.map +1 -0
- package/dist/src/rules/security/SecurePropertiesKeyRule.d.ts +23 -0
- package/dist/src/rules/security/SecurePropertiesKeyRule.d.ts.map +1 -0
- package/dist/src/rules/security/SecurePropertiesKeyRule.js +45 -0
- package/dist/src/rules/security/SecurePropertiesKeyRule.js.map +1 -0
- package/dist/src/rules/security/TlsKeystorePasswordRule.d.ts +25 -0
- package/dist/src/rules/security/TlsKeystorePasswordRule.d.ts.map +1 -0
- package/dist/src/rules/security/TlsKeystorePasswordRule.js +63 -0
- package/dist/src/rules/security/TlsKeystorePasswordRule.js.map +1 -0
- package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.d.ts +26 -0
- package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.d.ts.map +1 -0
- package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.js +61 -0
- package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.js.map +1 -0
- package/dist/src/rules/standards/ConfigPropertiesOrderingRule.d.ts +34 -0
- package/dist/src/rules/standards/ConfigPropertiesOrderingRule.d.ts.map +1 -0
- package/dist/src/rules/standards/ConfigPropertiesOrderingRule.js +76 -0
- package/dist/src/rules/standards/ConfigPropertiesOrderingRule.js.map +1 -0
- package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.d.ts +25 -0
- package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.d.ts.map +1 -0
- package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.js +111 -0
- package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.js.map +1 -0
- package/dist/src/rules/yaml/YamlRules.d.ts +6 -2
- package/dist/src/rules/yaml/YamlRules.d.ts.map +1 -1
- package/dist/src/rules/yaml/YamlRules.js +15 -11
- package/dist/src/rules/yaml/YamlRules.js.map +1 -1
- package/dist/src/types/Rule.d.ts +13 -0
- package/dist/src/types/Rule.d.ts.map +1 -1
- package/docs/README.md +87 -27
- package/docs/best-practices/ci-cd.md +135 -0
- package/docs/best-practices/connector-patterns.md +253 -0
- package/docs/best-practices/dataweave-patterns.md +370 -0
- package/docs/best-practices/deployment-2026.md +171 -0
- package/docs/best-practices/error-handling.md +277 -0
- package/docs/best-practices/event-driven-patterns.md +424 -0
- package/docs/best-practices/logging.md +163 -0
- package/docs/best-practices/mulesoft-best-practices.md +72 -865
- package/docs/best-practices/performance.md +273 -0
- package/docs/best-practices/rules-catalog.md +337 -29
- package/docs/best-practices/security.md +181 -0
- package/docs/best-practices/testing.md +190 -0
- package/docs/best-practices/variable-contracts.md +191 -0
- package/docs/linter/architecture.md +119 -64
- package/package.json +1 -1
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Deployment & Modernization (2026)
|
|
2
|
+
|
|
3
|
+
> **Applies to:** All
|
|
4
|
+
> **Related Rules:** `OPS-001` · `PROJ-001` · `PROJ-002`
|
|
5
|
+
> **Last Updated:** April 2026
|
|
6
|
+
|
|
7
|
+
## When to Read This
|
|
8
|
+
|
|
9
|
+
Read this when planning deployments, migrating to Java 17, adopting CloudHub 2.0, or modernizing tooling.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Development Tooling (2026)
|
|
14
|
+
|
|
15
|
+
### Anypoint Code Builder (ACB)
|
|
16
|
+
|
|
17
|
+
ACB (VS Code-based) is the recommended IDE for 2026+, replacing Anypoint Studio for new projects:
|
|
18
|
+
|
|
19
|
+
- **AI-assisted development** via MuleSoft Vibes
|
|
20
|
+
- **AsyncAPI 2.6 support** for event-driven API design
|
|
21
|
+
- **Native API Governance** validation during design
|
|
22
|
+
- **Integrated Exchange** publishing
|
|
23
|
+
|
|
24
|
+
### MuleSoft CLI Tools
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Lint analysis (CI/CD and local)
|
|
28
|
+
npx @sfdxy/mule-lint . -c .mulelintrc.json -f json
|
|
29
|
+
|
|
30
|
+
# Build + test
|
|
31
|
+
mvn clean test -Dmule.env=dev -Dsecure.key=test
|
|
32
|
+
|
|
33
|
+
# Package
|
|
34
|
+
mvn clean package -DskipTests
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Java 17 Migration
|
|
40
|
+
|
|
41
|
+
Mule 4.9+ **mandates Java 17**. Migration checklist:
|
|
42
|
+
|
|
43
|
+
- [ ] Update `pom.xml` compiler settings and runtime version
|
|
44
|
+
- [ ] Run `jdeps` to identify dependencies on removed Java APIs
|
|
45
|
+
- [ ] Audit connector compatibility (most modern connectors are Java 17 compatible)
|
|
46
|
+
- [ ] Recompile custom connectors and Java modules
|
|
47
|
+
- [ ] Test DataWeave patterns — `DateTime` coercion is stricter in Java 17
|
|
48
|
+
- [ ] Update `log4j2.xml` for Java 17 module system changes
|
|
49
|
+
- [ ] Performance test in staging — JIT compiler and GC behavior differ
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Deployment Models
|
|
54
|
+
|
|
55
|
+
### CloudHub 2.0 (Kubernetes-based)
|
|
56
|
+
|
|
57
|
+
| Feature | CloudHub 1.0 | CloudHub 2.0 |
|
|
58
|
+
| ------------------ | -------------------- | --------------------------------- |
|
|
59
|
+
| **Infrastructure** | VM-based workers | Kubernetes pods |
|
|
60
|
+
| **Scaling** | vCore-based | Pod replicas + HPA |
|
|
61
|
+
| **Networking** | Shared Load Balancer | Ingress / private networking |
|
|
62
|
+
| **Persistence** | Object Store V1 | Object Store V2 (pod-local) |
|
|
63
|
+
| **Monitoring** | Anypoint Monitoring | Anypoint Monitoring + K8s metrics |
|
|
64
|
+
|
|
65
|
+
### Runtime Fabric (RTF)
|
|
66
|
+
|
|
67
|
+
For hybrid or private cloud deployments:
|
|
68
|
+
|
|
69
|
+
- Self-managed Kubernetes clusters
|
|
70
|
+
- Air-gapped environments
|
|
71
|
+
- Regulatory compliance (data residency)
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Environment Promotion
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
Development → QA → Staging → Production
|
|
79
|
+
↓ ↓ ↓ ↓
|
|
80
|
+
dev.yaml qa.yaml stg.yaml prod.yaml
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Deployment Checklist
|
|
84
|
+
|
|
85
|
+
| Item | Description |
|
|
86
|
+
| ------------------------ | ----------------------------- |
|
|
87
|
+
| ✅ All tests pass | MUnit and integration tests |
|
|
88
|
+
| ✅ Lint checks pass | No errors from mule-lint |
|
|
89
|
+
| ✅ Properties configured | Environment YAML verified |
|
|
90
|
+
| ✅ Secrets encrypted | No plaintext credentials |
|
|
91
|
+
| ✅ API Manager policies | Authentication, rate limiting |
|
|
92
|
+
| ✅ Monitoring configured | Dashboards and alerts ready |
|
|
93
|
+
| ✅ Java 17 verified | Runtime compatible |
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## API Governance at Design Time
|
|
98
|
+
|
|
99
|
+
Before publishing to Exchange, validate API specifications against organizational rulesets:
|
|
100
|
+
|
|
101
|
+
1. Define governance rulesets in API Governance
|
|
102
|
+
2. Validate RAML/OAS/AsyncAPI specs during design in ACB
|
|
103
|
+
3. Block publishing to Exchange if governance rules fail
|
|
104
|
+
4. Automate governance checks in CI/CD pipeline
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## API Versioning
|
|
109
|
+
|
|
110
|
+
### URL-Based Versioning (Recommended)
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
/api/v1/orders
|
|
114
|
+
/api/v2/orders
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Deprecation Strategy
|
|
118
|
+
|
|
119
|
+
1. Announce deprecation timeline to consumers
|
|
120
|
+
2. Return `Deprecation` and `Sunset` headers
|
|
121
|
+
3. Monitor v1 vs v2 adoption
|
|
122
|
+
4. Sunset after consumer migration
|
|
123
|
+
|
|
124
|
+
```xml
|
|
125
|
+
<set-variable variableName="outboundHeaders" value="#[{
|
|
126
|
+
'Deprecation': 'true',
|
|
127
|
+
'Sunset': 'Sat, 01 Jan 2027 00:00:00 GMT',
|
|
128
|
+
'Link': '</api/v2/orders>; rel=\"successor-version\"'
|
|
129
|
+
}]"/>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Monitoring & Observability
|
|
135
|
+
|
|
136
|
+
### Three Pillars
|
|
137
|
+
|
|
138
|
+
| Pillar | Tool | Purpose |
|
|
139
|
+
| ----------- | ----------------------------------- | --------------------- |
|
|
140
|
+
| **Logs** | Anypoint Monitoring, Splunk, ELK | Debug, audit trail |
|
|
141
|
+
| **Metrics** | Anypoint Monitoring, Grafana | Performance, health |
|
|
142
|
+
| **Traces** | Anypoint Monitoring, Tracing module | Request flow, latency |
|
|
143
|
+
|
|
144
|
+
### Key Metrics to Monitor
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
Application Health:
|
|
148
|
+
├── Response time (p50, p95, p99)
|
|
149
|
+
├── Error rate (%)
|
|
150
|
+
├── Throughput (requests/sec)
|
|
151
|
+
├── Active connections
|
|
152
|
+
└── Worker CPU/Memory usage
|
|
153
|
+
|
|
154
|
+
Business Metrics:
|
|
155
|
+
├── Records processed per hour
|
|
156
|
+
├── Failed transactions
|
|
157
|
+
├── API calls by consumer
|
|
158
|
+
└── Integration latency by backend
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Alerting
|
|
162
|
+
|
|
163
|
+
| Level | Condition | Response |
|
|
164
|
+
| ------------ | ------------------------------- | ----------------------- |
|
|
165
|
+
| **Critical** | Error rate > 10%, App down | Immediate on-call |
|
|
166
|
+
| **Warning** | Error rate > 5%, Latency > 5s | Investigate within 1h |
|
|
167
|
+
| **Info** | Resource > 70%, unusual pattern | Review in daily standup |
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
**See also:** [CI/CD Integration](ci-cd.md) · [Security](security.md) · [Testing](testing.md)
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# Error Handling Best Practices
|
|
2
|
+
|
|
3
|
+
> **Applies to:** HTTP APIs · Event-Driven · Batch · All
|
|
4
|
+
> **Related Rules:** `MULE-001` · `MULE-003` · `MULE-005` · `MULE-007` · `MULE-009` · `ERR-001` · `ERR-002` · `ERR-003` · `ERR-004`
|
|
5
|
+
> **Last Updated:** April 2026
|
|
6
|
+
|
|
7
|
+
## When to Read This
|
|
8
|
+
|
|
9
|
+
Read this when designing, implementing, or reviewing error handling for any Mule 4 application — whether it exposes an HTTP API, listens to platform events, or processes batch data.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Decision Matrix
|
|
14
|
+
|
|
15
|
+
| Project Type | Error Handler Location | Sets `httpStatus`? | Error Response Format | Correlation ID Source |
|
|
16
|
+
| ------------------------------ | ------------------------------------------------------------ | ------------------------------------------ | ---------------------------------------- | ------------------------------------------------------------- |
|
|
17
|
+
| **HTTP API (SAPI/Experience)** | Dedicated `error-handling.xml` or `global-error-handler.xml` | ✅ Yes — sets `httpStatus` in every branch | JSON error envelope → HTTP response | `attributes.headers.'x-correlation-id' default correlationId` |
|
|
18
|
+
| **Event-Driven (PAPI)** | Part of `error-handling.xml` | ❌ No — no HTTP response layer | Error payload → writeback + notification | Platform Event `EventUuid` |
|
|
19
|
+
| **Batch / Scheduler** | Inline or referenced `error-handler` | Depends on trigger | Logged error + retry/dead-letter | Generated UUID or scheduler ID |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Key Principles
|
|
24
|
+
|
|
25
|
+
1. **Every flow needs error handling** — either an explicit `<error-handler>` or a `ref` to a global one
|
|
26
|
+
2. **Set HTTP status codes** — always set `httpStatus` variable for API responses (HTTP APIs only)
|
|
27
|
+
3. **Include correlation ID** — enable distributed tracing across all API layers
|
|
28
|
+
4. **Be specific about error types** — avoid catching `type="ANY"` except as the **last** handler in the chain
|
|
29
|
+
5. **Consistent error envelope** — use the same response shape for all error types
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Patterns
|
|
34
|
+
|
|
35
|
+
### Pattern 1: Global Error Handler (HTTP APIs)
|
|
36
|
+
|
|
37
|
+
**Use when:** building any HTTP-facing API (System API, Experience API, or APIKit-based Process API).
|
|
38
|
+
|
|
39
|
+
Every error branch should:
|
|
40
|
+
|
|
41
|
+
- Set `httpStatus` via `ee:set-variable`
|
|
42
|
+
- Build a JSON error response with `environment`, `correlationId`, `error`, and `message`
|
|
43
|
+
- Place `type="ANY"` as the **last** branch (catch-all)
|
|
44
|
+
|
|
45
|
+
```xml
|
|
46
|
+
<!-- src/main/mule/common/error-handling.xml -->
|
|
47
|
+
<error-handler name="global-error-handler">
|
|
48
|
+
|
|
49
|
+
<!-- 400 Bad Request -->
|
|
50
|
+
<on-error-propagate type="APIKIT:BAD_REQUEST">
|
|
51
|
+
<ee:transform>
|
|
52
|
+
<ee:message>
|
|
53
|
+
<ee:set-payload><![CDATA[%dw 2.0
|
|
54
|
+
output application/json
|
|
55
|
+
---
|
|
56
|
+
{
|
|
57
|
+
environment: p('mule.env'),
|
|
58
|
+
correlationId: (vars.correlationId default "") as String,
|
|
59
|
+
error: "InvalidInput",
|
|
60
|
+
message: error.detailedDescription default "Bad request"
|
|
61
|
+
}]]></ee:set-payload>
|
|
62
|
+
</ee:message>
|
|
63
|
+
<ee:variables>
|
|
64
|
+
<ee:set-variable variableName="httpStatus">400</ee:set-variable>
|
|
65
|
+
</ee:variables>
|
|
66
|
+
</ee:transform>
|
|
67
|
+
</on-error-propagate>
|
|
68
|
+
|
|
69
|
+
<!-- 404 Not Found -->
|
|
70
|
+
<on-error-propagate type="APIKIT:NOT_FOUND">
|
|
71
|
+
<!-- ... set httpStatus to 404, build response ... -->
|
|
72
|
+
</on-error-propagate>
|
|
73
|
+
|
|
74
|
+
<!-- 500 Internal Server Error (catch-all — MUST be last) -->
|
|
75
|
+
<on-error-propagate type="ANY" enableNotifications="true" logException="true">
|
|
76
|
+
<ee:transform>
|
|
77
|
+
<ee:message>
|
|
78
|
+
<ee:set-payload><![CDATA[%dw 2.0
|
|
79
|
+
output application/json
|
|
80
|
+
---
|
|
81
|
+
{
|
|
82
|
+
environment: p('mule.env'),
|
|
83
|
+
correlationId: (vars.correlationId default "") as String,
|
|
84
|
+
error: "InternalError",
|
|
85
|
+
message: error.detailedDescription default "An unexpected error occurred."
|
|
86
|
+
}]]></ee:set-payload>
|
|
87
|
+
</ee:message>
|
|
88
|
+
<ee:variables>
|
|
89
|
+
<ee:set-variable variableName="httpStatus">500</ee:set-variable>
|
|
90
|
+
</ee:variables>
|
|
91
|
+
</ee:transform>
|
|
92
|
+
</on-error-propagate>
|
|
93
|
+
|
|
94
|
+
</error-handler>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Reference it from the main API flow:
|
|
98
|
+
|
|
99
|
+
```xml
|
|
100
|
+
<flow name="api-main">
|
|
101
|
+
<http:listener config-ref="httpListenerConfig" path="/api/*">
|
|
102
|
+
<http:response statusCode="#[vars.httpStatus default 200]"/>
|
|
103
|
+
<http:error-response statusCode="#[vars.httpStatus default 500]">
|
|
104
|
+
<http:body><![CDATA[#[payload]]]></http:body>
|
|
105
|
+
</http:error-response>
|
|
106
|
+
</http:listener>
|
|
107
|
+
<apikit:router config-ref="api-config"/>
|
|
108
|
+
<error-handler ref="global-error-handler"/>
|
|
109
|
+
</flow>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Pattern 2: Error Handler (Event-Driven)
|
|
113
|
+
|
|
114
|
+
**Use when:** building a process API driven by Salesforce Platform Events, Anypoint MQ, or Kafka.
|
|
115
|
+
|
|
116
|
+
No `httpStatus`. Instead, errors trigger:
|
|
117
|
+
|
|
118
|
+
1. Structured error payload build
|
|
119
|
+
2. Writeback to source system (e.g., SF error field update)
|
|
120
|
+
3. Notification dispatch (email, Slack, NetSuite error log)
|
|
121
|
+
|
|
122
|
+
```xml
|
|
123
|
+
<error-handler name="global-error-handler">
|
|
124
|
+
<on-error-propagate enableNotifications="true" logException="true">
|
|
125
|
+
<!-- Build structured error payload -->
|
|
126
|
+
<ee:transform>
|
|
127
|
+
<ee:variables>
|
|
128
|
+
<ee:set-variable variableName="errorPayload"
|
|
129
|
+
resource="dwl/transforms/error-payload.dwl"/>
|
|
130
|
+
</ee:variables>
|
|
131
|
+
</ee:transform>
|
|
132
|
+
<!-- Log the error -->
|
|
133
|
+
<logger level="ERROR" message="#[vars.errorPayload]"
|
|
134
|
+
category="#[vars.logCategory default 'com.myorg.papi']"/>
|
|
135
|
+
<!-- Writeback error status to source system -->
|
|
136
|
+
<flow-ref name="sf-writeback-subflow"/>
|
|
137
|
+
<!-- Dispatch notifications -->
|
|
138
|
+
<flow-ref name="notification-router-subflow"/>
|
|
139
|
+
</on-error-propagate>
|
|
140
|
+
</error-handler>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Pattern 3: Try Scope for Risky Operations
|
|
144
|
+
|
|
145
|
+
**Use when:** a flow makes 2+ external calls (HTTP requests, DB operations, connector calls).
|
|
146
|
+
|
|
147
|
+
```xml
|
|
148
|
+
<!-- ❌ Bad — multiple calls without isolation -->
|
|
149
|
+
<flow name="process-order-flow">
|
|
150
|
+
<http:request config-ref="API"/>
|
|
151
|
+
<db:insert config-ref="Database"/>
|
|
152
|
+
</flow>
|
|
153
|
+
|
|
154
|
+
<!-- ✅ Good — each risky operation isolated -->
|
|
155
|
+
<flow name="process-order-flow">
|
|
156
|
+
<try>
|
|
157
|
+
<http:request config-ref="API"/>
|
|
158
|
+
<error-handler>
|
|
159
|
+
<on-error-propagate type="HTTP:CONNECTIVITY">
|
|
160
|
+
<logger category="com.myorg" level="ERROR"
|
|
161
|
+
message="#['API call failed: ' ++ error.description]"/>
|
|
162
|
+
</on-error-propagate>
|
|
163
|
+
</error-handler>
|
|
164
|
+
</try>
|
|
165
|
+
<try>
|
|
166
|
+
<db:insert config-ref="Database"/>
|
|
167
|
+
<error-handler>...</error-handler>
|
|
168
|
+
</try>
|
|
169
|
+
</flow>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Pattern 4: Centralized Error Log Object (CRM Writeback)
|
|
173
|
+
|
|
174
|
+
**Use when:** integration errors need visibility in the CRM for operations teams (multi-system integrations where business users manage error resolution).
|
|
175
|
+
|
|
176
|
+
**Do NOT use when:** it's an internal-only SAPI where standard logging dashboards suffice, or for transient errors that will auto-recover via retry.
|
|
177
|
+
|
|
178
|
+
| Scenario | CRM Error Log? | Why |
|
|
179
|
+
| ---------------------------------------- | -------------- | ----------------------------------------------- |
|
|
180
|
+
| Multi-system sync (CRM ↔ ERP ↔ Payments) | ✅ | Ops needs single-pane visibility |
|
|
181
|
+
| Internal SAPI with no business users | ❌ | Logging + dashboards sufficient |
|
|
182
|
+
| Transient error (retry will succeed) | ❌ | Handle with retry, not logging |
|
|
183
|
+
| Real-time latency-sensitive flow | ⚠️ | Extra HTTP call per error; make async if needed |
|
|
184
|
+
|
|
185
|
+
**Standardized error payload contract:**
|
|
186
|
+
|
|
187
|
+
```xml
|
|
188
|
+
<!-- Every caller builds this shape before calling errorLogFlow -->
|
|
189
|
+
<ee:transform doc:name="Error Payload">
|
|
190
|
+
<ee:set-payload><![CDATA[%dw 2.0
|
|
191
|
+
output application/json
|
|
192
|
+
---
|
|
193
|
+
{
|
|
194
|
+
"Subject": "Failed to sync Invoice to ERP",
|
|
195
|
+
"Error": error.detailedDescription default "",
|
|
196
|
+
"Link": p('links.crm.record') ++ vars.recordId ++ "/view",
|
|
197
|
+
"RecordId": vars.recordId default ""
|
|
198
|
+
}]]></ee:set-payload>
|
|
199
|
+
</ee:transform>
|
|
200
|
+
<flow-ref name="errorLogFlow"/>
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
**The error log flow — with self-healing handler:**
|
|
204
|
+
|
|
205
|
+
```xml
|
|
206
|
+
<flow name="errorLogFlow">
|
|
207
|
+
<ee:transform doc:name="Map to CRM Error Object">
|
|
208
|
+
<ee:set-payload><![CDATA[%dw 2.0
|
|
209
|
+
output application/json
|
|
210
|
+
---
|
|
211
|
+
{
|
|
212
|
+
"Application__c": "Mulesoft",
|
|
213
|
+
"Type__c": "Integration",
|
|
214
|
+
"Stacktrace__c": payload.Error default "",
|
|
215
|
+
"Record_Link__c": payload.Link default "",
|
|
216
|
+
"Record_Id__c": payload.RecordId default "",
|
|
217
|
+
"Subject__c": payload.Subject default ""
|
|
218
|
+
}]]></ee:set-payload>
|
|
219
|
+
</ee:transform>
|
|
220
|
+
|
|
221
|
+
<http:request method="POST" config-ref="SAPI_Config" path="/Error_Log__c"/>
|
|
222
|
+
|
|
223
|
+
<error-handler>
|
|
224
|
+
<!-- CRITICAL: Must NEVER throw — prevents infinite loop -->
|
|
225
|
+
<on-error-continue enableNotifications="true" logException="false">
|
|
226
|
+
<logger level="WARN"
|
|
227
|
+
message="Error logging failed: #[error.detailedDescription]"/>
|
|
228
|
+
</on-error-continue>
|
|
229
|
+
</error-handler>
|
|
230
|
+
</flow>
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
> ⚠️ **Self-healing rule:** The `errorLogFlow` **must never propagate an error**. If it does, the parent flow's error handler re-enters the error log → infinite loop. Always use `on-error-continue`.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Connector-Specific Error Types
|
|
238
|
+
|
|
239
|
+
### Salesforce Connector (11.3.0+)
|
|
240
|
+
|
|
241
|
+
| Error Type | HTTP Status | Description |
|
|
242
|
+
| ------------------------------------- | ----------- | ---------------------------- |
|
|
243
|
+
| `SALESFORCE:CONNECTIVITY` | 502 | Connection failure to SF org |
|
|
244
|
+
| `SALESFORCE:INVALID_INPUT` | 400 | DML/SOQL validation error |
|
|
245
|
+
| `SALESFORCE:INVALID_RESPONSE` | 400 | Unparseable SF response |
|
|
246
|
+
| `SALESFORCE:FAULTY_RESPONSE` | 400 | SF returned error body |
|
|
247
|
+
| `SALESFORCE:NOT_FOUND` | 404 | Record not found |
|
|
248
|
+
| `SALESFORCE:TIMEOUT` | 504 | Connector timed out |
|
|
249
|
+
| `SALESFORCE:LIMIT_EXCEEDED` | 429 | API governor limit hit |
|
|
250
|
+
| `SALESFORCE:INSUFFICIENT_PERMISSIONS` | 403 | Permission denied |
|
|
251
|
+
|
|
252
|
+
### APIKit Error Types
|
|
253
|
+
|
|
254
|
+
| Error Type | HTTP Status | Description |
|
|
255
|
+
| ------------------------------- | ----------- | --------------------------- |
|
|
256
|
+
| `APIKIT:BAD_REQUEST` | 400 | Schema validation failure |
|
|
257
|
+
| `APIKIT:NOT_FOUND` | 404 | Unknown URI path |
|
|
258
|
+
| `APIKIT:METHOD_NOT_ALLOWED` | 405 | HTTP verb not in RAML |
|
|
259
|
+
| `APIKIT:NOT_ACCEPTABLE` | 406 | Content negotiation failure |
|
|
260
|
+
| `APIKIT:UNSUPPORTED_MEDIA_TYPE` | 415 | Wrong Content-Type |
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Checklist
|
|
265
|
+
|
|
266
|
+
- [ ] Global error handler defined in a dedicated XML file
|
|
267
|
+
- [ ] Every flow has `<error-handler ref="global-error-handler"/>` or explicit handler
|
|
268
|
+
- [ ] `httpStatus` set in every error branch (HTTP APIs only)
|
|
269
|
+
- [ ] `correlationId` included in every error response
|
|
270
|
+
- [ ] `type="ANY"` is the **last** handler in the chain
|
|
271
|
+
- [ ] Connector-specific error types handled before generic ones
|
|
272
|
+
- [ ] Error response shape is consistent across all branches
|
|
273
|
+
- [ ] Error log flow uses `on-error-continue` — never cascades (Pattern 4)
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
**See also:** [Variable Contracts](variable-contracts.md) · [Logging](logging.md) · [Rules Catalog](rules-catalog.md)
|