HSG-MCS-HS21_tapas/tapas-tasks/README.md

170 lines
6.8 KiB
Markdown
Raw Permalink Normal View History

2021-10-04 07:13:00 +00:00
# tapas-tasks
Micro-service for Managing Tasks in a Task List implemented following Hexagonal Architecture.
Based on examples from book "Get Your Hands Dirty on Clean Architecture" by Tom Hombergs
Technologies: Java, Spring Boot, Maven
**Note:** this repository contains an [EditorConfig](https://editorconfig.org/) file (`.editorconfig`)
with default editor settings. EditorConfig is supported out-of-the-box by the IntelliJ IDE. To help maintain
consistent code styles, we recommend to reuse this editor configuration file in all your services.
## HTTP API Overview
2021-10-18 09:45:52 +00:00
The code we provide includes a minimalistic uniform HTTP API for (i) creating a new task, (ii) retrieving
a representation of the current state of a task, and (iii) patching the representation of a task, which
is mapped to a domain/integration event.
The representations exchanged with the API use two media types:
* a JSON-based format for task with the media type `application/task+json`; this media type is defined
in the context of our project, but could be [registered with IANA](https://www.iana.org/assignments/media-types)
to promote interoperability (see
[TaskJsonRepresentation](src/main/java/ch/unisg/tapastasks/tasks/adapter/in/formats/TaskJsonRepresentation.java)
for more details)
* the [JSON Patch](http://jsonpatch.com/) format with the registered media type `application/json-patch+json`, which is also a
JSON-based format (see sample HTTP requests below).
2021-10-04 07:13:00 +00:00
For further developing and working with your HTTP API, we recommend to use [Postman](https://www.postman.com/).
### Creating a new task
A new task is created via an `HTTP POST` request to the `/tasks/` endpoint. The body of the request
2021-10-18 09:45:52 +00:00
must include a representation of the task to be created using the content type `application/task+json`
defined in the context of this project. A valid representation must include at least two required fields
(see [TaskJsonRepresentation](src/main/java/ch/unisg/tapastasks/tasks/adapter/in/formats/TaskJsonRepresentation.java)
for more details):
2021-10-04 07:13:00 +00:00
* `taskName`: a string that represents the name of the task to be created
* `taskType`: a string that represents the type of the task to be created
A sample HTTP request with `curl`:
```shell
2021-10-18 09:45:52 +00:00
curl -i --location --request POST 'http://localhost:8081/tasks/' \
--header 'Content-Type: application/task+json' \
--data-raw '{
"taskName" : "task1",
"taskType" : "computation",
"originalTaskUri" : "http://example.org",
"inputData" : "1+1"
2021-10-04 07:13:00 +00:00
}'
HTTP/1.1 201
2021-10-18 09:45:52 +00:00
Location: http://localhost:8081/tasks/cef2fa9d-367b-4e7f-bf06-3b1fea35f354
Content-Type: application/task+json
Content-Length: 170
Date: Sun, 17 Oct 2021 21:03:34 GMT
2021-10-04 07:13:00 +00:00
{
2021-10-18 09:45:52 +00:00
"taskId":"cef2fa9d-367b-4e7f-bf06-3b1fea35f354",
"taskName":"task1",
"taskType":"computation",
"taskStatus":"OPEN",
"originalTaskUri":"http://example.org",
"inputData":"1+1"
2021-10-04 07:13:00 +00:00
}
```
2021-10-18 09:45:52 +00:00
If the task is created successfuly, a `201 Created` status code is returned together with a
representation of the created task. The response also includes a `Location` header filed that points
to the URI of the newly created task.
2021-10-04 07:13:00 +00:00
### Retrieving a task
2021-10-18 09:45:52 +00:00
The representation of a task is retrieved via an `HTTP GET` request to the URI of task.
2021-10-04 07:13:00 +00:00
A sample HTTP request with `curl`:
```shell
2021-10-18 09:45:52 +00:00
curl -i --location --request GET 'http://localhost:8081/tasks/cef2fa9d-367b-4e7f-bf06-3b1fea35f354'
2021-10-04 07:13:00 +00:00
HTTP/1.1 200
2021-10-18 09:45:52 +00:00
Content-Type: application/task+json
Content-Length: 170
Date: Sun, 17 Oct 2021 21:07:04 GMT
2021-10-04 07:13:00 +00:00
{
2021-10-18 09:45:52 +00:00
"taskId":"cef2fa9d-367b-4e7f-bf06-3b1fea35f354",
"taskName":"task1",
"taskType":"computation",
"taskStatus":"OPEN",
"originalTaskUri":"http://example.org",
"inputData":"1+1"
2021-10-04 07:13:00 +00:00
}
```
2021-10-18 09:45:52 +00:00
### Patching a task
REST emphasizes the generality of interfaces to promote uniform interaction. For instance, we can use
the `HTTP PATCH` method to implement fine-grained updates to the representational state of a task, which
may translate to various domain/integration events. However, to conform to the uniform interface
contraint in REST, any such updates have to rely on standard knowledge — and thus to hide away the
implementation details of our service.
In addition to the `application/task+json` media type we defined for our uniform HTTP API, a standard
representation format we can use to specify fine-grained updates to the representation of tasks
is [JSON Patch](http://jsonpatch.com/). In what follow, we provide a few examples of `HTTP PATCH` requests.
For further details on the JSON Patch format, see also [RFC 6902](https://datatracker.ietf.org/doc/html/rfc6902)).
#### Changing the status of a task from OPEN to ASSIGNED
Sample HTTP request that assigns the previously created task to group `tapas-group1`:
```shell
curl -i --location --request PATCH 'http://localhost:8081/tasks/cef2fa9d-367b-4e7f-bf06-3b1fea35f354' \
--header 'Content-Type: application/json-patch+json' \
--data-raw '[ {"op" : "replace", "path": "/taskStatus", "value" : "ASSIGNED" },
{"op" : "add", "path": "/serviceProvider", "value" : "tapas-group1" } ]'
HTTP/1.1 200
Content-Type: application/task+json
Content-Length: 207
Date: Sun, 17 Oct 2021 21:20:58 GMT
{
"taskId":"cef2fa9d-367b-4e7f-bf06-3b1fea35f354",
"taskName":"task1",
"taskType":"computation",
"taskStatus":"ASSIGNED",
"originalTaskUri":"http://example.org",
"serviceProvider":"tapas-group1",
"inputData":"1+1"
}
```
In this example, the requested patch includes two JSON Patch operations:
* an operation to `replace` the `taskStatus` already in the task's representation with the value `ASSIGNED`
* an operation to `add` to the task's representation a `serviceProvider` with the value `tapas-group1`
Internally, this request is mapped to a
[TaskAssignedEvent](src/main/java/ch/unisg/tapastasks/tasks/application/port/in/TaskAssignedEvent.java).
The HTTP response returns a `200 OK` status code together with the updated representation of the task.
#### Changing the status of a task from to EXECUTED
Sample HTTP request that changes the status of the task to `EXECUTED` and adds an output result:
```shell
curl -i --location --request PATCH 'http://localhost:8081/tasks/cef2fa9d-367b-4e7f-bf06-3b1fea35f354' \
--header 'Content-Type: application/json-patch+json' \
--data-raw '[ {"op" : "replace", "path": "/taskStatus", "value" : "EXECUTED" },
{"op" : "add", "path": "/outputData", "value" : "2" } ]'
HTTP/1.1 200
Content-Type: application/task+json
Content-Length: 224
Date: Sun, 17 Oct 2021 21:32:25 GMT
{
"taskId":"cef2fa9d-367b-4e7f-bf06-3b1fea35f354",
"taskName":"task1",
"taskType":"computation",
"taskStatus":"EXECUTED",
"originalTaskUri":"http://example.org",
"serviceProvider":"tapas-group1",
"inputData":"1+1",
"outputData":"2"
}
```
Internally, this request is mapped to a
[TaskExecutedEvent](src/main/java/ch/unisg/tapastasks/tasks/application/port/in/TaskExecutedEvent.java).
The HTTP response returns a `200 OK` status code together with the updated representation of the task.