Copyright © 2005-2023

Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.

Overview

This guide describes the RESTful API of the OpenWMS.org CORE Preferences Service and its usage. Some general terms and definitions are explained and declared in the first part of the document whereas in the second part the usage of the API is shown in a more use-case-driven approach.

Representation Formats

Basically JSON is used as representation format by default if not otherwise requested or mentioned below. XML format is supported for the index pages as well, but must be requested explicitly. Furthermore a vendor specific JSON format is used to represent resource representations. Therefore it is absolutely required that the Accept header denotes the demanded type. Find the type in the examples below.

Dates in JSON

Date or datetime fields are not treated specially in JSON. Within the scope of this API a date or datetime field is always expected and rendered as JSON String in ISO8601 format with timezone information and milliseconds: yyyy-MM-dd’T’HH:mm:ss.SSSTZD.

Embedded Entities

For the sake of convenience some response entities may included embedded entities or even parts of it. A reference to the actual entity is provided as HAL link as well.

Error Responses

Beside the actual representation of resources, the server may result an error response in JSON format that contains basic information about the error occurred. This information is additional to the standard HTTP status code and may help clients to identify the error cause in order to re-phrase and send the request again.

Currently there are two types of errors with their own response formats.

Server Declined Errors

This kind of errors are sent by the server runtime environment even before the request had a chance to be processed.

An example response looks like this:

{
  "timestamp" : 1512400854941,
  "path" : "/v1/preferences",
  "status" : 409,
  "error" : "Conflict",
  "message" : "",
  "requestId" : "7acb57f4"
}

The JSON structure contains the following fields.

Property Name Description

timestamp

When the error occurred on server side

path

The part of the URI for the REST resource that was queried

status

The http status of the error

error

A short error text

message

A more descriptive error text describing the error in detail

requestId

Server assigned unique id of each request, used for tracing and profiling

API Declined Errors

Those errors are thrown within the REST API validation and processing logic. For example, if a client request does not match the expected format or has produced an error on server side, the API will decline the request and return a response with status client-side error (4xx).

The structure of the response is aligned to the RFC7808. An example response looks like this:

{
    "message": "LocationGroup with name [NOT_EXISTS] not found",
    "messageKey": "owms.common.common.lg.notFoundByName",
    "obj" : [ "NOT_EXISTS" ],
    "httpStatus" : "404",
    "class" : "String"
}

The JSON structure contains the following fields.

Property Name Description

message

A short error text

messageKey

An unique identifier across the API that can be used to identify and translate the error message on the client side

obj

An array of possible passed arguments to the message

httpStatus

The http status of the error

class

The arguments type

Following message keys are currently used:

Message Key Description Action

not.found

The requested resource has not been found

The resource does not exist anymore or has never existed. The resource identifier must be verified

owms.common.common.tu.notFoundByBK

The TransportUnit does not exist

Verify the identifying attribute passed to the API

owms.common.common.loc.notFoundByName

The requested Location does not exist

Verify the identifying attribute passed to the API

owms.common.common.lg.notFoundByName

The requested LocationGroup does not exist

Verify the identifying attribute passed to the API

owms.common.common.tut.notFoundByName

The requested TransportUnitType does not exist

Verify the identifying attribute passed to the API

Resources

A description of all used API resources.

ClassDiagram

Index

The initial HTTP request to retrieve information about all available resources looks like the following. The Index page is a public available resource and does not need any authentication.

GET /index HTTP/1.1
Host: localhost:8080

The Index resource is returned in the response body with the response status of 200-OK. This main Index lists all primary resource entities to follow next.

HTTP/1.1 200 OK
Content-Type: application/hal+json
Content-Length: 116

{
  "_links" : {
    "preferences-index" : {
      "href" : "http://localhost:8080/v1/preferences/index"
    }
  }
}

A client application must only know about the agreed link names and follow the corresponding href link to navigate further.

Preference

A Preference represents a configuration value in a particular scope. So a Preference could only be visible and editable by one particular user in the system, then this is an UserPreference. If a Preference should be valid for many users then it can be assigned to a user role and is of type RolePreference.

Apart from users and roles a Preference can also be assigned to an abstract thing called Module. This could be a single Microservice for example. This is of type ModulePreference. The whole application consists of several Microservices that may require common preferences that are valid for all modules, those are stores of type ApplicationPreference.

All kind of preferences share same data stored in a supertype called Preference. Each subtype defines the scope as a property and an owner of the Preference. This might be the name of the user, the role name or the microservice name. A Preference is identified by type, owner and the key field.

Preferences Index

The Preferences Index with all possible operations can be retrieved with the following GET request:

GET /v1/preferences/index HTTP/1.1
Host: localhost:8080

The response lists all the operations with a name and the corresponding href link:

HTTP/1.1 200 OK
Content-Type: application/hal+json
Content-Length: 993

{
  "_links" : {
    "preferences-findall" : {
      "href" : "http://localhost:8080/v1/preferences"
    },
    "preferences-findbypkey" : {
      "href" : "http://localhost:8080/v1/preferences/pKey"
    },
    "preferences-findallofscope" : {
      "href" : "http://localhost:8080/v1/preferences?scope=%7Bscope%7D"
    },
    "preferences-findbyownerscopekey" : {
      "href" : "http://localhost:8080/preferences/groups?owner=user&scope=USER&name=group1"
    },
    "preferences-create" : {
      "href" : "http://localhost:8080/v1/preferences?strict=false"
    },
    "preferences-update" : {
      "href" : "http://localhost:8080/v1/preferences/pKey"
    },
    "preferences-delete" : {
      "href" : "http://localhost:8080/v1/preferences/pKey"
    },
    "user-preferences-findbyuser" : {
      "href" : "http://localhost:8080/v1/preferences?user=user"
    },
    "user-preferences-findbyuserandkey" : {
      "href" : "http://localhost:8080/v1/preferences?user=user&key=key"
    }
  }
}

Find all Preferences (preferences-findall)

Send a HTTP GET request without any further query parameters to find and return all existing Preferences

GET /v1/preferences HTTP/1.1
Host: localhost:8080

The server responds with an array of all Preferences, that might be empty if no Preferences exist

HTTP/1.1 200 OK
Content-Type: application/vnd.openwms.core.preference-v1+json
Content-Length: 709

[ {
  "@class" : "org.openwms.core.preferences.api.UserPreferenceVO",
  "pKey" : "1000",
  "key" : "key1",
  "owner" : "owner1",
  "description" : "String description",
  "value" : "current val",
  "groupName" : "GLOBAL",
  "type" : "STRING"
}, {
  "@class" : "org.openwms.core.preferences.api.UserPreferenceVO",
  "pKey" : "1001",
  "key" : "key2",
  "owner" : "owner1",
  "description" : "String description",
  "value" : "current val",
  "groupName" : "GLOBAL",
  "type" : "STRING"
}, {
  "@class" : "org.openwms.core.preferences.api.ApplicationPreferenceVO",
  "pKey" : "1002",
  "key" : "key3",
  "description" : "Application",
  "value" : "current val",
  "groupName" : "GLOBAL",
  "type" : "STRING"
} ]

Find a Preference by Key (preferences-findbypkey)

Send a HTTP GET request with the persistent key as part of the path to find and return the Preference

GET /v1/preferences/1000 HTTP/1.1
Host: localhost:8080

The server returns the Preference resource in case it exists

HTTP/1.1 200 OK
Content-Type: application/vnd.openwms.core.user-preference-v1+json
Content-Length: 241

{
  "@class" : "org.openwms.core.preferences.api.UserPreferenceVO",
  "pKey" : "1000",
  "key" : "key1",
  "owner" : "owner1",
  "description" : "String description",
  "value" : "current val",
  "groupName" : "GLOBAL",
  "type" : "STRING"
}

or responds with a 404 NOT-FOUND if the Preference does not exist

HTTP/1.1 404 Not Found
Content-Type: application/hal+json
Content-Length: 203

{
  "message" : "Preference with persistent key [UNKNOWN] does not exist",
  "messageKey" : "owms.core.preferences.notFoundByPKey",
  "obj" : [ "UNKNOWN" ],
  "httpStatus" : "404",
  "class" : "String"
}

Find all Preferences of particular Scope (preferences-findallofscope)

Send a HTTP GET request with the desired scope as request parameter to find and return all Preferences that belong to the given scope

GET /v1/preferences?scope=APPLICATION HTTP/1.1
Host: localhost:8080

The server responds with an array of Preferences, or an empty array if no Preferences exist

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 223

[ {
  "@class" : "org.openwms.core.preferences.api.ApplicationPreferenceVO",
  "pKey" : "1002",
  "key" : "key3",
  "description" : "Application",
  "value" : "current val",
  "groupName" : "GLOBAL",
  "type" : "STRING"
} ]

Notice: It is not allowed to query UserPreferences without a particular user parameter to prohibit spoofing of private user settings. The attempt to do so is blocked by the server with:

HTTP/1.1 401 Unauthorized
Content-Type: application/hal+json
Content-Length: 150

{
  "message" : "Not allowed to fetch User preferences",
  "messageKey" : "owms.core.preferences.notAllowedToFetchUserPrefs",
  "httpStatus" : "401"
}

Create a new Preference (preferences-create)

New Preferences can be created either with the definition in XML files or over the REST API. A client must send a POST request to the Preferences resource in order to create a new instance. The content is passed in the request body.

POST /v1/preferences HTTP/1.1
Content-Type: application/json
Content-Length: 145
Host: localhost:8080

{"@class":"org.openwms.core.preferences.api.UserPreferenceVO","key":"keyY","owner":"owner2","description":"A Boolean","value":true,"type":"BOOL"}

The server responds with 201 CREATED if the operation succeeds.

HTTP/1.1 201 Created
Location: http://localhost:8080/v1/preferences/64dbef5e-ff22-4121-ba90-3e85ef4b5b03
Content-Type: application/json
Content-Length: 229

{
  "@class" : "org.openwms.core.preferences.api.UserPreferenceVO",
  "pKey" : "64dbef5e-ff22-4121-ba90-3e85ef4b5b03",
  "key" : "keyY",
  "owner" : "owner2",
  "description" : "A Boolean",
  "value" : "true",
  "type" : "BOOL"
}

If the Preference to create already exists, the server returns:

HTTP/1.1 409 Conflict
Content-Type: application/hal+json
Content-Length: 262

{
  "message" : "Preference with key [keyY] and owner [owner2] and scope [USER] already exists",
  "messageKey" : "owms.core.preferences.alreadyExistsWithOwnerAndScopeAndKey",
  "obj" : [ "keyY", "owner2", "USER" ],
  "httpStatus" : "409",
  "class" : "String"
}

Update an existing Preference (preferences-update)

To modify an existing Preference an PUT request with the Preference as request body is expected. The Preference to update is identified by the persistent key as part of the path.

PUT /v1/preferences/1000 HTTP/1.1
Content-Type: application/json
Content-Length: 159
Host: localhost:8080

{"@class":"org.openwms.core.preferences.api.UserPreferenceVO","pKey":"1000","key":"keyX","owner":"owner2","description":"A Boolean","value":true,"type":"BOOL"}

The server responds with 204 NO-CONTENT.

HTTP/1.1 200 OK
Content-Type: application/vnd.openwms.core.user-preference-v1+json
Content-Length: 197

{
  "@class" : "org.openwms.core.preferences.api.UserPreferenceVO",
  "pKey" : "1000",
  "key" : "keyX",
  "owner" : "owner2",
  "description" : "A Boolean",
  "value" : "true",
  "type" : "BOOL"
}

Delete a Preference (preferences-delete)

To delete an existing Preference one can call the URI to the resource with a HTTP DELETE request. The persistent key of the Preference is required to identify the resource to delete.

DELETE /v1/preferences/1000 HTTP/1.1
Host: localhost:8080

The server responds with 204 NO-CONTENT is the resource has been deleted successfully.

HTTP/1.1 204 No Content

If the resource doesn’t exist and could not be deleted the server responds with a 404 NOT-FOUND.

UserPreference

A UserPreference is a Preference that is only valid for a single user.

Find all UserPreferences of an User (user-preferences-findbyuser)

Send a HTTP GET request without the user name as query parameter to find all existing UserPreferences of that user.

GET /v1/preferences?user=owner1 HTTP/1.1
Host: localhost:8080

The server responds with an array of all UserPreferences, that might be empty if no UserPreferences exist.

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 488

[ {
  "@class" : "org.openwms.core.preferences.api.UserPreferenceVO",
  "pKey" : "1000",
  "key" : "key1",
  "owner" : "owner1",
  "description" : "String description",
  "value" : "current val",
  "groupName" : "GLOBAL",
  "type" : "STRING"
}, {
  "@class" : "org.openwms.core.preferences.api.UserPreferenceVO",
  "pKey" : "1001",
  "key" : "key2",
  "owner" : "owner1",
  "description" : "String description",
  "value" : "current val",
  "groupName" : "GLOBAL",
  "type" : "STRING"
} ]

Find a UserPreference by Key (user-preferences-findbyuserandkey)

Send a HTTP GET request with the persistent key and the user name as query parameters to find and return the UserPreference.

GET /v1/preferences?user=owner1&key=key1 HTTP/1.1
Host: localhost:8080

The server returns the UserPreference if exists.

HTTP/1.1 200 OK
Content-Type: application/hal+json
Content-Length: 241

{
  "@class" : "org.openwms.core.preferences.api.UserPreferenceVO",
  "pKey" : "1000",
  "key" : "key1",
  "owner" : "owner1",
  "description" : "String description",
  "value" : "current val",
  "groupName" : "GLOBAL",
  "type" : "STRING"
}

or responds with a 404 NOT-FOUND if the UserPreference does not exist.

HTTP/1.1 404 Not Found
Content-Type: application/hal+json
Content-Length: 256

{
  "message" : "Preference key [UNKNOWN] and owner [owner1] and scope [USER] does not exist",
  "messageKey" : "owms.core.preferences.notFoundByOwnerAndScopeAndKey",
  "obj" : [ "UNKNOWN", "owner1", "USER" ],
  "httpStatus" : "404",
  "class" : "String"
}