سؤال

We're creating a new API to add new Jobs into a legacy system. The question deals with how to handle creating a Job's required parent entities when you don't know the IDs of those parent entities to assign to. The structure of when a Job is created is as such:

  • A Job must be assigned to a Project.
  • A Project must be assigned to a CustomerAccount.
  • There is no knowledge of what the ID is of the Project it should be assigned to. This goes by the Project Name instead.
  • Additionally, two CustomerAccounts could have the same Project Name. For that reason, we also need to pass over the Name of the CustomerAccount.

To summarize, we need to create a new Job while also passing over the Project Name and CustomerAccount Name since we don't have access to the IDs to use. If the Project is not found, one is automatically created then assigned to the Job about to be created.

With this established, the question is: What is the best practice for implementing a REST endpoint that will also create required parent entities?

Our current solution is:

POST /jobs/account/{accountName}/project/{projectName}

(with the Body containing the JobDTO).

In this scenario, what are some alternative solutions or better ideas for the naming of this endpoint?

Thanks in advance.

هل كانت مفيدة؟

المحلول

To summarize, we need to create a new Job while also passing over the Project Name and CustomerAccount Name since we don't have access to the IDs to use. If the Project is not found, one is automatically created then assigned to the Job about to be created.

Keep it simple. You don't need the project id or account id (I assume these are database ids). You already have a name that the client already knows about. These names already uniquely identify the jobs. So just PUT the new job resource to

PUT /accounts/{accountName}/projects/{projectName}/jobs/{jobName}

A side effect of this is that the server can create what ever it needs to create sot that accountName and projectName now exist on its end, so that

GET /accounts/{accountName}

now returns that account resource.

نصائح أخرى

As a rule of thumb with RESTful APIs I've found that you should only ever need to do "one hop" when defining relationships between two entities. As soon as you need to start defining relationships across "two hops" it's normally a sign that the endpoint isn't very RESTful any more.

Endpoints should only really be concerned with one entity. Remember this isn't a web application where users can describe complicated relationships via dropdowns populated by AJAX requests. It's fine to have to make a couple of API calls to achieve your goal. API calls are fast and cheap.

Also you mention that you don't know their IDs. How else are you going to identify the linked entities? Unless they have a unique field that you can identify them by you're going to run into problems. All RESTful APIs rely on having an identifier of some type otherwise everything falls over because no one is ever quite sure what entity you're talking about.

So get the IDs and only allow the API to accept immediate relationships.

You also mention routes. The "one hop" rule applies here too. In a fictitious scenario with authors, posts and tags I would set up my routes like so:

  • /authors
  • /authors/1
  • /authors/1/posts
  • /posts
  • /posts/1
  • /posts/1/tags
  • /tags
  • /tags/1

This keeps your routes small and easy to immediately understand.

Maybe this one will be considered a marginal answer, and I do not know all the details of this case, but I came to a conclusion that using a graph instead of "linear" API can save your day.

The exact technology for a graph does not matter much (can be JSON-LD, RDF, GraphQL - you name it), but what is important is the ability to transfer subgraphs from one system to another.

In this way, one can easily include all relationships of the child object. There still may be some missing foreign key concerns in the legacy (presumably relational database-powered) system, but graph API can be conceptually easier because it allows to exchange logically aggregated entities right at the transactional borders of those aggregates.

Of course, some kind of framework is needed to simplify graph processing, but the resulting system and API may be more flexible, especially if the use cases of the API are many and diverse. Graph API is also easily extendable, robust, and require much less requests to exchange the data.

The downside may be familiarity of the development team with the technology and query languages.

Also, no RESTful dogma prevents you from having simple CRUD APIs and graph API for more complex updates / queries.

One more note: tree is also a graph. Can be used to increase performance of operations and does not require special format (JSON or XML would be enough).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى softwareengineering.stackexchange
scroll top