NEW model-specific DMN kie-server endpoints
23 March 2021
Modernising kie-server with new and more user-friendly DMN endpoints, better Swagger/OpenAPI documentation, easier JSON-based REST invocations; an intermediate step to help developers transitioning to service-oriented deployments such as a Kogito-based application.
In a nutshell:
The current DMN kie-server endpoints are fully compliant with kie-server extension design architecture, and aligned with all other kie-server services and extensions; however, some aspects of the current generic approach of kie-server sometimes are not very user-friendly for DMN evaluations, due to limitations of swagger documentation and the REST payloads requirements to follow the generic kie-server marshaller protocol. These aspects do apply to all kie-server services, including naturally DMN kie-server endpoints as well.
On other hand, experience shown that building manually the REST payload on Kogito for DMN evaluation is very easy for end-users, thanks to key features pertaining to DMN core capabilities.
This new feature (DROOLS-6047) extends DMN on kie-server with new endpoints, leveraging those core capabilities; the new DMN endpoints provide better Swagger documentation and can be more easily consumed by end-users, therefore contributing to modernising the kie-server platform while also making easier to eventually transition to a full Kogito-based application and deployment!
Why is this needed?
Currently on kie-server, the DMN service exposes 2 endpoints which are fully compliant with kie-server extension design architecture:
GET /server/containers/{containerId}/dmn
Retrieves DMN model for given container
POST /server/containers/{containerId}/dmn
Evaluates decisions for given input
The current swagger documentation is agnostic to the actual model content of the knowledge asset, like for any other kie-server extension:
This limited style of swagger documentation is sometimes an undesirable side-effect to the generic approach of kie-server extension design:
- all kie-server extensions receive as input a generic String, which is actually converted internally to the extension using the generic kie-server marshaller.
This causes the swagger documentation to not display anything meaningful for the request body besides Model==string, and the only helpful information can only be provided as a comment (“DMN context to be used while evaluation decisions as DMNContextKS type”). - all kie-server extensions return as output a
ServiceResponse<T>
, where the Java’s generic T is extension-specific. Generating swagger documentation with Java generics is already limited, in this case the difficulty compounds because the actual content of T varies, by DMN model to model !
- the DMN evaluation payload itself contains the coordinates of the model to be evaluated and the model-specific input context, per the original implementation requirements; but this interconnection between model coordinates values and input content structure, is pragmatically impossible to be defined meaningfully with a Swagger or OpenAPI descriptor.
About the last point specifically, consider this example DMN payload:
{
"model-namespace": "https://kiegroup.org/dmn/_FA9849E2-C92E-4E27-83BF-07A7428DC9C9",
"model-name": "Traffic Violation",
"dmn-context": {
"Driver": ...,
"Violation": ...
}
}
because the content of dmn-context
depends on the values of model-namespace
and model-name
coordinates, there is no pragmatic way to define with Swagger/OpenAPI that dmn-context
must have the properties “Driver”, “Violation” for this traffic violation model, or property “Customer” for another DMN model.
Besides endpoint documentation limitations, experience proved that building manually from scratch the kie-server generic payload following the style of the kie-server generic marshaller is very difficult for most end-users (in fact we always advise to use the Kie Server Client API first, and not start from scratch, but this suggestion is often ignored anyway):
- XML/JAXB format requires domain model pojo to be correctly annotated first, and building Java collection manually is quite tricky.
- XML/XStream is a more natural format, still requires domain model pojo annotations, requires to respect the domain object FQN, but is yet another xml format while most end-users seem to prefer json instead.
- JSON/Jackson would be the user preference nowadays, but requires to respect the domain object FQN which is very alien to json native users.
Example. The correct way to marshall for Traffic Violation example, respecting the domain model defined in the kjar project, would be:
{
"model-namespace": "https://kiegroup.org/dmn/_FA9849E2-C92E-4E27-83BF-07A7428DC9C9",
"model-name": "Traffic Violation",
"dmn-context": {
"Driver": { "com.acme.Driver" : {
"Points": 15
}},
"Violation": { "com.acme.Violation" : {
"Type": "speed",
"Date": "2020-10-01",
"Actual Speed": 111,
"Speed Limit": 100
}}
}
}
Everything would be much more easier, while building the JSON body payload manually for DMN evaluation, if we could drop the strict requirement to respect the generic kie-server marshalling format.
NEW model-specific DMN kie-server endpoints
We can now move past and beyond these limitations, thanks to the next generation of DMN endpoints on kie-server, leveraging some new DMN core capabilities:
- programmatic generation of Swagger and OpenAPI (Swagger/OAS) metadata (DROOLS-5670)
- consistent DMNContext build from JSON, based on DMN Model metadata (DROOLS-5719)
to ultimately offer more user-friendly endpoints on kie-server for DMN evaluation!
Following similar style to what is offered today via Kogito, summarized in this blog post, we implemented the following new DMN endpoints on kie-server:
GET /server/containers/{containerId}/dmn/openapi.json (|.yaml)
Retrieves Swagger/OAS for the DMN models in the kjar projectGET /server/containers/{containerId}/dmn/models/{modelname}
Standard DMN XML but without any decision logic, so this can be used as a descriptor of the DMN model (which are the inputs, which are the decisions), while using the same format of the DMN XSD instead.POST /server/containers/{containerId}/dmn/models/{modelname}
JSON-only evaluation of a specific DMN model with a body payload tailored for the specific modelPOST /server/containers/{containerId}/dmn/models/{modelname}/{decisionServiceName}
JSON-only evaluation of a specific decision service of a specific DMN model with a body payload tailored for the specific modelPOST /server/containers/{containerId}/dmn/models/{modelname}/dmnresult
JSON-only evaluation of a specific DMN model with a body payload tailored for the specific model, but returning a JSON representation as a DMNResultPOST /server/containers/{containerId}/dmn/models/{modelname}/{decisionServiceName}/dmnresult
JSON-only evaluation of a specific decision service of a specific DMN model with a body payload tailored for the specific model, but returning a JSON representation as a DMNResult
For the difference between “business-domain” and “dmnresult” variants of the rest endpoints, reference the original blog post as also linked above.
Making reference to the Traffic Violation example model, this new capability can now offer on kie-server something similar to:
As we can see, both the input body payload and the response body payload offer Swagger/OAS schemas which are consistent with the specific DMN model!
This is possible thanks to a convergence of factors:
- Because each REST POST endpoint for DMN evaluation is specific for DMN model in the REST Path, it is possible to offer Swagger/OAS definition which are DMN model-specific
e.g.: becausePOST /server/containers/mykjar-project/dmn/traffic-violation
is a REST endpoint specific to the Traffic Violation model, both its input and output payload can now be documented properly in the Swagger/OAS schema definitions. - Because each Swagger/OAS definition is offered at kjar/kie-container level, it is possible to generate programmatically the schema definitions for the DMN models contained only in the specific container.
e.g.: becauseGET /server/containers/mykjar-project/dmn/openapi.json
would offer only definitions for the DMN models inside “mykjar-project”.
This is thanks to the following DMN core capability: programmatic generation of Swagger/OAS metadata (DROOLS-5670) - Because these endpoints are DMN evaluation specific and focusing on a natural and idiomatic JSON usage, they do NOT require to follow the generic kie-server marshalling format.
This is thanks to the following DMN core capability: consistent DMNContext build from JSON based on DMNModel metadata (DROOLS-5719)
Any limitations?
Being a new set of endpoints, in addition to the currently existing ones, there is basically no impact on the already-existing DMN kie-server capabilities.
As this proposed set of new endpoints are contained within a specific {containerId}, it also means that the openapi.json|.yaml swagger/OAS definition file is only kie-container specific.
In turn, it means when accessing the swagger-ui client editor, user need to manually point to the container URL, for example something like:
Finally, as this core capability do leverage Eclipse MicroProfile for OpenAPI Specification (OAS) and SmallRye-openapi-core, this requires making use of Swagger-UI and clients which are compatible with OpenAPI Specification version 3.0.3, onwards.
Conclusions
We believe this feature meaningfully extends the current set of capabilities, by providing more user-friendly DMN endpoints on kie-server!
Developers can make full use of this new feature to simplify existing REST call invocations, and as a stepping stone to eventually migrate to a Kogito-based application.
Have you tried it yet?
Do you have any feedback?
Let us know in the comments below!