I don't fully understand how creating and accessing association resources works with Spring Data REST and MongoDB. I have noticed a few strange behaviours, and I am hoping to get some clarification here.
I have a simple object model where one resource type (Request) contains a list of objects of another resource type (Point). Both resources are top-level resources, i.e. have their own Repository interfaces.
I would like to be able to add a new Point to a Request by POSTing to /requests/{id}/points with a link to an existing point (as I know from this question that I can't just POST a point as a JSON payload).
Furthermore, I would like to be able to GET /requests/{id}/points to retrieve all the points associated with a request.
Here is my object model (getters/setters omitted):
Request.java
public class Request {
@Id
private String id;
private String name;
@DBRef
private List<Point> points = new ArrayList<>();
}
RequestRepository.java
public interface RequestRepository extends MongoRepository<Request, String> {
}
Point.java
@Data
public class Point {
@Id
private String id;
private String name;
}
PointRepository.java
public interface PointRepository extends MongoRepository<Point, String> {
}
Let's say that I POST a new Request. Then doing a GET on /requests gives me this:
{
"_links" : {
"self" : {
"href" : "http://localhost:8080/requests",
"templated" : false
}
},
"_embedded" : {
"requests" : [ {
"name" : "request 1",
"_links" : {
"self" : {
"href" : "http://localhost:8080/requests/55e5dc47b7605d55c7c361ba",
"templated" : false
},
"request" : {
"href" : "http://localhost:8080/requests/55e5dc47b7605d55c7c361ba",
"templated" : false
},
"points" : {
"href" : "http://localhost:8080/requests/55e5dc47b7605d55c7c361ba/points",
"templated" : false
}
}
} ]
}
}
So I have a points link in there. Good. Now, if I do a GET on /requests/55e5dc47b7605d55c7c361ba, I notice strange thing #1. There is no points link anymore:
{
"name" : "request 1",
"_links" : {
"self" : {
"href" : "http://localhost:8080/requests/55e5dc47b7605d55c7c361ba",
"templated" : false
},
"request" : {
"href" : "http://localhost:8080/requests/55e5dc47b7605d55c7c361ba",
"templated" : false
}
}
}
But anyway forget about that for now, let's POST a point (which gets ID 55e5e225b76012c2e08f1e3e) and link it to the request:
curl -X PUT -H "ContentType: text/uri-list" http://localhost:8080/requests/55e5dc47b7605d55c7c361ba/points
-d "http://localhost:8080/points/55e5e225b76012c2e08f1e3e"
204 No Content
That seemed to work. Ok, so now if I do a GET on http://localhost:8080/requests/55e5dc47b7605d55c7c361ba/points, I expect to see the point I just added, right? Enter strange thing #2, I get the following response:
{
"_links" : {
"self" : {
"href" : "http://localhost:8080/requests/55e5dc47b7605d55c7c361ba/points",
"templated" : false
}
}
}
So at this point I realise I've done something wrong. Could somebody please explain to me what's happening here? Do I have a fundamental misunderstanding of the way SDR is working? Should I even be using DBRefs? Or is this simply not possible with MongoDB?
Thanks in advance, and sorry for the long question!
Edit
The Points are in fact being added as DBRefs (verified by looking at the db manually), but it appears that SDR is not giving them back. If I explicitly ask for http://localhost:8080/requests/55e5dc47b7605d55c7c361ba/points/55e5e225b76012c2e08f1e3e, then I get the following response:
{
"_links" : {
"self" : {
"href" : "http://localhost:8080/points/55e5e225b76012c2e08f1e3e",
"templated" : false
},
"point" : {
"href" : "http://localhost:8080/points/55e5e225b76012c2e08f1e3e",
"templated" : false
}
}
}
Which is also strange... where is my Point.name?