Input Entity Definitions
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:
- variables you expect from the caller
- the types of those variables
- whether or not the types are required
- what http methods the variables are valid for
- where to find the variables in the request
Endpoints can also have their input entity definition describe things like:
- How to convert friendly user-facing values to legacy server-side values and vice versa.
- A list of values to constrain the input to
- Ways to map user supplied fields into the GE when user-facing fields and legacy server-side field names do not align.
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:
Input Entity Definition object properties
Property Name | Value | Comments |
---|---|---|
name | string | A unique identifier for this input entity definition. The identifier must be unique within the entire Endpoint.json definition file. |
fields | object | Within the value object, each property name is the expected input field name. That property's value is a Field Object (described below). |
Field Object 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:
Property Name | Value | Comments |
---|---|---|
type | string | Describes what type the framework should expect for the input field. Valid types are string, int, integer, long, decimal, bool, boolean, date, datetime, array and double. |
input | object | An Input Object that further defines the payload (described below) |
description | string | A description of the field. This will be surfaced in the public API documentation. |
sourceField | string | If the input payload gets mapped into a GE by the business logic, this value allows you to automatically map public facing fields to backend fields. |
Input Object properties
Property Name | Value | Comments |
---|---|---|
source | string | Where the framework should look at the HTTP request for this piece of input. Valid values are path, queryString, and body. |
httpMethods | array of strings | An array of HTTP methods this input field should be allowed for. |
requiredHttpMethods | array of strings | An array of HTTP methods this input field must be supplied for. |
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.
- POST endpoints do not refer to an existing resource, and often require all values to successfully create a resource.
- PATCH endpoints always refer to an existing resource, and often do not require all values be sent to update a resource.
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.
Examples
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.
Copyright © 2014-2019 Aptify - Confidential and Proprietary