defining ‘UJMW’ (a message wrapper format for JSON based webservice calls)

Do you implement WebAPIs which are NOT located on the persistence layer and therefore NOT focused on doing CRUD operations?

Then you should avoid to implement them as a ‘RESTful’ api, cause this makes no sense. Some HTTP-based APIs having a ‘call-based’ approach to known BL operations.

IN-, OUT- and return-arguments should not be transmitted over the URL. Instead you need to use request-/response- wrappers, which are very lightweight and are a compromise for broad support and adaptability in REST-inspired technologies as well as soap-inspired technologies – so lets see the definition document:


Motivation:

Problems of SOAP and its "Call-based" style

TBD

Problems of REST and its "CRUD" style

TBD

The truth within the middle

What we want is ....... TBD

a quick look on classical WCF-Wrappers

TBD

Transporting Arguments

Each request and response must have the wrapper object as json-root containing named Arguments as properties.

The wrapper capsule is ALWAYS required, also if there is none or just one argument

{
    "myNamedParam1": ...,
    "myNamedParam2": ...,
}

Naming:

DataTypes

Type Convention Sample
Date / Time must be in ISO8601 Format + should be UTC 2020-06-15T13:45:30.0000000Z
Byte[] / Binary must be in Base64 TWFuIGlzIGRpc3Rpbmd==
Numeric values must not have 1000-separator-chars + must have the char "." for separating the decimal places 123433454.23

Encoding

The "return"-Property

"return" is a constant name which is magic-value between the other argument Names. It represents the return-value of this Function, which is invoked.

{
    "return": ...
}

VOID-Methods

If a VOID (a Method without a return-value) is invoked, the result-wrapper must not contain a "return" property. A "return"-property with a null-value is NOT allowed in this case, because this is reserved for Functions returning a null-value.

Why "return" instead of "result"

We never use "result" here because assuming that an return-value would have the semantic to be the "result" of an operation is highly BL-related and needs to be specified within the service-contract (using argument or method-names or comments) instead of the transport layer. "return" has the maximum level abstraction and is exactly right for this layer!

"Out"-Arguments

Same way as in arguments - a VOID which has only IN/OUT arguments will have exactly the same response-wrapper as the request-wrapper.

The "fault"-Property

Is also a constant name which is magic-value representing an Exception. This means, that only response-wrappers can contain a "fault" Property AND if it is exists, no other properties have to exist!

{
    "fault": "message"
}

Please note that the "fault"-Property should only used for critical, non-business Errors - like Exceptions. All regular possible failures of the executed operation should be transferred over other channels. For that were recommending the "returnCode"-Pattern as described below (maybe in combination with the "lastError" - SideChannel. Nevertheless also Exceptions from our BL should not affect the transport-layer technology. However, even exceptions from the BL should not affect the transport layer technology, and because of this, the usage of the fault-Property MUST NOT be accompanied by an http-response code other than 200!

The "returnCode"-Pattern

This is just a propose for using an OUT-Arg which usually should have a name like "returnCode" to do something like a Try...Methods (in some Languages). In this case were not blocking the primary "return" value just for delivering an information about the success of a invoked method.

  • The code does not have a dedicated semantic to always be an error - so it must not be called "errorCode"!

  • If an returnCode was delivered, which indicated an error, then some additional details can be placed within the "lastError"-SideChannel (as described below)

Side-Channels

This part is optional within the wrapper!

To avoid conflicts with the regular arguments, we need a sub-structure which is placed within a property named "_" (also a magic-value).

{
    "_": {
      "myAdditionalData": ...,
    },
}

Reserved / well known Side-Channel names

Channel Name Direction Description
"lastError" RESPONSE ONLY TDB (documentation / derVodi)
"ambientDataFlow" REQUEST ONLY TBD
"transactionId" REQUEST ONLY used to transfer Transaction-Handles

Leave a Reply