From 60951330196168f560a7c61496e2b66a2f2c8474 Mon Sep 17 00:00:00 2001 From: Kai Zimmermann Date: Fri, 1 Feb 2019 12:09:11 +0100 Subject: [PATCH] Fix DMF docs and unnecessary content_type enforcements. (#792) * Fix DMF docs and unnecessary content_typ enforcements. * One more error. * Typo --- docs/content/apis/dmf_api.md | 330 +++++++++--------- .../amqp/AmqpMessageHandlerService.java | 1 - ...pMessageHandlerServiceIntegrationTest.java | 13 - 3 files changed, 165 insertions(+), 179 deletions(-) diff --git a/docs/content/apis/dmf_api.md b/docs/content/apis/dmf_api.md index 8486a443c..20d0c9204 100644 --- a/docs/content/apis/dmf_api.md +++ b/docs/content/apis/dmf_api.md @@ -5,7 +5,8 @@ weight: 83 --- The DMF API provides Java classes which allows that the message body can be deserialized at runtime into a Java object. Also Java classes can be used to serialize Java objects into JSON bodies to send a message to hawkBit. -Currently, bodies of messages are based on JSON. +Currently, bodies of messages are based on JSON. + ## Basics @@ -18,7 +19,7 @@ There are three basic concepts of AMQP: **Queues** are just a place for receiving messages. Bindings determine how messages get put in this place -Queues can also be bound to multiple exchanges. +Queues can also be bound to multiple exchanges. **Exchanges** are just publish messages. The user decides who can produce on an exchange and who can create bindings on that exchange for delivery to a specific queue. @@ -26,66 +27,61 @@ The user decides who can produce on an exchange and who can create bindings on t hawkBit will create all necessary queues, exchanges and bindings for the user, making it easy to get started. The exchange name for outgoing messages is **dmf.exchange**. -The user has to set a ``reply_to`` header (see chapter below), to change the default sender exchange. +The user has to set a `reply_to` header (see chapter below), to change the default sender exchange. The following chapter describes the message body, header and properties. -Note: the DMF protocol was intended to be open for other non update use cases by design (e.g. [Eclipse Hono](https://github.com/eclipse/hono). As a result, DMF uses the term **thing** and not **target** but they are actually synonyms in this case. +Note: the DMF protocol was intended to be compatible to other use cases by design. As a result, DMF uses the term **thing** and not **target** but they are actually synonyms in this case. ## Messages sent to hawkBit + All messages have to be sent to the exchange **dmf.exchange**. ### Message to register a thing -| Message Header | Description | Type | Mandatory -|-----------------------------|----------------------------------|-------------------------------------|---------------- -| type | Type of the message | Fixed string "THING_CREATED " | true -| thingId | The ID of the registered thing | String | true -| sender | Name of the message sender | String | false -| tenant | The tenant this thing belongs to | String | false +| Message Header | Description | Type | Mandatory | +| -------------- | -------------------------------- | ----------------------------- | --------- | +| type | Type of the message | Fixed string "THING_CREATED " | true | +| thingId | The ID of the registered thing | String | true | +| tenant | The tenant this thing belongs to | String | true | - -| Message Properties | Description | Type | Mandatory -|-----------------------------|----------------------------------|-------------------------------------|---------------- -| content_type | The content type of the payload | String | true -| reply_to | Exchange to reply to. | String | false +| Message Properties | Description | Type | Mandatory | +| ------------------ | --------------------- | ------ | --------- | +| reply_to | Exchange to reply to. | String | true | **Example Header** -| Headers | MessageProperties -|---------------------------------------|--------------------------------- -| type=THING\_CREATED
tenant=tenant123
thingId=abc
sender=Lwm2m | content\_type=application/json
reply_to (optional) =sp.connector.replyTo - +| Headers | MessageProperties | +| ------------------------------------------------------------- | -------------------------- | +| type=THING_CREATED
tenant=tenant123
thingId=abc | reply_to=dmfclient.replyTo | ### Message to update target attributes -| Message Header | Description | Type | Mandatory -|-----------------------------|----------------------------------|-------------------------------------|---------------- -| type | Type of the message | Fixed string "EVENT" | true -| topic | Topic to handle events different | Fixed string "UPDATE_ATTRIBUTES" | true -| thingId | The ID of the registered thing | String | true -| tenant | The tenant this thing belongs to | String | false - - -| Message Properties | Description | Type | Mandatory -|-----------------------------|----------------------------------|-------------------------------------|---------------- -| content_type | The content type of the payload | String | true +| Message Header | Description | Type | Mandatory | +| -------------- | -------------------------------- | -------------------------------- | --------- | +| type | Type of the message | Fixed string "EVENT" | true | +| topic | Topic to handle events different | Fixed string "UPDATE_ATTRIBUTES" | true | +| thingId | The ID of the registered thing | String | true | +| tenant | The tenant this thing belongs to | String | true | +| Message Properties | Description | Type | Mandatory | +| ------------------ | ------------------------------- | ------ | --------- | +| content_type | The content type of the payload | String | true | **Example Header and Payload** -| Headers | MessageProperties -|---------------------------------------|--------------------------------- -| type=EVENT
tenant=tenant123
thingId=abc
topic=UPDATE\_ATTRIBUTES | content\_type=application/json
+| Headers | MessageProperties | +| ------------------------------------------------------------------------------------ | ----------------------------- | +| type=EVENT
tenant=tenant123
thingId=abc
topic=UPDATE_ATTRIBUTES | content_type=application/json | Payload Template ```json { - "attributes": { - "exampleKey1" : "exampleValue1", - "exampleKey2" : "exampleValue2" - } + "attributes": { + "exampleKey1": "exampleValue1", + "exampleKey2": "exampleValue2" + } } ``` @@ -93,86 +89,85 @@ Payload Template The Java representation is ActionUpdateStatus: -| Header | Description | Type | Mandatory -|-----------------------------|----------------------------------|-------------------------------------|-------------- -| type | Type of the message | Fixed string "EVENT" | true -| topic | Topic to handle events different | Fixed string "UPDATE_ACTION_STATUS" | true -| tenant | The tenant this thing belongs to | String | false +| Header | Description | Type | Mandatory | +| ------ | -------------------------------- | ----------------------------------- | --------- | +| type | Type of the message | Fixed string "EVENT" | true | +| topic | Topic to handle events different | Fixed string "UPDATE_ACTION_STATUS" | true | +| tenant | The tenant this thing belongs to | String | true | -| Message Properties | Description | Type | Mandatory -|-----------------------------|----------------------------------|-------------------------------------|---------------- -| content_type | The content type of the payload | String | true +| Message Properties | Description | Type | Mandatory | +| ------------------ | ------------------------------- | ------ | --------- | +| content_type | The content type of the payload | String | true | Payload Template ```json { - "actionId": long, - "softwareModuleId": long, - "actionStatus":"String", - "message":["String"] + "actionId": long, + "softwareModuleId": long, + "actionStatus": "String", + "message": ["String"] } ``` Possible actionStatus -| Header | Description -|-----------------|------------------------------------ -| DOWNLOAD | Device is downloading -| RETRIEVED | Device management service has retrieved something -| RUNNING | Update is running -| FINISHED | Update process finished successful -| ERROR | Error during update process -| WARNING | Warning during update process -| CANCELED | Cancel update process successful -| CANCEL_REJECTED | Cancel update process has been rejected - +| Header | Description | +| --------------- | ------------------------------------------------- | +| DOWNLOAD | Device is downloading | +| RETRIEVED | Device management service has retrieved something | +| RUNNING | Update is running | +| FINISHED | Update process finished successful | +| ERROR | Error during update process | +| WARNING | Warning during update process | +| CANCELED | Cancel update process successful | +| CANCEL_REJECTED | Cancel update process has been rejected | **Example Header and Payload** -| Headers | MessageProperties -|---------------------------------------|--------------------------------- -| type=EVENT
tenant=tenant123
topic=UPDATE\_ACTION\_STATUS | content_type=application/json +| Headers | MessageProperties | +| -------------------------------------------------------------------- | ----------------------------- | +| type=EVENT
tenant=tenant123
topic=UPDATE_ACTION_STATUS | content_type=application/json | ```json { - "actionId":137, - "softwareModuleId":17, - "actionStatus":"DOWNLOAD", - "message":["The download has started"] + "actionId": 137, + "softwareModuleId": 17, + "actionStatus": "DOWNLOAD", + "message": ["The download has started"] } ``` ### Message to cancel an update task -| Header | Description | Type | Mandatory -|-----------------------------|----------------------------------|-------------------------------------|---------------- -| type | Type of the message | Fixed string "Event" | true -| thingId | The ID of the registered thing | String | true -| topic | Topic to handle events different | Fixed string "CANCEL_DOWNLOAD" | true -| tenant | The tenant this thing belongs to | String | false +| Header | Description | Type | Mandatory | +| ------- | -------------------------------- | ------------------------------ | --------- | +| type | Type of the message | Fixed string "Event" | true | +| thingId | The ID of the registered thing | String | true | +| topic | Topic to handle events different | Fixed string "CANCEL_DOWNLOAD" | true | +| tenant | The tenant this thing belongs to | String | true | -| Message Properties | Description | Type | Mandatory -|-----------------------------|----------------------------------|-------------------------------------|---------------- -| content_type | The content type of the payload | String | true +| Message Properties | Description | Type | Mandatory | +| ------------------ | ------------------------------- | ------ | --------- | +| content_type | The content type of the payload | String | true | Payload Template ```json { - "actionId": long + "actionId": long } ``` **Example Header and payload** -| Headers | MessageProperties -|---------------------------------------|--------------------------------- -| type=EVENT
tenant=tenant123
thingId=abc
topic=CANCEL\_DOWNLOAD | content_type=application/json +| Headers | MessageProperties | +| ---------------------------------------------------------------------------------- | ----------------------------- | +| type=EVENT
tenant=tenant123
thingId=abc
topic=CANCEL_DOWNLOAD | content_type=application/json | ```json { - "actionId":137 + "actionId": 137 } ``` @@ -180,122 +175,127 @@ After this message has been sent, an action status event with either actionStatu **Example Header and Payload when cancellation is successful** -| Headers | MessageProperties -|---------------------------------------|--------------------------------- -| type=EVENT
tenant=tenant123
topic=UPDATE\_ACTION\_STATUS | content_type=application/json +| Headers | MessageProperties | +| -------------------------------------------------------------------- | ----------------------------- | +| type=EVENT
tenant=tenant123
topic=UPDATE_ACTION_STATUS | content_type=application/json | ```json { - "actionId":137, - "softwareModuleId":17, - "actionStatus":"CANCELED", - "message":["The update was canceled."] + "actionId": 137, + "softwareModuleId": 17, + "actionStatus": "CANCELED", + "message": ["The update was canceled."] } ``` **Example Header and Payload when cancellation was rejected** -| Headers | MessageProperties -|---------------------------------------|--------------------------------- -| type=EVENT
tenant=tenant123
topic=UPDATE\_ACTION\_STATUS | content_type=application/json +| Headers | MessageProperties | +| -------------------------------------------------------------------- | ----------------------------- | +| type=EVENT
tenant=tenant123
topic=UPDATE_ACTION_STATUS | content_type=application/json | ```json { - "actionId":137, - "softwareModuleId":17, - "actionStatus":"CANCEL_REJECTED", - "message":["The cancellation was not possible since the target sent an unexpected response."] + "actionId": 137, + "softwareModuleId": 17, + "actionStatus": "CANCEL_REJECTED", + "message": [ + "The cancellation was not possible since the target sent an unexpected response." + ] } ``` + ## Messages sent by hawkBit -All messages from hawkBit will be sent to the specified exchange in the ``reply_to`` property. + +All messages from hawkBit will be sent to the specified exchange in the `reply_to` property. ### Message sent by hawkBit to initialize an update task +| Header | Description | Type | Mandatory | +| ------- | -------------------------------- | ----------------------------------- | --------- | +| type | Type of the message | Fixed string "EVENT" | true | +| thingId | The ID of the registered thing | String | true | +| topic | Topic to handle events different | Fixed string "DOWNLOAD_AND_INSTALL" | true | +| tenant | The tenant this thing belongs to | String | true | -| Header | Description | Type | Mandatory -|-----------------------------|----------------------------------|-------------------------------------|---------------- -| type | Type of the message | Fixed string "EVENT" | true -| thingId | The ID of the registered thing | String | true -| topic | Topic to handle events different | Fixed string "DOWNLOAD_AND_INSTALL" | true -| tenant | The tenant this thing belongs to | String | false - - -| Message Properties | Description | Type | Mandatory -|-----------------------------|----------------------------------|-------------------------------------|---------------- -| content_type | The content type of the payload | String | true +| Message Properties | Description | Type | Mandatory | +| ------------------ | ------------------------------- | ------ | --------- | +| content_type | The content type of the payload | String | true | The Java representation is DownloadAndUpdateRequest: - Payload Template ```json { - "actionId": long, - "targetSecurityToken": "String", - "softwareModules":[ - { - "moduleId": long, - "moduleType":"String", - "moduleVersion":"String", - "artifacts":[ - { - "filename":"String", - "urls":{ - "HTTP":"String", - "HTTPS":"String" - }, - "hashes":{ - "md5":"String", - "sha1":"String" - }, - "size":long - }], - "metadata":[ - { - "key":"String", - "value":"String" - } - ] - }] + "actionId": long, + "targetSecurityToken": "String", + "softwareModules": [ + { + "moduleId": long, + "moduleType": "String", + "moduleVersion": "String", + "artifacts": [ + { + "filename": "String", + "urls": { + "HTTP": "String", + "HTTPS": "String" + }, + "hashes": { + "md5": "String", + "sha1": "String" + }, + "size": long + } + ], + "metadata": [ + { + "key": "String", + "value": "String" + } + ] + } + ] } ``` **Example Header and Payload** -| Headers | MessageProperties -|---------------------------------------|--------------------------------- -| type=EVENT
tenant=tenant123
thingId=abc
topic=DOWNLOAD\_AND\_INSTALL | content_type=application/json - +| Headers | MessageProperties | +| --------------------------------------------------------------------------------------- | ----------------------------- | +| type=EVENT
tenant=tenant123
thingId=abc
topic=DOWNLOAD_AND_INSTALL | content_type=application/json | ```json { - "actionId":137, - "targetSecurityToken":"bH7XXAprK1ChnLfKSdtlsp7NOlPnZAYY", - "softwareModules":[{ - "moduleId":7, - "moduleType":"firmware", - "moduleVersion":"7.7.7", - "artifacts":[ - { - "filename":"artifact.zip", - "urls":{ - "HTTP":"http://download-from-url.com", - "HTTPS":"https://download-from-url.com" - }, - "hashes":{ - "md5":"md5hash", - "sha1":"sha1hash" - }, - "size":512 - }], - "metadata":[ - { - "key":"installationType", - "value":"5784K#" - } - ] - }] + "actionId": 137, + "targetSecurityToken": "bH7XXAprK1ChnLfKSdtlsp7NOlPnZAYY", + "softwareModules": [ + { + "moduleId": 7, + "moduleType": "firmware", + "moduleVersion": "7.7.7", + "artifacts": [ + { + "filename": "artifact.zip", + "urls": { + "HTTP": "http://download-from-url.com", + "HTTPS": "https://download-from-url.com" + }, + "hashes": { + "md5": "md5hash", + "sha1": "sha1hash" + }, + "size": 512 + } + ], + "metadata": [ + { + "key": "installationType", + "value": "5784K#" + } + ] + } + ] } ``` diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java index 69eb3a848..1cc6752c9 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java @@ -132,7 +132,6 @@ public class AmqpMessageHandlerService extends BaseAmqpService { final MessageType messageType = MessageType.valueOf(type); switch (messageType) { case THING_CREATED: - checkContentTypeJson(message); setTenantSecurityContext(tenant); registerTarget(message, virtualHost); break; diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java index 1ce6b9d41..ecaf64bb5 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java @@ -121,19 +121,6 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServic } - @Test - @Description("Tests not allowed content-type in message. This message should forwarded to the deadletter queue") - @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) }) - public void wrongContentType() { - final String controllerId = TARGET_PREFIX + "wrongContentType"; - final Message createTargetMessage = createTargetMessage(controllerId, TENANT_EXIST); - createTargetMessage.getMessageProperties().setContentType("WrongContentType"); - getDmfClient().send(createTargetMessage); - - verifyOneDeadLetterMessage(); - assertAllTargetsCount(0); - } - @Test @Description("Tests null reply to property in message header. This message should forwarded to the deadletter queue") @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })