Many of the endpoints you stand up will take input from the user. The input you expect for your endpoint is defined by the input entity definition. The input entity definition defines things like:
Endpoints can also have their input entity definition describe things like:
The input entity definition is a flat structure. It cannot currently contain complex types like other objects.
An endpoint does not require an input entity definition. You only need an input entity definition when there is variable data coming from the user. For example, your route for the endpoint is, GET /examples/products,
there is no variable input coming from the user. But if your route is GET /examples/products/{productId
}, or if you want to accept query parameters, or you expect a POST payload, you need to tell the system what this data looks like and when to expect it.
The input entity definition object can have the following properties:
|
The field's property on the input entity definition should be an object value. Each property on the object should be the expected input field name. That property's value should be an object with the following properties:
|
You might be wondering why the input entity definition has properties around the HTTP methods. Aren't HTTP methods an attribute of the route? They absolutely are part of the route. And the route definition is the only thing that dictates how your endpoint is addressable. However, if you are developing CRUD based endpoints, you will find that the input you expect from your callers is very similar across HTTP methods. For example, POST (create) and PATCH (update) payloads typically only differ in a few minor areas.
Being able to describe the HTTP methods the fields are valid / required for allows us to reuse the input entity definition in different endpoints using references. |
Assume we have a route definition of GET /examples/products/{productId
}. We need to define an input entity definition that tells the system about product Id.
{ "endpoints": { "ExamplesGetSingleProduct": { "inputEntityDefinition": { "name": "ExampleGetSingleProductInput", "fields": { "productId": { "type": "long", "input": { "httpMethods": [ "GET" ], "source": "path" } } } } //remaining metadata omitted } } } |
We didn't include a httpRequiredMethods attribute here. That's because fields from the path are always required. It would not be possible to route to the endpoint successfully if path fields were allowed to be optional.
Let's say we were also going to allow customers to also update existing products. This would require an additional endpoints to be defined with the following route:
PATCH /examples/products/{productId
}Our input entity definition for both end points could look like this:
"inputEntityDefinition": { "name": "ExampleGetSingleProductInput", "fields": { "productId": { "type": "long", "input": { "httpMethods": [ "GET", "PATCH" ], "source": "path", "requiredHttpMethods" : ["PATCH"] }, "productName" : { "httpMethods" : [ "PATCH" ], //allow caller to update productName "source" : "body" } } } } |
The takeaway here is that we didn't have to duplicate a lot of metadata. It might not seem like much when you only have one input field, but as your endpoints start accepting more client input this becomes a time saver. How you reuse the metadata across endpoints is covered in the section on references.