Can REST TCC handle PUT? - rest

We are developing a REST API where client (application) will make call to our REST APIs.
The client (application) will handle the business logic with rollback capabilities (eg. client can rollback if update "Shipment" services [pass] and update "Stock" services [failed]).
There are many online articles about TCC [Try/Confirm/Cancel] which describe reserving/cancelling a resource via POST/DELETE method but none describe how to handle PUT request (eg. update "Stock" count by 1 and rollback on failure).
Anyone know of a solution to handle a PUT rollback (since PUT request overwrite the original data, how can we rollback to the original data)?

Per TCC pattern, the confirm operation uses PUT for its idempotent characteristics. When implementing such behavior if partial reservation is confirmed while others has expired, we could use the cancel operation to mimic the rollback behavior so that each confirmed participant link will be sent with another DELETE request. I wrote a tutorial article about a minimal TCC implementation with Java in a Booking system. You can refer to the implementation there.

TCC is only a concept to implement transactional behaviour using HTTP/REST. It covers a standard how to model the transaction including timeouts and cancellation. In this model the transaction is bound to any kind of resource with an id so you are able to either confirm or cancel it at any point. As the transaction has a timeout you may end up with an invalid or no longer existing transaction.
Whatever you do from start to the end of the transaction is up to you. But you need something to identify a transaction. As an overwrite of a resource using PUT does not create a resource object by itself you would need a kind of virtual resource to do so.
You may create a new version (maybe using locking) of the resource (the entities is just a placeholder here):
Start: PUT /entities/42 -> link rel:tcc, href: /entities/42/version/7
Confirm: PUT <application/tcc> /entities/42/version/7
Cancel: DELETE /entities/42/version/7
Instead of a version you can also think of a kind of transaction id if you have such.

Related

How do PUT, POST or PATCH request differ ultimately?

The data, being sent over a PUT/PATCH/POST request, ultimately ends up in the database.
Now whether we are inserting a new resource or updating or modifying an existing one - it all depends upon the database operation being carried out.
Even if we send a POST and ultimately perform just an update in the database, it does not impact anywhere at all, isn't it?!
Hence, do they actually differ - apart from a purely conceptual point of view?
Hence, do they actually differ - apart from a purely conceptual point of view?
The semantics differ - what the messages mean, and what general purpose components are allowed to assume is going on.
The meanings are just those described by the references listed in the HTTP method registry. Today, that means that POST and PUT are described by HTTP semantics; PATCH is described by RFC 5789.
Loosely: PUT means that the request content is a proposed replacement for the current representation of some resource -- it's the method we would use to upload or replace a single web page if we were using the HTTP protocol to do that.
PATCH means that the request content is a patch document - which is to say a proposed edit to the current representation of some resource. So instead of sending the entire HTML document with PUT, you might instead just send a fix to the spelling error in the title element.
POST is... well, POST is everything else.
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.” -- Fielding 2009
The POST method has the fewest constraints on its semantics (which is why we can use it for anything), but the consequence is that the HTTP application itself has to be very conservative with it.
Webber 2011 includes a good discussion of the implementations of the fact that HTTP is an application protocol.
Now whether we are inserting a new resource or updating or modifying an existing one - it all depends upon the database operation being carried out.
The HTTP method tells us what the request means - it doesn't place any constraints on how your implementation works.
See Fielding, 2002:
HTTP does not attempt to require the results of a GET to be safe. What it does is require that the semantics of the operation be safe, and therefore it is a fault of the implementation, not the interface or the user of that interface, if anything happens as a result that causes loss of property (money, BTW, is considered property for the sake of this definition).
The HTTP methods are part of the "transfer of documents over a network" domain - ie they are part of the facade that allows us to pretend that the bank/book store/cat video archive you are implementing is just another "web site".
It is about the intent of the sender and from my perspective it has a different behaviour on the server side.
in a nutshell:
POST : creates new data entry on the server (especially with REST)
PUT : updates full data entry on the server (REST) or it creates a new data entry (non REST). The difference to a POST request is that the client specifies the target location on the server.
PATCH : the client requests a partial update (Id and partial data of entry are given). The difference to PUT is that the client sends not the full data back to the server this can save bandwidth.
In general you can use any HTTP request to store data (GET, HEAD, DELETE...) but it is common practice to use POST, PUT, and PATCH for specific and standardized scenarios. Because every developer can understand it later
They are slightly different and they bind to different concepts of REST API (which is based on HTTP)
Just imagine that you have some Booking entity. And yo perform the following actions with resources:
POST - creates a new resource. And it is not idempotent - if you sent the same request twice -> two bookings will be stored. The third time - will create the third one. You are updating your DB with every request.
PUT - updates the full representation of a resource. It means - it replaces the booking full object with a new one. And it is idempotent - you could send a request ten times result will be the same (if a resource wasn't changed between your calls)
PATCH - updates some part of the resource. For example, your booking entity has a date property -> you update only this property. For example, replace the existing date with new date which is sent at the request.
However, for either of the above - who is deciding whether it is going to be a new resource creation or updating/modifying an existing one, it's the database operation or something equivalent to that which takes care of persistence
You are mixing different things.
The persistence layer and UI layer are two different things.
The general pattern used at Java - Model View Controller.
REST API has its own concept. And the DB layer has its own purpose. Keep in mind that separating the work of your application into layers is exactly high cohesion - when code is narrow-focused and does one thing and does it well.
Mainly at the answer, I posted some concepts for REST.
The main decision about what the application should do - create the new entity or update is a developer. And this kind of decision is usually done through the service layer. There are many additional factors that could be done, like transactions support, performing filtering of the data from DB, pagination, etc.
Also, it depends on how the DB layer is implemented. If JPA with HIbernate is used or with JDBC template, custom queries execution...

Which HTTP Verb should I use to claim and lock an item in a job queue?

I plan on using an HTTP REST interface to connect to a Job Control service.
One key operation is to request a computational Job.
The caller does not know the ID of the Job; that is what it will be told.
The job will be marked in the database as locked by the service.
The data needed for processing of the job will be returned to the caller.
Later on, when the caller is done processing the job, it will send the results back via another REST call.
Now it knows the ID of the record to be updated.
The second REST call will update the Job record with the results.
and change the Job's status and release the lock.
Only the Success/Fail status needs to be returned.
I am leaning towards using PUT for each operation because no new record is being created; it is being updated in both cases.
Is this proper? Can the first PUT return a large JSON payload with the Job data or does it just return an HTTP status? Should I use a POST instead, even though I am not creating a record, just updating it?
I would have used a GET for the first operation, but a GET is not supposed to change any objects on the service, and I am locking it, which is a change. Is locking a record acceptable in a GET request?
Which HTTP Verb should I use to claim and lock an item in a job queue?
Key idea: a REST API is a facade - your application/service pretends to be an HTTP compliant document store. All of the interesting things that happen are side effects triggered by modifying documents. See Jim Webber, 2011.
With that in mind...
POST is fine. It's okay to use POST.
PUT/PATCH are a good for remote authoring; the client fetches your representation of a resource, makes edits to his local copy, and sends you a copy of the representation (PUT) or a patch document describing the changes (PATCH). The server can then apply those edits to its copy, or not.
So for your specific example, I would expect the client to GET a representation of your resource, change the information in that representation from unlocked to locked, and then to PUT the changed representation back to your server. You server would be expected to update your copy of the representation to match.
It may remind you of a declarative style - the client tells the server what the representation should look like, and it's up to the server to figure out how to do that.
Included for Completeness, NOT Recommened:
The HTTP method registry also includes a method LOCK, with a corresponding UNLOCK. The semantics for these method tokens are defined by the WebDAV specification. If your meaning of LOCK matches that of WebDAV, then using that might be an answer. Note that the specification includes comments like
Any resource that supports the LOCK method MUST, at minimum, support the XML request and response formats defined herein.
Unless you are already in a space where people are expecting to be able to use general-purpose WebDAV clients to interact with your API, that's probably not a good fit.
The HTTP method registry is extendable. So you could define the semantics of your own method token, then push to have it adopted as a standard.

How to model a CANCEL action in a RESTful way?

We are currently in the process of wrangling smaller services from our monoliths. Our domain is very similar to a ticketing system. We have decided to start with the cancellation process of the domain.
Our cancel service has as simple endpoint "Cancel" which takes in the id of the ticket. Internally, we retrieve the id, perform some operations related to cancel on it and update the state of the entity in the store. From the store's perspective the only difference between a cancelled ticket and a live ticket are a few properties.
From what I have read, PATCH seems to be the correct verb to be used in this case, as am updating only a simple property in the resource.
PATCH /api/tickets/{id}
Payload {isCancelled: true}
But isCancelled is not an actual property in the entity. Is it fair to send properties in the payload that are not part of the entity or should I think of some other form of modeling this request? I would not want to send the entire entity as part of the payload, since it is large.
I have considered creating a new resource CancelledTickets, but in our domain we would never have the need to a GET on cancelled tickets. Hence stayed away from having to create a new resource.
Exposing the GET interface of a resource is not compulsory.
For example, use
PUT /api/tickets/{id}/actions/cancel
to submit the cancellation request. I choose PUT since there would be no more than one cancellation request in effect.
Hope it be helpful.
Take a look what exactly is RESTful way. No matter if you send PATCH request with isCancelled as payload or even DELETE if you want tickets to disappear. It's still RESTful.
Your move depends on your needs. As you said
I have considered creating a new resource CancelledTickets, but in our
domain we would never have the need to a GET on cancelled tickets.
I would just send DELETE. You don't have to remove it physically. If it's possible to un-cancel, then implement isCancelled mechanism. It's just question of taste.
REST is basically a generalization of the browser based Web. Any concepts you apply for the Web can also be applied to REST.
So, how would you design a cancel activity in a Web page? You'd probably have a table row with certain activities like edit and delete outlined with icons and mouse-over text that on clicking invoke a URI on the server and lead to a followup state. You are not that much interested how the URI of that button might look like or if a PATCH or DELETE command is invoked in the back. You are just interested that the request is processed.
The same holds true if you want to perform the same via REST. Instead of images that hint the user that an edit or cancel activity is performed on an entry, a meaningful link-relation name should be used to hint the client about the possiblities. In your case this might be something like reserve new tickets, edit reservation or cancel reservation. Each link relation name is accompanied by a URL the client can invoke if he wants to perform one of the activities. The exact characters of the URI is not of importance here to the client also. Which method to invoke might either be provided already in the response (as further accompanying field) or via the media type the response was processed for. If neither the media type nor an accompanying field gives a hint on which HTTP operation to use an OPTIONS request may be issued on the URI beforehand. The rule of thumb here is, the server should teach a client on how to achieve something in the end.
By following such a concept you decouple a client from the API and make it robust to changes. Instead of a client generating a URI to invoke the client is fed by the server with possible URIs to invoke. If the server ever changes its iternal URI structure a client using one of the provided URIs will still be able to invoke the service as it simply used one of the URIs provided by the server. Which one to use is determined by analyzing the link relation name that hints the client when to invoke such URI. As mentioned above, such link relation names need to be defined somewhere. But this is exactly what Fielding claimed back in 2008 by:
A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. (Source)
Which HTTP operation to choose for canceling a ticket/reservation may depend on your desing. While some of the answers recommended DELETE RFC 7231 states that only the association between the URI and the resource is removed and no gurantee is given that the actual resource is also being removed here as well. If you design a system where a cancelation might be undone, then DELETE is not the right choice for you as the mapping of the URI to the resource should not exist further after handling a DELETE request. If you, however, consider a cancelation to also lead to a removal of the reservation then you MAY use DELETE.
If you model your resource in a way that maintains the state as property within the resource, PATCHing the resource might be a valid option. However, simply sending something like state=canceled is probably not enough here as PATCH is a calculation of steps done by the client in order to transform a certain resource (or multipe resources) into a desired target state. JSON Patch might give a clue on how this might be done. A further note needs to be done on the atomicy requirement PATCH has. Either all of the instructions succeed or none at all.
As also PUT was mentioned in one of the other answers. PUT has the semantics of replacing the current representation available at the given URI with the one given in the request' payload. The server is further allowed to either reject the content or transform it to a more suitable representation and also affect other resources as well, i.e. if they mimic a version history of the resource.
If neither of the above mentioned operations really satisfies your needs you should use POST as this is the all-purpose, swiss-army-knife toolkit of HTTP. While this operation is usually used to create new resources, it isn't limited to it. It should be used in any situation where the semantics of the other operations aren't applicable. According to the HTTP specification
The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics.
This is basically the get-free-out-of-jail card. Here you can literally process anything at the server according to your own rules. If you want to cancel or pause something, just do it.
I highly discourage to use GET for creating, altering or canceling/removing something. GET is a safe operation and gurantees any invoking client that it wont alter any state for the invoked resource on the server. Note that it might have minor side-effects, i.e. logging, though the actual state should be unaffected by an invocation. This is a property Web crawler rely on. They will simply invoke any URI via GET and learn the content of the received response. And I assume you don't want Google (or any other crawler) to cancel all of your reservations, or do you?
As mentioned above, which HTTP operation you should use depends on your design. DELETE should only be used if you are also going to remove the representation, eventhough the spec does not necessarily require this, but once the URI mapping to the resource is gone, you basically have no way to invoke this resource further (unless you have created a further URI mapping first, of course). If you designed your resource to keep the state within a property I'd probably go for PATCH but in general I'd basically opt for POST here as here you have all the choices at your hands.
I would suggest having a state resource.
This keeps things RESTful. You have your HTTP method acting as the verb. The state part of the URI is a noun. Then your request body is simple and consistent with the URI.
The only thing I don't like about this is the value of state requires documentation, meaning what states are there? This could be solved via the API by providing possible states on a meta resource or part of the ticket body in meta object.
PUT /api/tickets/:id/state
{state: "canceled"}
GET /api/meta/tickets/state
// returns
[
"canceled",
...
]
GET /api/tickets/:id
{
id: ...
meta: {
states: [
"canceled",
...
]
}
}
For modelling CANCEL Action in Restful way :
Suppose we have to delete a note in DB by providing noteId(Note's ID) and Note is a pojo
1] At controller :
#DeleteMapping(value="/delete/{noteId}")
public ResponseEntity<Note> deleteNote( #PathVariable Long noteId)
{
noteServiceImpl.deleteNote(noteId);
return ResponseEntity.ok().build();
}
2]Service Layer :
#Service
public class NoteServiceImpl {
#Autowired
private NotesRepository notesDao;
public void deleteNote(Long id) {
notesDao.delete(id);
}
}
3] Repository layer :
#Repository
public interface NotesRepository extends CrudRepository<Note, Long> {
}
and in 4] postman : http://localhost:8080/delete/1
So we have deleted note Id 1 from DB by CANCEL Action

Should Odata(V4) actions be invoked only with POST?

Odata V4 Spec says that Actions MAY have observable side effects and should be invoked using HTTP POST. But we do have scenarios where we need to use actions which just modifies some status.
For example :
1.You might want to mark status of a document identified by a id as locked
Endpoint - .../Documents({id})/lock().
Since I am doing a partial update here, In my opinion PATCH is more suitable.2. You might want to offer two ways of deleting a document
a) Just Hide Endpoint - ...../Documents({id}) This is with HTTP DELETE (no disputes)
b) Delete PermanentlyEndpoint - ...../Documents({id})/permanentDelete() This as an ODATA action. In my opinion, HTTP Delete would be more appropriate here instead of HTTP POST.
What is the recommended way to do this from Odata standpoint? Any help here is much appreciated.
Below is the information from SPEC.
SPEC
11.5.4 Actions
Actions are operations exposed by an OData service that MAY have side effects when invoked. Actions MAY return data but MUST NOT be further composed with additional path segments.
11.5.4.1 Invoking an Action
To invoke an action bound to a resource, the client issues a POST request to an action URL. An action URL may be obtained from a previously returned entity representation or constructed by appending the namespace- or alias-qualified action name to a URL that identifies a resource whose type is the same as, or derives from, the type of the binding parameter of the action. The value for the binding parameter is the value of the resource identified by the URL prior to appending the action name, and any non-binding parameter values are passed in the request body according to the particular format.
Thanks in advance
--ksp
From an OData standpoint, you always have to invoke an action with a POST, with any other verb, it won't work.
Both of your examples are things that I personally don't think are well suited to an action as there are already ways to do these things with OData and they use the verbs that you are mentioning.Updating a property is supported with a PATCH and deleting an object is supported with a DELETE. You mention that you have two different types of delete operations, this is more difficult but you could use a custom header to distinguish between them.
An action tends to be something that doesn't fit into the normal CRUD operations so it isn't always clear which HTTP verb should be used for this.
In your examples, it does feel right to want to use DELETE and PATCH. However, the problem comes because we need to have a standard to follow, bear in mind that OData actions are all discoverable through the metadata so could be consumed by a client with no knowledge of what the actions actually do and in this case, we need to have something defined. Since we know that actions affect the server in some way, to me, it seems like POST is the least bad option that is consistent for all actions.
At the end of the day, as the author, your API is yours to command. Just as we shouldn't use properties in C# class design that cause side affects in other properties, that doesn't mean we cant, and it can be pretty common.
From an OData standpoint, PATCH is analogous to using property accessors and actions or POST is for accessing methods.
Making the decision between PATCH or POST to affect change is therefor the same design decision between using property mutators (making them writable) or forcing the caller to set their values through related methods.
You might want to mark status of a document identified by a id as locked
Endpoint - .../Documents({id})/lock().
Since I am doing a partial update here, In my opinion PATCH is more suitable.
If your resource has a property called Locked, and your current lock() Action only sets the Locked property to true, then you could simply use PATCH to update just that Locked field.
Some common reasons to use an Action specifically for a lock process:
You want to execute specific logic when lock() is called and you want to maintain this logic in it's own method, rather than having complex conditional logic inside your patch handler.
You don't want the reverse logic, unlock() to be available to everyone, when a resource is locked, presumably only the user who locked it can release the lock or other conditions need to be satisfied.
as with the first point, this sort of logic is generally easier to maintain in its own method, and therefore Action.
You want to use Security Attributes to restrict access to lock() to certain security groups, yet you want all users to have read access the the Locked state field.
When a resource is locked other fields are also set, like LockedBy and perhaps DateLocked.
While all of that logic could be managed in your single PATCH endpoint logic for the controller, I can't stress enough how this can easily make your solution unmanageable over time or as the complexity of your resource increases.
More importantly: the documented and accepted convention is that PATCH will NOT have side effects, and as such there is no need to execute a GET after a PATCH because the same change on the client has been accepted on the server. Conversely, because a POST MAY have side effects, it is reasonable for the client to expect to execute a GET to get all the related changes if the response from the POST does not contain the updated resource.
In the case of Delete vs PermanentlyDelete now things become personal / opinionated...
By convention, the expectation of DELETE is two fold:
After a delete the resource should no longer appear in collection query results from a GET
After a delete the resource should no longer appear in item requests via GET
From a server point of view, if my resource has a soft delete, that simply sets a flag, and a permanent delete that deletes the record from the underlying store, then by convention I would use an Action called Delete() for the soft delete, and the permanent delete should use the DELETE http verb.
The general reasoning for this is the same as for the discussion about locked().
However, if the intention of soft vs permanent delete is to intercept the client's standard delete workflow, such that the permanent delete concept is hidden or otherwise abstracted in a way that it is not part of the usual workflow (the user has to go somewhere different, like the recycle bin to view deleted records and restore or permanently delete), in that scenario, use the HTTP verb DELETE for soft delete, and make a specific, perhaps collection bound Action to accept the request for permanent delete
This action may have to be unbound, or bound to the collection depending on how you implement your filtering, if we have deleted record 'xyz' such the GET: ~/document('xyz') returns NOT-FOUND then we can't really expect POST: ~/document('xyz')/delete() to execute...

What is the proper HTTP method for modifying a subordinate of the named resource?

I am creating a web client which has the purpose of modifying a set of database tables by adding records to them and removing records from them. It must do so atomically, so both deletion and insertion must be done with a single HTTP request. Clearly, this is a write operation of some sort, but I struggle to identify which method is appropriate.
POST seemed right at first, except that RFC 2616 specifies that a POST request must describe "a new subordinate" of the named resource. That isn't quite what I'm doing here.
PUT can be used to make changes to existing things, so that seemed about right, except that RFC 2616 also specifies that "the URI in a PUT request identifies the entity enclosed with the request [...] and the server MUST NOT attempt to apply the request to some other resource," which rules that method out because my URI does not directly specify the database tables.
PATCH seemed closer - now I am not cheating by only partly overwriting a resource - but RFC 5789 makes it clear that this method, like PUT, must actually modify the resource specified by the URI, not some subordinate resource.
So what method should I be using?
Or, more broadly for the benefit of other users:
For a request to X, you use
POST to create a new subordinate of X,
PUT to create a new X,
PATCH to modify X.
But what method should you use if you want to modify a subordinate of X?
To start.. not everything has to be REST. If REST is your hammer, everything may look like a nail.
If you really want to conform to REST ideals, PATCH is kind of out of the question. You're only really supposed to transfer state.
So the common 'solution' to this problem is to work outside the resources that you already have, but invent a new resource that represents the 'transaction' you wish to perform. This transaction can contain information about the operations you're doing in sequence, potentially atomically.
This allows you to PUT (or maybe POST) the transaction, and if needed, also GET the current state of the transaction to find out if it was successful.
In most designs this is not really appropriate though, and you should just fall back on POST and define a simple rpc-style action you perform on the parent.
First, allow me to correct your understanding of these methods.
POST is all about creating a brand new resource. You send some data to the server, and expect a response back saying where this new resource is created. The expectation would be that if you POST to /things/ the new resource will be stored at /things/theNewThing/. With POST you leave it to the server to decide the name of the resource that was created. Sending multiple identical POST requests results in multiple resources, each their own 'thing' with their own URI (unless the server has some additional logic to detect the duplicates).
PUT is mostly about creating a resource. The first major difference between PUT and POST is that PUT leaves the client in control of the URI. Generally, you don't really want this, but that's getting of the point. The other thing that PUT does, is not modify, if you read the specification carefully, it states that you replace what ever resource is at a URI with a brand new version. This has the appearance of making a modification, but is actually just a brand new resource at the same URI.
PATCH is for, as the name suggest, PATCHing a resource. You send a data to the server describing how to modify a particular resource. Consider a huge resource, PATCH allows you to send just the tiny bit of data that you wish to change, whilst PUT would require you send the entire new version.
Next, consider the resources. You have a set of tables each with many rows, that equates to a set of collections with many resources. Now, your problem is that you want to be able to atomically add resources and remove them at the same time. So you can't just POST then DELETE, as that's clearly not atomic. PATCHing the table how ever can be...
{ "add": [
{ /* a resource */ },
{ /* a resource */ } ],
"remove" : [ "id one", "id two" ] }
In that one body, we have sent the data to the server to both create two resources and delete two resources in the server. Now, there is a draw back to this, and that is that it's hard to let clients know what is going on. There's no 'proper' way of the client of the two new resources, 204 created is sort of there, but is meant have a header for the URI of the one new resource... but we added two. Sadly, this a problem you are going to face no matter what, HTTP simple isn't designed to handle multiple resources at once.
Transaction Resources
So this is a common solution people propose, and I think it stinks. The basic idea is that you first POST/PUT a blob of data on the server the encodes the transaction you wish to make. You then use another method to 'activate' this transaction.
Well hang on... that's two requests... it sends the same data that you would via PATCH and then you have fudge HTTP even more in order to somehow 'activate' this transaction. And what's more, we have this 'transaction' resource now floating around! What do we even do with that?
I know this question has been asked already some time ago, but I thought I should provide some commentary to this myself. This is actually not a real "answer" but a response to thecoshman's answer. Unfortunately, I am unable to comment on his answer which would be the right thing to do, but I don't have enough "reputation" which is a strange (and unnecessary) concept, IMHO.
So, now on to my comment for #thecoshman:
You seem to question the concept of "transactional resources" but in your answer it looks to me that you might have misunderstood the concept of them. In your answer, you describe that you first do a POST with the resource and the associated transaction and then POST another resource to "activate" this transaction. But I believe the concept of transactional resources are somehow different.
Let me give you a simple example:
In a system you have a "customer" resource and his address with customer as the primary (or named) resource and the address being the subordinate address. For this example, let us assume we have a customer with a customerId of 1234. The URI to reach this customer would be /api/customer/1234. So, how would you now just update the customer's address without having to update the entire customer resource? You could define a "transaction resource" called "updateCustomerAddress". With that you would then POST the updated customer address data (JSON or even XML) to the following URI: POST /api/customer/1234/updateCustomerAddress. The service would then create this new transactional resource to be applied to the customer with customerId=1234. Once the transaction resource has been created, the call would return with 201, although the actual change may not have been applied to the customer resource. So a subsequent GET /api/customer/1234 may return the old address, or already the new and updated address. This supports well an asynchronous model for updating subordinate resources, or even named resources.
And what would we do with the created transactional resource? It would be completely opaque to the client and discarded as soon as the transaction has been completed. So the call may actually not return a URI of the transactional resource since it may have disappeared already by the time a client would try to access it.
As you can see, transactional resources should not require two HTTP calls to a service and can be done in just one.
RFC 2616 is obsolete. Please read RFC 723* instead, in particular https://datatracker.ietf.org/doc/html/rfc7231#section-4.3.3.