forked from mulesoft-catalyst/error-handler-plugin
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcommon.dwl
More file actions
122 lines (116 loc) · 5.25 KB
/
Copy pathcommon.dwl
File metadata and controls
122 lines (116 loc) · 5.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
%dw 2.0
/*
NOTICE:
This file must be in the ./resources/<module name> folder in order to be exported in the META-INF/mule-artifact/mule-artifact.json file. This allows the functions to be used in the module as they are executed in the app's context (without the mule message context).
*/
/*
* Get the error type as a String
*/
fun getErrorTypeAsString(errorType) =
if (!isBlank(errorType.namespace))
errorType.namespace ++ ":" ++ (errorType.identifier default "")
else
"UNKNOWN"
/*
* Get the proper error from the merged default and custom error lists. Provide a standard error if none found.
*/
fun getError(errorType, defaultErrors, customErrors = {}) = do {
import mergeWith from dw::core::Objects
var errorList = (defaultErrors mergeWith (customErrors default {}))
var foundError = errorList[errorType]
var error = if ( !isEmpty(foundError) ) foundError else errorList["UNKNOWN"]
---
error
}
/**
* Converts a value to a String representation.
* Binary is converted as-is to Strings since it must be read to get content.
* Primitives are directly converted to Strings.
* Complex objects, like Objects and Arrays, are converted to the String presentation of their Java form.
*
* @p value to convert.
* @p def is the default value if the provided value is empty.
* @r String. If empty, then returns the default value provided
*/
fun toString(value, def="") = do {
var safeValue = if (!isEmpty(value)) value else def default "" // No nulls allowed
---
typeOf(safeValue) match {
case "String" -> safeValue
case "Number" -> safeValue as String
case "Binary" -> read(safeValue, "text/plain")
else -> write(safeValue, "application/java")
}
}
/**
* Extract a downstream API's error message from a Mule Error for APIs that conform to this
* module's response format: { error: { code, reason, message } }. Uses only the public
* Message API (errorMessage.payload); it never accesses internal fields such as `typedValue`,
* which raise an IllegalAccessException under Java 17 module encapsulation (Mule 4.6+).
* Handles composite (childErrors), Until-Successful (suppressedErrors), and standard errors.
* Any extraction failure, such as a non-conforming or malformed body, resolves to null.
*
* @p error the Mule error object.
* @r The first conforming downstream error message (typically a String; may be an Array or
* Object per the response schema), or null when unavailable.
*/
fun getPreviousErrorMessage(error) = do {
var attempt = dw::Runtime::try(() -> do {
fun messagesOf(errors) =
(errors default []) map ((e) -> e.errorMessage.payload.error.message) filter ((m) -> !isEmpty(m))
var candidates =
messagesOf(error.childErrors)
++ messagesOf(error.suppressedErrors)
++ messagesOf([error])
---
(candidates distinctBy $)[0]
})
---
if (attempt.success) attempt.result else null
}
/**
* Extract the entire previous (downstream) error body from a Mule Error as a String, for
* propagating errors whose body does not conform to this module's response format, such as
* SOAP faults, HTML, or third-party JSON. Uses only the public Message API (errorMessage.payload)
* and never internal fields such as `typedValue`, which raise an IllegalAccessException under
* Java 17 module encapsulation (Mule 4.6+). Handles composite (childErrors), Until-Successful
* (suppressedErrors), and standard errors. Text bodies pass through unchanged; structured
* (Object/Array) bodies are serialized as JSON so a JSON downstream body round-trips faithfully
* instead of degrading to a Java-map rendering. Any extraction failure resolves to null.
*
* @p error the Mule error object.
* @r String the previous error body: a single body as-is (text) or as JSON (structured); a
* composite error yields a JSON array of the distinct bodies; null when unavailable.
*/
fun getPreviousError(error) = do {
var attempt = dw::Runtime::try(() -> do {
// Serialize a downstream body faithfully: text and numbers pass through, binary is read
// as text, and structured bodies are written as JSON (not application/java) so a JSON
// body is not degraded to a Java-map rendering.
fun bodyToString(value) =
typeOf(value) match {
case "String" -> value
case "Number" -> value as String
case "Binary" -> read(value, "text/plain")
else -> write(value, "application/json")
}
fun bodiesOf(errors) =
(errors default []) map ((e) -> e.errorMessage.payload) filter ((p) -> !isEmpty(p))
var groups = [
bodiesOf(error.childErrors),
bodiesOf(error.suppressedErrors),
[error.errorMessage.payload] filter ((p) -> !isEmpty(p))
]
var bodies = (groups dw::core::Arrays::firstWith ((group) -> !isEmpty(group))) default []
var distinctBodies = bodies distinctBy $
---
if (isEmpty(distinctBodies))
null
else if (sizeOf(distinctBodies) == 1)
bodyToString(distinctBodies[0])
else
write(distinctBodies, "application/json")
})
---
if (attempt.success) attempt.result else null
}