I have defined a @Projection for my Spring Data entity as described here
For the same reasons as described there. When I do GET
request, everything is returned as expected. But when I do a POST
request, the projection won't work. Following the example provided above, "Address" is shown as a URL under Links and is not exposed the way it is with GET
request.
How to get it exposed the same way?
I created a class with @RepositoryRestController
where I can catch the POST
method. If I simply return the entity, it is without links. If I return it as a resource, the links are there, but "Address" is also a link. If I remove the GET
method from my controller, the default behavior is as described above.
UPDATE
My entities are same as described here A
, B
and SuperClass
except I don't have fetch defined in my @ManyToOne
My controller looks like this:
@RepositoryRestController
public class BRepositoryRestController {
private final BRepository bRepository;
public BRepositoryRestController(BRepository bRepository) {
this.bRepository = bRepository;
}
@RequestMapping(method = RequestMethod.POST, value = "/bs")
public
ResponseEntity<?> post(@RequestBody Resource<B> bResource) {
B b= bRepository.save(bResource.getContent());
BProjection result = bRepository.findById(b.getId());
return ResponseEntity.ok(new Resource<>(result));
}
}
And my repository looks like this:
@RepositoryRestResource(excerptProjection = BProjection.class)
public interface BRepository extends BaseRepository<B, Long> {
@EntityGraph(attributePaths = {"a"})
BProjection findById(Long id);
}
And my projection looks like this:
@Projection(types = B.class)
public interface BProjection extends SuperClassProjection {
A getA();
String getSomeData();
String getOtherData();
}
And SuperClassProjection looks like this:
@Projection(types = SuperClass.class)
public interface SuperClassProjection {
Long getId();
}
In the custom @RepositoryRestController POST method you should also return the projection. For example:
@Projection(name = "inlineAddress", types = { Person.class })
public interface InlineAddress {
String getFirstName();
String getLastName();
@Value("#{target.address}")
Address getAddress();
}
public interface PersonRepo extends JpaRepository<Person, Long> {
InlineAddress findById(Long personId);
}
@PostMapping
public ResponseEntity<?> post(...) {
//... posting a person
InlineAddress inlineAddress = bookRepo.findById(person.getId());
return ResponseEntity.ok(new Resource<>(inlineAddress));
}
UPDATE
I've corrected my code above and the code from the question:
@RepositoryRestResource(excerptProjection = BProjection.class)
public interface BRepository extends CrudRepository<B, Long> {
BProjection findById(Long id);
}
@Projection(types = B.class)
public interface BProjection {
@Value("#{target.a}")
A getA();
String getSomeData();
String getOtherData();
}
Then all works fine.
POST request body:
{
"name": "b1",
"someData": "someData1",
"otherData": "otherData",
"a": {
"name": "a1"
}
}
Response body:
{
"a": {
"name": "a1"
},
"someData": "someData1",
"otherData": "otherData",
"_links": {
"self": {
"href": "http://localhost:8080/api/bs/1{?projection}",
"templated": true
}
}
}
See working example