3
votes

Using Spring Data REST with via JPARepsitory repositories, I have two entities that have a one-to-many relationship.

@Entity
class Owner {

    // owner attributes...

    @OneToMany
    Set<Item> items;
}

and

@Entity
class Item {

    // item attributes...

    @ManyToOne
    Owner owner;
}    

The setup is Owner with id 1 has an Item with id 5.

When I call http://localhost:8080/api/items/5 I get something like

{
  // item attributes
  "_links": {
    "self": {
      "href": "http://localhost:8080/api/items/5"
    },
    "item": {
      "href": "http://localhost:8080/api/items/5"
    },
    "owner": {
      "href": "http://localhost:8080/api/items/5/owner"
    }
  }
}

Then, when I call http://localhost:8080/api/items/5/owner I get

{
  "content": {
    // owner attributes
  },
  "_links": {
    "self": {
      "href": "http://localhost:8080/api/owners/1"
    },
    "owner": {
      "href": "http://localhost:8080/api/owners/1"
    },
    "items": {
      "href": "http://localhost:8080/api/owners/1/items"
    }
  }
}

However, if I call http://localhost:8080/api/owners/1 (which is the same entity, but at the identity href instead of the association href) I get something like

{
  // owner attributes
  "_links": {
    "self": {
      "href": "http://localhost:8080/api/owners/1"
    },
    "owner": {
      "href": "http://localhost:8080/api/owners/1"
    },
    "items": {
      "href": "http://localhost:8080/api/owners/1/items"
    }
  }
}

Here, Owner is wrapped in an extra content object when being called from a singular association resource.

Update to clarify

I would expect if I were to call the self href I would get back the exact same representation, but in this case I don't. I get the canonical entity representation.

My question is, why is this the case? Should an entity returned via an association resource have a self href that is the URI the entity was retrieved from or should the entity returned via the association resource have the same representation of that of the entity's item resource?

In short, when I call http://localhost:8080/api/items/5/owner I would expect to get

{
  "content": {
    // owner attributes
  },
  "_links": {
    "self": {
      "href": "http://localhost:8080/api/items/5/owner"
      // ^^^ the URI that was retrieved that will always return this representation
    },
    "owner": {
      "href": "http://localhost:8080/api/owners/1"
      // ^^^ the canonical entity URI
    },
    "items": {
      "href": "http://localhost:8080/api/owners/1/items"
    }
  }
}

OR

{
  // owner attributes
  "_links": {
    "self": {
      "href": "http://localhost:8080/api/owners/1"
    },
    "owner": {
      "href": "http://localhost:8080/api/owners/1"
    },
    "items": {
      "href": "http://localhost:8080/api/owners/1/items"
    }
  }
}
// ^^^ The canonical entity representation (no "content" wrapper)

but not a mix of the two.

1
Why would you call http://localhost:8080/api/items/5/owner instead of the owner's URI? - a better oliver
Because I'm using the merchant link from the Item. I'll update the question. - Strengthiness

1 Answers

2
votes

http://localhost:8080/api/items/5/owner refers to a so called association resource. It doesn't point to the "real" owner resource.

It's purpose is to handle associations. E.g. sending a request with DELETE would only remove the owner from the item, but not delete the actual owner entity.

Depending on the configuration you can get all attributes of the owner embedded. That's what you get as content.