I am trying to get my head around how to handle relationships in REST.
I have read this question.
If I have Drivers and Cars in my api and a Driver can only exist if connected to a Car I would make Drivers a subresource in Cars. The relationship between a Car and a Driver contains a set of properties, say averageSpeed and timeOnTheRoad. One Car can have many Drivers, but a Driver can only have one Car.
How should I add a new driver? How should I add a relationship between a driver and a car?
If I add a resource Wunderbaums which is not a subresource to Cars, but a Car can contain Wunderbaums. How should I add a relationship between a Car and a Wunderbaum?
One way of adding a relationship between two entities is to POST to /entityA/{id}/entityB/{id} and send properties for the relationship in the body. This would work for my example with Cars and Wunderbaums since Wunderbaums is not a subresource of Cars, but it would not work in my example with Cars and Drivers since it would interfere with CRUD functionality for Drivers. The path cars/{id}/drivers{id} would be the same for creating a relationship between a Car and a Driver as for creating a Driver.
I also found this unanswered question on the subject.
Edit 1
#JB Nizet suggested that I put the relationship properties inside of the Driver, since its a one to many relationship. It would be a possible solution, but what if a Driver could have many Cars? Should we handle one to many relations different than many to many relations?
Edit 2
We could put relationship properties with the Driver in a many to many relationship scenario as well. The question then is if Driver has its own resource, is it ok that cars/2/drivers/4 returns a different set of properties than drivers/4? In the case where I get the Driver by its relation to Car I will include avrageSpeed and timeOnTheRoad in the response.
From a DDD perspective, I think perhaps you're asking the wrong question; the question is not 'how do Cars and Drivers relate in the database and thus how should they manifest in the API', but "what capabilities does my API expose and what behaviors does it support"?
In other words, what does the/each REST API call mean in the context of the business (or the user's mind)? If the request is "what cars have I driven?" then driver ->> car is the relationship for that API call. If the request is "assign Tim to drive the Minivan" then the relationship for that API call is Driving -> Driver,Car
Building a CRUD system out of REST can work fine, but it sounds like what you want is a step beyond that.
Related
I am designing a RESTful API and my questions is the following: What is the best practice for managing relationships using POST and PATCH in a RESTful API? Where and when should I allow the consumer of the API to establish relationships between entities when the opposite entity/entities already exists/exist? My goals are to (a) minimize code and code maintenance with (b) a balanced ratio of easiness to understand the API and number of API calls to establish relationships. The most limiting criterion is that I am developing and maintaining the API on my own.
If it is of any interest, I am using ASP.NET Core and separated the API (with outer facing models) and the entity framework based data layer (with data models) into two different layers, where the API layer references the data layer (API -> Data).
I would like to discuss all possible combinations of the http request methods POST and PATCH and the three types of relationships one-to-one, one-to-many and many-to-many.
POST one-to-one
I was thinking about allowing the consumer of the API to let the POST request for the new entity only go through when the opposite entity has no relationship to any other entity of the posted entity type.
Another option would be to never allow setting relationships through POST but only let it update via PATCH. I favor this option, because it makes the entity easier and saver to create when treating the relationships separately. Even better, it would only require two API calls - one for POSTing the new entity and one for PATCHing even multiple relationships to many different one-to-one opposite entities.
POST one-to-many
One option would be allowing the consumer of the API to let the POST for the new entity only go through when all of the opposite entities have no relationship to any other entity of the posted entity type. Less save would be to allow the consumer to override existing relationships of the opposite entity to another entity of the type of the posted entity.
Another option would be to not allow posting any relationship of a single entity to many entities, because the relationships are effectively set in the opposite entities anyway. I prefer to only allow setting the relationship in the opposite entities via PATCH since this is the place where the many to one relationship is effectively established, and it keeps the creation of the entity separated from establishing relationships.
POST many-to-many
I would never allow to set a relationship for a POST request in a many-to-many relationship, but only allow to PATCH new relationships on both the new entity and the opposite entity. Due to the complexity of this type of relationship, I think it is best keep the entity creation as easy as possible and manage relationships separately through PATCH requests.
PATCH one-to-one
I would set no restrictions and allow the consumer of the API to set the relationship freely on both sides.
PATCH one-to-many
This one is a real dilemma for me - number of API calls vs easiness to understand relationships and lines of code.
On the one hand, I could allow to PATCH from the single entity point of view (it contains for example an array of opposite entity IDs). This would require only one API call to update the relationships of the multiple opposite entities, but this requires more code, because the data layer needs find and loop through all opposite entities. In addition, updating from the single entity point of view is sometimes hard to understand for me - many times its easier for me to establish the relationships in all opposite entities that refer to the same single entity.
On the other hand, I could allow the consumer of the API to update all opposite entities individually. This would require many API calls, but I sometimes think updating from this point of view is easier to understand, and the relationship is effectively set in the multiple opposite entities anyway.
I don't know what to favor yet. I am thinking about offering both options.
PATCH many-to-many
The only way I can see is to allow the consumer of the API to allow setting relationships on both sides due to the nature of this relationship.
While elaborating my ideas above, I think the best guideline is to keep creation of entities completely separated from establishing relationships and to set the relationships only where they are effectively established (mimicking SQL table behavior). I assume the latter one is what most API consumers should be familiar with and the first one keeps the API save and simple (at the cost of efficiency).
Please let me know if I missed any cases, criteria for decision making or didn't think of any implementation strategies.
Best regards,
philippfx
I am new to domain driven design and trying to learn and implement in my project. My project structure up till now similar to this.
Maintainance Folder Maintainance.Data(Class
Library) Maintainance.Domain(Class Library)
Maintainance.Domin.Tests(test project)
MovieBooking Folder MovieBooking.Data(Class
Library) MovieBooking.Domain(Class Library)
MovieBooking.Domain.Tests(test project)
SharedKernel Common things
Web Application MovieBooking MVC Web
Application(which have reference to MovieBooking Domain)
In Maintainance boundned context I am keeping all CRUD, GetAll type things for say Movie, Country, Category, Subcategory entities in Maintainance DBContext.
Now in MovieBooking data layer I will also need to use these entities (mostly to display name or dropdown fills in view, kind of subset needed - not all properties needed, only few like Id, name)
There are few ways I can access this entities in Movie booking Bounded Context
Via web services - Need to create web api for common entities like Movie,Country,Category,Subcategory and call web api in web project (to fill Dropdowns or get name from entities)
Via Reference Context (Seperate Dbcontext) - Need to configure Dbset and then map a database view (with only require fields) to Dbset
Example :
modelBuilder.Entity().ToTable(ViewName);
For (1) it can be long term implmentation solution for me
(2) I have to create view (with only few properties) for each require table and it will increase my number of views in my DB drastically as I have enterprise level application.
Is there any other way I can achieve this? Anything I am missing in DDD to look for ?
Option 2, while it will save you time, is actually a very bad idea from the DDD perspective as it allows for violations of the transactional boundary guarantees that each aggregate is meant to enforce\represent.
Option 1 seems a better option, although there are still quite a bit of wiggle room for interpretation based on your brief description of your proposed solution. If I understood correctly, it is generally recommended to follow the below:
Do not expose your aggregate state directly since this exposes internals and increases coupling. Simple create meaningful DTO's and use something like Automapper to map your Aggregates to DTO's easilly and with little effort before sending it over.
Have a duplicate of the DTO definition in your client. This will reduce coupling and allow for easier deployments.
I strongly recommend reading the DDD orange book although I have to say that I cannot recall specifically on which chapter this is discussed. You will also benefit a lot by reading about hexagonal architecture (and I would search for that term in the orange book to find more info about your question).
There is actually one alternative that I can think of: if you're publishing events from your BC's you can create a workflow to translate the domain events to "public" events and then in the other BC listen for the public events that you need to and store the data that you need somewhere inside there. The difficulty of this ranges from very easy to quite problematic depending on your infrastructure. Be aware that it is not a very good idea to re-use your domain events for transmitting data to other BC's since this closely couples the two BC's.
I hope this helps. Please do not hesitate to elaborate if I did not understood the question well enough.
I'm writing an API with spring boot, trying to keep it restful but the structure is quite nested. So say I have:
/api/examboard/{ebid}/qualification/{qid}/subject/{sid}/module/{mid}/
I have a controller for every noun that will take in all Id's, the problem with this is that I don't really need an ebid or a qid for modules, they only really need to be concerned with subjects most of the time. The mapping between them all is quite simple. An examboard will have many qualifications, a qualification will have many subjects etc....
Now the problem is say I go for a simpler API design where I only need the parent Id so the Subject controller will also have:
api/subject/{sid}/module
then I need to include multiple services in my controller based on the way JPA works. As I need to include SubjectEntity based calls and ModuleEntity based calls. However I want to maintain a one to one relationship between my controllers/services and services/repositories. This is why I opted for the longer url as I've mentioned above, but it does seem like overkill. Does anyone have any advice on how I should structure an API like this, most examples are quite small and don't really fit.
Without knowing more about your models and the relations between them, this answer will have to stay a bit diffuse.
First of all - "it depends". I know, but it really does. The way you should design an API depends heavily on your use cases that will define required access patterns. Do you often need all modules for a subject? Then introduce /subjects/{sid}/modules, if you need the details for a module of a subject in a qualification in an examboard - by all means have a /examboards/{ebid}/qualifications/{qid}/subjects/{sid}/modules/{mid}
As you say there are many relations between your entities. That is fine, but it does not mean that you need your API to capture each of these relations in a dedicated endpoint. You should distiguish between retrieving and modifying entities here. Find below examples for certain operations you might want to have (not knowing your models, this may not apply - let's consider this an illustration)
Retrieve qualifications for an examboard
GET /examboards/{ebid}/qualifications plain and simple
GET /qualifications?ebid={ebid} if you feel you might need sophisticated filtering later on
or create a new qualitication for an examboard
POST /examboards/{ebid}/qualifications with the details submitted in the body
POST /qualifications with the details submitted in the body and making the associated examboard ebid part of the submitted data
or update an existing qualification
PUT /qualifications/{qid} (if this operation is idempotent)
POST /qualifications/{qid} (if it should not be considered idempotent)
or delete qualifications
DELETE /qualifications/{qid} deletes entities, cascade-deletes associations
DELETE /examboards/{ebid}/qualifications clears all qualifications from an examboard, without actually deleting the qualification entities
There are certainly more ways to let an API do all these things, but this should demonstrate that you need to think of your use cases first and design your API around them.
Please note the pluralisation of collection resources in the previous examples. This comes down to personal preference, but I tends to follow the argumentation of Sam Ruby in RESTful Web Services (available as PDF) that collections should be first-class citizens in an API
Usually, there should not be a reason to have 1:1:1 relationships between controllers, services and repositories. Usually, this is not even possible. Now, I don't know the reason why you might want to do this, but following through with this will force you to put a lot of logic into your database queries and models. While this (depending on your setup and skills) may or may not be easily testable, it certainly shifts the required test types from unit (simpler, usually faster, more fine-grained) to integration tests (require more setup, more complex, usually slower), when instead of having the bulk of your business logic in your services you put them into many joins and subselects in your repositories.
I will only address your REST API structure question.
As you already pointed out
The problem with this is that I don't really need an ebid or a qid for modules, they only really need to be concerned with subjects most of the time
You need to think of your entities as resources if your entity can stand for itself give it its own top level resource. If instead your entity exists only as a part of another entity build a subresource below its parent. This should correspond with the association type aggregation and composition in your object model design.
Otherwise every entity that is part of a many relationship should also be accessible via a subresource on the other side of the relationship.
As I understood you you have a OneToMany relationship between examboard and qualification so we get:
api/examboards/{eid}/qualifications
api/qualifications/{qid}/examboard
Yo could also remove the examboard subresource and include it in the qualification response.
For ManyToMany realtionships you need two subresources:
api/foos/{fid}/bars
api/bars/{bid}/foos
And another resource to manipulate the relationship itself.
api/foosToBars/{fid}+{bid}
Or likewise.
I'm looking at building an application using Play. Imagine a typical eCommerce domain model: Customer, Order, Order Line Item, Product.
In investigating various options for persistence the recommendation seems to be to avoid ORM layers in Scala and use a different abstraction, such as Slick.
Where I am stuck is that with an ORM I could pass a single "Order" object to my view, which could then use existing relationships to pull related information from the Customer, OrderLines, and Products. With Slick, I'm currently passing a tuple of (Order, Customer, Seq[(OrderLine, Product)]) to the view to provide the same information. If you start to complicate the model a bit more, say with an Address on the customer object, it gets very messy quickly.
Is this the recommended approach or am I missing something? I've found several Play-Slick example applications, but they just have 1 or 2 entities, so they don't really address the issue I bring up here.
Have a look at the Slick-Examples, especially: This one
If you implemented your classes correctly you should be able to access either Customer-object via the Order-object or vice-versa (for example order.customer.name or something like that to access the customer's Name).
When designing a RESTful API should resources which are dependent on others be modeled as sub-uris or should they simply reference each other?
E.g. presuming a door is always dependent on a house then
/house/73/door/1
or
/house/73
/door/1044
where house and door include references to each other?
Most RESTful APIs I have found are quite flat so I would value references to any which do have more complex relationship dependencies.
Regards
In UML terms, if the relationship is that of Aggregation, then you use a flat hierarchy with links between things, whereas if the relationship is that of Composition (i.e., the lifetime of a door is strictly bounded by the lifetime of a house) you use sub-resources.
I'm not suggesting drawing a UML diagram! But it does help to have in mind that distinction. (You could also model the Aggregation case by having sub-resources that are just redirect to the real ones; redirects are RESTful. OTOH, I don't actually like doing that; I prefer to make any relationships explicit and to keep the number of redirects down.)
Just remember that URIs are an implementation detail of the server. If you can model them as flat resources then do so. It will be easier for the server to handle them.
If the identifier for the door is not unique across all houses, then your server is going to need to know the house and therefore you need to include the house in the URI.
The relationships between the resources should be modeled by links within the returned representations. i.e. Your house representation should probably contain links to all of the door resources in that house. I would recommend trying to avoid using the URL structure as having some domain meaning.
Only use a hierarchy if it is needed to uniquely identify the resource.