mko
mko

Reputation: 7325

How to do POST partial updates via REST API and using DDD?

I have a project where rest api is being refactored from classic CRUD into domain drive design (DDD). One of the challenges is that endpoints have to remain the same using same verbs and payload.

I have the following situation

For example GET /orders/1048 returns

{
   "id":1048,
   "order_total":100.11,
   "is_paid":true,
   "order_status":"active",
   "items":[
      {
         "id":5000,
         "name":"baseball hat"
      },
      {
         "id":5001,
         "name":"baseball bat"
      }
   ]
}

Now if I have POST order/update/1048 where I send full or partial request model via POST (not via PUT because POST is not idempotent and PUT request entire model to be provided, always) and based on data provided I want to trigger particular domain behavior

a) update status case 1.

{
   "id":1048,
   "order_total":100.11,
   "is_paid":true,
   "order_status":"cancel",
   "items":[
      {
         "id":5000,
         "name":"baseball hat"
      },
      {
         "id":5001,
         "name":"baseball bat"
      }
   ]
}

b) update status case 2.

{
    "id": 1048,
    "order_status": "cancel"
}

c) update items case

{
   "id":1048,
   "items":[
      {
         "id":5000,
         "name":"baseball hat"
      }
   ]
}

d) update status + items

{
   "id":1048,
   "order_status":"cancel",
   "items":[
      {
         "id":5000,
         "name":"baseball hat"
      }
   ]
}

My plan is to do the following inside application layer and domain layer.

This is not really "DDD ready request" since I am not sending commands using PATCH, but these is the only workaround I can think of, and I would like to know am I doing it right?

Upvotes: 1

Views: 1613

Answers (2)

guillaume31
guillaume31

Reputation: 14064

If content types are changeable, you can use them to convey information about the command and match on that rather than field by field comparison.

PUT /order/1048
Content-Type:application/json;command=UpdateStatus

https://www.infoq.com/articles/rest-api-on-cqrs

As a side note, UpdateStatus is probably not specific enough as a command name.

Upvotes: 2

Constantin Galbenu
Constantin Galbenu

Reputation: 17683

Considering that you may not or can not modify the client:

My plan is to do the following inside application layer and domain layer

If you do this only in the Application layer then it is DDD as long as the domain layer contains only domain logic. The diff algorithm does not belong in the domain layer, it should belong in a temporary refactoring facade; this facade could be put even farther, in front of the Application layer in order to be removed simpler after the refactoring is complete.

If/when you refactor the client:

The commands that you send to the domain (to the Aggregates) can be wrapped in RESTful requests using POST or PUT (depending on the idempotency of your commands). For every domain command (not for every domain entity) you can have a REST resource, like http://server/place/order/{orderId}.

Then you can drop that refactoring facade.

Upvotes: 2

Related Questions