Is there any recommended way of handling validation/business logic
errors when operating on resources? For example, let's say that to
open a bank account in some bank you could do a POST on the Account
resource. If all goes well, you would get back a HTTP 201 Created
status code with the representation of the newly created account. But
let's say that the bank has a restriction on the number of checking
accounts a client can open and that a client that already has a
checking account tries to create a second one. What would be the
appropriate HTTP status code to return to the caller? And what about
returning error information to the caller, what would be appropriate?
In our application, in this situation, we decided to return a 200 OK
response with a list of error messages as the representation. But I'm
not too sure this is the appropriate solution.
> Is there any recommended way of handling validation/business logic > errors when operating on resources? For example, let's say that to > open a bank account in some bank you could do a POST on the Account > resource. If all goes well, you would get back a HTTP 201 Created > status code with the representation of the newly created account. But > let's say that the bank has a restriction on the number of checking > accounts a client can open and that a client that already has a > checking account tries to create a second one. What would be the > appropriate HTTP status code to return to the caller? And what about > returning error information to the caller, what would be appropriate?
> In our application, in this situation, we decided to return a 200 OK > response with a list of error messages as the representation. But I'm > not too sure this is the appropriate solution.
Yeah, I thought about using 400 as the return code, but the w3c spec I
read mentioned syntax problems as the reason to return a 400. But
digging a bit further, I see that a 400 can either mean syntax
problems or that the request cannot be fulfilled. Which corresponds
exactly to the example I described.
So in the end, 400 seems appropriate and much better than returning a
200.
Thanks very much.
On Jan 24, 2:06 pm, Dan Haywood <d...@haywood-associates.co.uk> wrote:
> 400 (bad request), with a representation that includes an error message:
> {
> "error": "Client cannot have two checking accounts"
> }
> On 24 January 2012 18:58, Etienne Hardy <etienne.ha...@gmail.com> wrote:
> > Hello group,
> > Is there any recommended way of handling validation/business logic
> > errors when operating on resources? For example, let's say that to
> > open a bank account in some bank you could do a POST on the Account
> > resource. If all goes well, you would get back a HTTP 201 Created
> > status code with the representation of the newly created account. But
> > let's say that the bank has a restriction on the number of checking
> > accounts a client can open and that a client that already has a
> > checking account tries to create a second one. What would be the
> > appropriate HTTP status code to return to the caller? And what about
> > returning error information to the caller, what would be appropriate?
> > In our application, in this situation, we decided to return a 200 OK
> > response with a list of error messages as the representation. But I'm
> > not too sure this is the appropriate solution.
This is a pretty interesting question. The HTTP response codes pertain to HTTP, rather than any underlying domain (they're separate bounded contexts).
So while I agree 400 is the correct response here, I think I differ in the motivation.
For me, if you've submitted a representation that I cannot process for whatever reason then I will respond 400 with helpful advice about why your representation is invalid. So I'd differ from Dan's 400 response like this:
You bring an interesting nuance. Thanks for the precision.
Your comment about the separation of contexts between HTTP and the
underlying application domain is also interesting. There's a straight
mapping between between the 200 and 201 responses codes and what
happens in the application domain. But it always puzzled me if we
should use the 400 response code to signal application level errors.
On Jan 25, 7:03 am, Jim Webber <j...@jimwebber.org> wrote:
> This is a pretty interesting question. The HTTP response codes pertain to HTTP, rather than any underlying domain (they're separate bounded contexts).
> So while I agree 400 is the correct response here, I think I differ in the motivation.
> For me, if you've submitted a representation that I cannot process for whatever reason then I will respond 400 with helpful advice about why your representation is invalid. So I'd differ from Dan's 400 response like this:
On 25 January 2012 12:03, Jim Webber <j...@jimwebber.org> wrote:
> This is a pretty interesting question. The HTTP response codes pertain to > HTTP, rather than any underlying domain (they're separate bounded contexts).
Just to stir up this thread a smidge, I'm not sure I agree that they are separate bounded contexts (presumably this is the DDD vocabulary, as per [1]).
To put it another way: one can see Rest mostly as a presentation layer of a domain model (at least, I do); and presentation layers are not in a different BC to the domain.
> That is, it's the representation that is at fault (it fails its "schema" > check) rather than being directly mapped to the underlying domain.
I don't particularly object to that representation, however I think it's redundant to mention "checking_account" in the response because (presumably) that identity of the checking account is implied by the resource URL that was invoked.
> On 25 January 2012 12:03, Jim Webber <j...@jimwebber.org> wrote:
>> This is a pretty interesting question. The HTTP response codes pertain to >> HTTP, rather than any underlying domain (they're separate bounded contexts).
> Just to stir up this thread a smidge, I'm not sure I agree that they are > separate bounded contexts (presumably this is the DDD vocabulary, as per > [1]).
> To put it another way: one can see Rest mostly as a presentation layer of > a domain model (at least, I do); and presentation layers are not in a > different BC to the domain.
I would say they are different because while Restis a presentation layer (Resource Model) on top of a Domain Model, HTTP is not your Resource Model. HTTP is the protocol you use to transmit your Resource Model, which is why they should be treated as different contexts.
>> That is, it's the representation that is at fault (it fails its "schema" >> check) rather than being directly mapped to the underlying domain.
> I don't particularly object to that representation, however I think it's > redundant to mention "checking_account" in the response because > (presumably) that identity of the checking account is implied by the > resource URL that was invoked.
I don't think a client should use the URL to know what was requested it should be opaque. So that means you need to use the Content-Type to determine what was returned. With that said I think you would determine to put "checking_account" depending on the Content-Type (aka representation) you are working with. IF you were to use
application/vnd.resinpractice.Error+json
then Dan's response seems like it is enough. The client can see the 400 and say "oh dear, something went wrong I wonder what it was". Then it would say "well I got back an error representation, I know how to read one of those". "I got back an error message, so let me display that to the guest". I would argue a better error response would look something like this
{ "type" : "MAX_ACCOUNTS_REACHED", "message" : "Client cannot have two checking accounts"
}
This gives the client a key to rely on incase it can "fix" the application level error or provide better insight into the error (like redirect to a different form).
If you content type was more generic though
application/vnd.restinpractice.Banking+json
Then I think you need something like "error" or "checking-account.invalid-content" in the response document so that the user while interpretting the response konws an error occured without having to rely on the URL.
On 28 January 2012 13:47, Daniel Roop <dan...@danielroop.com> wrote:
>> I would say they are different because while Restis a presentation layer > (Resource Model) on top of a Domain Model, HTTP is not your Resource Model. > HTTP is the protocol you use to transmit your Resource Model, which is why > they should be treated as different contexts.
Are you still using the word "context" to in the DDD sense of a bounded context? If they are different, then draw me a context map [1] and indicate the relationship between them: conformant, client/supplier, kernel, open host, separate ways, what?
I agree that HTTP is a protocol, of course, but as you can probably tell, I think that Jim (and perhaps you) are misusing the term "bounded context" here.
>>> That is, it's the representation that is at fault (it fails its "schema" >>> check) rather than being directly mapped to the underlying domain.
>> I don't particularly object to that representation, however I think it's >> redundant to mention "checking_account" in the response because >> (presumably) that identity of the checking account is implied by the >> resource URL that was invoked.
> I don't think a client should use the URL to know what was requested it > should be opaque.
Point of information: there's nothing in REST to say that the URL needs to be opaque.
But in any case, that isn't what I meant. Rather, the client, who has just invoked the URL, presumably understands its semantics, probably by having interpreted the "rel" of the link they were following from the previous representation they obtained. That's why I think that specifying the "checking_account" in the output representation is redundant.
> So that means you need to use the Content-Type to determine what was > returned. With that said I think you would determine to put > "checking_account" depending on the Content-Type (aka representation) you > are working with. IF you were to use
> application/vnd.resinpractice.Error+json
Happy with that, though from a pragmatic standpoint it doesn't work well, eg if you browse to that representation using Chrome, for example.
Instead, I've taken to using the "profile" parameter instead [2]:
bounded context: A description of a boundary (typically a subsystem, or the work of a particular team) within which a particular model is defined and applicable
I'd counter: A RESTful service meets these requirements: it is not (IMO) simply some aspect of a presentation layer otherwise it would be totally isomorphic to and interchangeable with other "presentation" technologies like SOAP + WSDL. As years of failed frameworks and tooling have shown, this is not the case.
When I build REST services the service layer is very much a separate bounded context from the "domain" layer and exchange information across a well-defined (and therefore testable) boundary.
I believe conflating your integration concerns with presentation issues is wrong. It's equally wrong IMO to conflate integration concerns with your core domain model.
On 28 January 2012 19:34, Jim Webber <j...@jimwebber.org> wrote:
> bounded context: > A description of a boundary (typically a subsystem, or the work of a > particular > team) within which a particular model is defined and applicable
> [snip]
> When I build REST services the service layer is very much a separate > bounded context from the "domain" layer and exchange information across a > well-defined (and therefore testable) boundary.
I prefer the way you are expressing this now to how you did previously (about how HTTP is a different BC).
When you say service layer, I'm interpreting that as including a resource model (as per Daniel Roop, earlier in the thread)? But not every context map pattern requires that the model of one BC is different from that of another BC. For example, shared kernel says that they are the same. Conformist means that similar. The pattern that says that there is an explicit mapping is, of course, anti-corruption layer. But I don't think that it's correct to assume that different BCs implies an ACL.
> I believe conflating your integration concerns with presentation issues is > wrong. It's equally wrong IMO to conflate integration concerns with your > core domain model.
I don't necessarily see REST implying integration. Of course, that's a very common scenario, and so if two BCs are being integrated, then the context mapping between them needs to be understood.
But REST can also be used within a single BC, in which case it is much more like a presentation layer.
Let me put my viewpoint a different way: who owns each end of the pipe? Three scenarios.
If both bits of software collaborating are under the control of a single team (eg a Javascript client with a RESTful backend), then it's a single BC and there's no need for a separate resource model.
Or, the two systems could be managed by different teams/be in different BCs, but the client is conformist to the server. In this case a change to the server requires a redeployment of the client. That also doesn't require a separate resource model/service layer.
Only when the deployment cycle of the consuming client is different from that of the server is an ACL required; in this case the cost of a separate resource model/service layer must be incurred.