Search code examples
odata

why odata specs return 204 and 404 for those two similar cases


In http://docs.oasis-open.org/odata/odata/v4.0/odata-v4.0-part1-protocol.html

11.2.7 Requesting Entity References

If the resource path terminates on a single entity, the response MUST be the format-specific representation of an entity reference pointing to the related single entity. If the resource path terminates on a single entity and no such entity exists, the service returns 404 Not Found.

11.2.6 Requesting Related Entities

If the relationship terminates on a single entity, the response MUST be the format-specific representation of the related single entity. If no entity is related, the service returns 204 No Content

I think those two cases are similar, they should either both return 404 or 204, why the specification defines the response differently.


Solution

  • The spec makes sense. Think of it in terms of an in-memory dictionary of Entity objects indexed by their identity value, and a routing engine that maps URI paths of the form /Entities(x) to the Entity with identity value x.

    private static final Map<int, Entity> entities;
    static
    {
        Entity entity1 = new Entity() {{ id = 1; relatedThing = new Thing() {{ id = 42; }}; }};
        Entity entity2 = new Entity() {{ id = 2; relatedThing = null; }};
        entities = new HashMap<int, Entity>();
        entities.put(entity1.id, entity1);
        entities.put(entity2.id, entity2);
    }
    

    Requesting Entity References: If you request /Entities(1)/$ref, dictionary lookup will succeed and you will get a reference to the Entity with id of 1. But if you request /Entities(57)/$ref, the dictionary lookup will fail and you will get an error response (404).

    Requesting Related Entities: If you request /Entities(1)/RelatedThing, dictionary lookup will succeed, the OData runtime will dereference the relatedThing property, and you will get a representation of the Thing object associated with the Entity. If you request /Entities(2)/RelatedThing, lookup succeeds, but dereferencing produces null. Note that the navigation property relatedThing exists (because the Entity exists), but there is no associated Thing (i.e., the cardinality of the association is 0..1). Since lookup succeeded, an error response (4xx) is not appropriate. And since dereferencing produced "nothing", the HTTP response code that indicates "no additional content to send in the response payload body" is completely appropriate.