-
Notifications
You must be signed in to change notification settings - Fork 12
Stub Configuration
The most important part of the Stub part is its configuration. When the approach is designed some key points were considered:
- It must be usable for any kind of SW development project that needs a stub solution. Therefore it must be independent from the projects.
- It must be flexible enough to be extended by testers/developers if project specific things should be added.
- It must be easy to implement and use
- It must be easy to change the configuration on the fly (during run-time), even for temporary configs.
A JSON based approach was selected, the JSON schema file is available here.
Main objects: wilmaStubConfiguration, dialogDescriptors and templates
{
"wilmaStubConfiguration": {
"dialogDescriptors": [
{
"name": ...,
"usage": ...,
"comment": ....,
"conditionDescriptor": ...,
"responseDescriptor": ...
}
],
"templates": [
{
"name": ...,
"type": ...,
"resource": ...
}
],
"groupName": ...,
"active": ...,
"sequenceDescriptors": ...,
"interceptors": ...,
"conditionSets": ...,
"responseFormatterSets": ...
}
}
Object: dialogDescriptors
The stub configuration contains an array of dialogDescriptors that describes one or more request-response pair(s) - with what response the stub should answer in case of a specific request.
Its name is mandatory, should be meaningful and unique.
usage is optional.
- "always" - Means this dialog descriptor is valid when Wilma is running. This is the default value.
- "timeout" - Means that when the specific dialogDescriptor object appears, after a timeout (specified in minutes in validityValue), the dialogDescriptor will be disabled
- "hitCount" - Means that after this dialogDescriptor has been applied for N times (defined in validityValue), the dialogDescriptor will be disabled
- "disabled" - Means that this dialogDescriptor is not in use.
The comment object is optional, may be used to describe the purpose of the dialogDescriptor (like: "This req-resp pair is to test bad response from X service, when xxx attribute is missing, however should not.")
On-the-fly behavior: wilmaStubConfiguration can be added / removed on-the-fly by using Wilma admin pages. When an object become disabled and that object was not originally in the starting Wilma-stub, the object itself should be deleted as well from the active structure.
The dialogDescriptor contains two more mandatory fields: a conditionDescriptor and a responseDescriptor object.
Object: conditionDescriptor
This object describes a complex condition which should be evaluated by the switch engine (= part of Wilma that decides between proxying the request or generating a stub response).
method: ResponseDescriptor evaluateCondition(DialogDescriptor, RequestMessage)
, -> evaluates the ConditionDescriptor part and returns with the ResponseDescriptor class this condition matched, or NULL in case condition failed.
When has value -> Stub shall be activated with the ResponseDescriptor info.
When has no value (NULL) -> goes to next DialogDescriptor, or if no such left -> proxy mode is used
Its definition is the following:
"conditionDescriptorDefinition": {
"description": "Describes a complex condition which should be evaluated by the switch engine",
"type": "object",
"oneOf": [
{
"$ref": "#/definitions/conditionDefinition"
},
{
"$ref": "#/definitions/conditionSetInvokerDefinition"
},
{
"$ref": "#/definitions/logicalConditionDefinition"
}
]
}
from where
-
conditionDefinition
represents a single condition that should be evaluated, and its result is a boolean value. -
conditionSetInvokerDefinition
represents a set of conditions, and -
logicalConditionDefinition
represents a logical association of the condition(s) and a conditionDescriptor must contain exactly one of the objects above.
Object: condition This object describes a single condition that should be evaluated, its result is a boolean value.
In real life it looks like:
"condition": {
"class": ...,
"negate": ...,
"parameters": [
{
"name": ...,
"value": ...
}
]
}
Where
-
"class"
is the used class that describes the type of the check. See details below and Built-in condition checker classes page to get further information about built-in condition checkers usage. -
"negate"
=false|true - optional, if it is true then negates the final result of the condition, default=false -
"parameters"
array is optional and should contain as many"name"
/"value"
pairs as expected by the specified class. The value of these objects are always strings.
Notes on "class"
object:
If the class is not a built-in one, then the class should be loaded dynamically and its checker method should be called.
Used interface: boolean conditionEvaluator(RequestMessage, negate, parameters[])
In case a custom class is in use, it is loaded at the evaluation of the configuration JSON itself, not later.
Object: logicalCondition
logicalCondition
can be: "and": [object array]
, "or": [object array]
, "not": object
: logical OR or AND between its object values or NOT (negate) the object value. An object(s) can be can be logicalCondition(s) and/or condition(s) and/or conditionSetInvoker(s).
Example:
"and": [
{"condition": { "class": "com.epam.wilma.stubconfig.condition.checker.general.header.PostMethodChecker" }},
{"condition": {
"class": "JsonPathChecker",
"parameters": [ { "name": "jsonPath", "value": "$.paymentType" }, { "name": "expected", "value": "CASH" } ]
}}
]
Object: conditionSetInvoker
"conditionSetInvoker": ...
refers to the name of a conditionSet - and just evaluates the given conditionSet.
Please note, that by referring to itself (the specific consitionSet may conatin a reference to itself), an endless loop can be configured -> this is checked and forbidden by Wilma
Object: responseDescriptor
This object describes what answer should be sent back, and in case a template is used, what method should be used to make it up-to-date.
"responseDescriptor": {
"code": ...,
"delay": ...,
"mimeType": ...,
"templateName": "template 1 - errorResponse",
"responseFormatterSet": ...
}
Its code is optional, defines the response code. Default value is 200 (here E500 and others can be specified).
The delay is optional too, its default value is 0, defines the delay of the response in milliseconds, 0 means no delay.
The mimeType is mandatory, declares the mime type (content type) of the response. Possible values are: text/plain
, text/html
, text/xml
, application/xml
, application/soap+xml
, application/json
.
The templateName is mandatory, reference to the name of the template
object used as starting point to formulate the answer.
The responseFormatterSet is optional, it is used to formulate the response, based on the specified template.
Object: responseFormatterSet
This object is an array and contains one or more objects of responseFormatter
and responseFormatterSetInvoker
.
The responseFormatter
and responseFormatterSetInvoker
objects in responseFormatterSet
array can be mixed, but are called in order, from top to bottom.
Object: responseFormatter
This object has a mandatory class
and an optional parameters
field.
The "class"
defines the method that formats the response. It can be external class too, by calling byte[] formatResponse(WilmaHttpRequest, HttpServletResponse, responseResource, parameters)
method
See Response Formatters page to get further information about response formatters usage.
The "parameters"
part is an optional array, and contains as many "name"
and "value"
object pairs as necessary for the class to work on the response.
Object: responseFormatterSetInvoker
"responseFormatterSetInvoker": ...
refers to the name of a responseFormatterSet and just evaluates the given responseFormatterSet.
Please note, that by referring to itself (the specific responseFormatterSet may conatin a reference to itself), an endless loop can be configured -> this is checked and forbidden by Wilma
Object: template
This objectdescribes a template and how it should be handled when it is used as response. This object may appear in the templates
array only.
{
"name": ...,
"type": ...,
"resource": ...
}
name
is a unique name of the template
type
is the type of the template resource, that can be one of the followings: "xml"
, "text"
, "html"
, "json"
, "xmlFile"
, "textFile"
, "htmlFile"
, "jsonFile"
and "external"
.
resource
describes the resource based on its type
: When a simple type is given, the resource itself is embedded into the "resource"
field. When "...File" is given, the "resource"
field contains the filename to be loaded as resource and when "external"
is specified, that means a custom class name that implements the TemplateGenerator interface and returns with a template on-thy-fly.
Object: responseFormatterSet
This object is used to collect a set of responseFormatters and responseFormatterSetInvokers, in order to use them later on templates.
{
"name": ...,
"responseFormatterSet" : [ ... ]
}
name
is a unique name of the template
.
responseFormatterSet
is an array of responseFormatter
-s and responseFormatterSetInvoker
-s.
Object conditionSets
This object contains a reusable set of conditions that can be called in the conditionDescriptor
.
"conditionSets": [
{
"name": ...,
"conditionDescriptor": { ... }
},
{...},
...
]
name
is a unique name of the conditionSet
in the array.
conditionDescriptor
is a standard conditionDescriptor
object, that may contain a condition
, a logicalCondition
or a conditionSetInvoker
.
Only one conditionSets
object may exists inside wilmaStubConfiguration
object.
Usage Example:
{
"wilmaStubConfiguration": {
"dialogDescriptors": [
{
"name": "Test",
"conditionDescriptor": {
"conditionSetInvoker": "firstCondition"
},
"responseDescriptor": { "code": 200, "delay": 0, "mimeType": "text/html", "templateName": "htmlTemplate1" }
}
],
"templates": [ { "name": "htmlTemplate1", "type": "html", "resource": "<head>T1</head><body> Template 1 </body>" } ],
"conditionSets": [
{
"name": "firstCondition",
"conditionDescriptor": {
"condition": {
"class": "AlwaysTrueChecker"
}
}
}
]
}
}
Object: responseFormatterSets
This object is an array of responseFormatterSet
-s those can be called during formatting the response.
Only one such object may exists inside wilmaStubConfiguration
object.
Object: templates
The templates
object is an array of template objects, on other words contains many template definitions. The same physical response template can be used by several templates, as the same template - by using different fill methods - can be used for different purposes.
Only one such object may exists inside wilmaStubConfiguration
object.
Validation: the configuration json should be validated, not just formally, but logically too - like if a dialogDescriptor
refers to a template
, then that template need to be defined properly.
In case of validation error:
- at Wilma startup check: Wilma writes meaningful error message to console and exits
- at run-time: change request is refused (with meaningful error message), and the original - validated - configuration remains in use
See Example Stub configuration page to get some real world usage possibilities.
Among the main elements of configuration xml described here, further elements may exist in the xml file, like