@@ -3,17 +3,40 @@ The implementation of an **_External Task_** is done by a _**Worker**_.
3
3
4
4
So for each _ External Task_ type we have a DSL for an according _ Worker_ .
5
5
6
+ @: callout (info)
7
+ In the future, it is possible to have more than the Worker types, that are described here.
8
+ @:@
9
+
10
+ ## General
11
+ Let's start with functions that are provided for all Workers.
12
+
13
+ ### validate
14
+ In every _ Worker_ , the input ` In ` is validated automatically (it is decoded from JSON to a ` In ` object).
15
+ However, you can override the ` validate ` method to add more sophisticated validation logic.
16
+
17
+ Example:
18
+ ``` scala
19
+ override def validate (in : In ): Either [ValidatorError , In ] =
20
+ for
21
+ _ <- Try (in.accountTypeFilterAsSeq).toEither.left.map: _ =>
22
+ ValidatorError (
23
+ " accountTypeFilter must be a single Int or a comma separated String of Ints"
24
+ )
25
+ // _ <- moreValidation(in)
26
+ yield in
27
+ ```
28
+
6
29
## Custom Worker
7
30
The _ Custom Worker_ is a general _ Worker_ that can used for any business logic or integration.
8
31
9
- It automatically does:
10
- - validate the input variables
11
-
12
32
You can create:
13
33
- business logic that can't be handled by the expression language in the BPMN itself
34
+ - complex mappings
14
35
- a service integration that is not covered by the _ Service Worker_
15
36
- whatever you want
16
37
38
+ Use this [ Generator] ( ../development/projectDev.md#customtask ) to create a new _ Custom Worker_
39
+
17
40
``` scala
18
41
import mycompany .myproject .bpmn .myprocess .v1 .MyCustomTask .*
19
42
@@ -25,25 +48,25 @@ class MyCustomTaskWorker extends CompanyCustomWorkerDsl[In, Out]:
25
48
def runWork (in : In ): Either [CamundalaWorkerError .CustomError , Out ] =
26
49
// your business logic
27
50
???
28
- override def validate (in : In ): Either [CamundalaWorkerError .ValidatorError , In ] =
29
- ??? // custom validation logic here
30
51
```
31
- - ` lazy val customTask ` is just needed for the compiler to check the correctness of the types.
52
+ - ` lazy val customTask ` is just needed for the compiler to check the correctness of the types ( _ Prototype _ pattern) .
32
53
- ` runWork ` is the method that is called by the _ Worker_ to execute the business logic.
33
54
- The code can either:
34
55
- complete the task successfully with a result -> ` Right[Out] `
35
56
- fail the task with an error -> ` Left[CamundalaWorkerError.CustomError] `
36
- - ` override def validate(in: In) ` is optional and can be used to add more sophisticated validation logic.
37
- If the validation fails, the process will fail.
38
57
39
- Examples:
40
-
41
- ### runWork
42
- TODO
43
- ### validate
44
- This is the same in every worker type.
45
- TODO
58
+ Example:
46
59
60
+ ``` scala
61
+ def runWork (in : In ): Either [CamundalaWorkerError .CustomError , Out ] =
62
+ doSomethingThatCanFail(in)
63
+ .left.map: e =>
64
+ CamundalaWorkerError .CustomError (" Problem in Worker: " + e.getMessage)
65
+
66
+ private def doSomethingThatCanFail (in : In ): Either [Throwable , In ] = ???
67
+ ```
68
+ ` doSomethingThatCanFail ` does some mapping or business logic that can fail.
69
+ If it fails, it returns a ` Left ` with an error message, that you wrap with a _ CamundalaWorkerError.CustomError_ .
47
70
48
71
## Init Process Worker
49
72
The _ Init Process Worker_ is a special _ Worker_ that is used to start a process.
@@ -57,8 +80,6 @@ You can:
57
80
- init process variables used to control the process flow,
58
81
like counters, variables that may not be on the process.
59
82
- create simplified process variables to simplify the process flow.
60
- - validate the input variables, if you need more sophisticated validation logic,
61
- than you can do with the type definition.
62
83
63
84
``` scala
64
85
import mycompany .myproject .bpmn .myprocess .v1 .MyProcess .*
@@ -70,27 +91,29 @@ class MyProcessWorker extends CompanyInitWorkerDsl[In, Out, InitIn, InConfig]:
70
91
71
92
def customInit (in : In ): InitIn =
72
93
??? // init logic here
73
- override def validate (in : In ): Either [CamundalaWorkerError .ValidatorError , In ] =
74
- ??? // custom validation logic here
75
94
```
76
95
- ` lazy val inOutExample ` is just needed for the compiler to check the correctness of the types.
77
96
- ` customInit ` is the method that is called by the _ Worker_ to execute the init logic.
78
97
- The method sets the process variables according the _ InitIn_ object.
79
98
Be aware that this can not fail, as the input variables are already validated.
80
- - ` override def validate(in: In) ` is optional and can be used to add more sophisticated validation logic.
81
- If the validation fails, the process will fail.
82
99
83
100
Examples:
84
101
85
102
### customInit
86
- TODO
103
+
104
+ ``` scala
105
+ def customInit (in : In ): InitIn =
106
+ InitIn (
107
+ currency = in.currency.getOrElse(Currency .EUR ), // set optional value with default value
108
+ requestCounter = 0 , // init process variables used to control the process flow
109
+ iban = in.person.iban, // simplify process variables
110
+ // ...
111
+ )
112
+ ```
87
113
88
114
## Service Worker
89
115
The _ Service Worker_ is a special _ Worker_ that is used to call a REST API service.
90
116
91
- It automatically does:
92
- - validate the input variables
93
-
94
117
You can provide:
95
118
- the method and the path of the service
96
119
- the query parameters
@@ -106,9 +129,9 @@ class MyServiceTaskWorker extends CompanyServiceWorkerDsl[In, Out]:
106
129
lazy val serviceTask = example
107
130
108
131
def apiUri (in : In ) = uri " $serviceBasePath/myService "
109
- override protected lazy val method : Method = Method .POST
132
+ override lazy val method : Method = Method .POST
110
133
111
- override protected def inputHeaders (in : In ): Map [String , String ] =
134
+ override def inputHeaders (in : In ): Map [String , String ] =
112
135
??? // map the input variables to the headers
113
136
override def querySegments (in : In ) =
114
137
??? // map the input variables to the query parameters
@@ -119,8 +142,6 @@ class MyServiceTaskWorker extends CompanyServiceWorkerDsl[In, Out]:
119
142
in : In
120
143
): Either [ServiceMappingError , Out ] =
121
144
??? // map the service response body and header to the output variables
122
- override def validate (in : In ): Either [CamundalaWorkerError .ValidatorError , In ] =
123
- ??? // custom validation logic here
124
145
```
125
146
- ` lazy val serviceTask ` is just needed for the compiler to check the correctness of the types.
126
147
- ` def apiUri(in: In) ` the path of the service, with the path parameters from the ` in ` object.
@@ -130,17 +151,97 @@ class MyServiceTaskWorker extends CompanyServiceWorkerDsl[In, Out]:
130
151
- ` override def inputHeaders(in: In) ` is optional and can be used to add headers to the request.
131
152
- ` override def inputMapper(in: In) ` is optional and can be used to map the input variables to the request body.
132
153
- ` override def outputMapper(out: ServiceResponse[ServiceOut], in: In) ` is optional and can be used to map the response body and -headers to the output variables.
133
- - ` override def validate(in: In) ` is optional and can be used to add more sophisticated validation logic.
134
- If the validation fails, the process will fail.
135
154
136
155
Examples:
137
156
138
157
### apiUri
139
- TODO
140
- ### querySegments
141
- TODO
158
+ ``` scala
159
+ def apiUri (in : In ) = uri " $serviceBasePath/myService/account/ ${in.accountId}"
160
+ ```
161
+ The only required function. It returns the path of the service, with the path parameters from the ` in ` object.
162
+
163
+ ### method
164
+ ``` scala
165
+ override lazy val method : Method = Method .POST
166
+ ```
167
+ Override the HTTP method. Default is ` Method.GET ` .
168
+
142
169
### inputHeaders
143
- TODO
170
+ ``` scala
171
+ override def inputHeaders (in : In ): Map [String , String ] =
172
+ Map (" Correlation-ID" -> in.userId)
173
+ ```
174
+
175
+ ### querySegments
176
+ We support three ways to provide query parameters:
177
+
178
+ #### queryKeys
179
+ ``` scala
180
+ override def querySegments (in : In ) =
181
+ queryKeys(" limitSelection" , " accountType" )
182
+ ```
183
+ A list of optional ` In ` fields that are mapped to query parameters.
184
+ So in this example you need to have ` limitSelection ` and ` accountType ` in your ` In ` object.
185
+ ``` scala
186
+ case class In (limitSelection : Option [Int ], accountType : Option [String ])
187
+ ```
188
+
189
+ #### queryKeyValues
190
+ ``` scala
191
+ override def querySegments (in : In ) =
192
+ queryKeyValues(
193
+ " limitSelection" -> in.limitSelection,
194
+ " accountType" -> adjust(in.accountType)
195
+ )
196
+ ```
197
+ If you need to adjust an ` In ` value, you can use this way of explicit listing the key-value pairs.
198
+
199
+ #### queryValues
200
+ ``` scala
201
+ override def querySegments (in : In ) =
202
+ queryValues(
203
+ s " eq(username,string: ${in.user}) "
204
+ )
205
+ ```
206
+ If you have a query language, you can use this way to provide the query parameters.
207
+
208
+ #### a combination of the above
209
+ ``` scala
210
+ override def querySegments (in : In ) =
211
+ queryKeys(" limitSelection" ) ++
212
+ queryKeyValues(" accountType" -> adjust(in.accountType))
213
+ ```
214
+ And you can combine them as you like.
215
+
144
216
### inputMapper
145
- TODO
217
+ ``` scala
218
+ override def inputMapper (in : In ): Option [ServiceIn ] =
219
+ Some (ServiceIn (in.accountType, in.accountId))
220
+ ```
221
+ Mapping the input variables to the request body.
222
+
146
223
### outputMapper
224
+
225
+ ``` scala
226
+ override def outputMapper (
227
+ out : ServiceResponse [ServiceOut ],
228
+ in : In
229
+ ): Either [ServiceMappingError , Out ] =
230
+ out.outputBody
231
+ .collect:
232
+ case b if b.nonEmpty =>
233
+ Right (Out (
234
+ creditCardDetail = b.head,
235
+ creditCardDetails = b
236
+ ))
237
+ .getOrElse(Left (ServiceMappingError (" There is at least one CreditCardDetail expected." )))
238
+ ```
239
+
240
+ Mapping the response body and -headers to the output variables.
241
+
242
+ @: callout (info)
243
+ As you can see there are only two methods that can fail:
244
+ - ` validate ` -> For the input, use this methode to validate the input and return any possible error.
245
+ - ` outputMapper ` -> For the output, we do not have an extra 'validate' method.
246
+ So if the service response is not as expected, you can return an error here.
247
+ @:@
0 commit comments