I'm trying to build a RESTful API with Spring Boot using spring-boot-starter-data-rest. There are some entities: accounts, transactions, categories and users - just the usual stuff.
When I retrieve the objects at http://localhost:8080/transactions via the API that has been generated by default, all is going well an I get a list with all transactions as JSON objects like that one:
{
"amount": -4.81,
"date": "2014-06-17T21:18:00.000+0000",
"description": "Pizza",
"_links": {
"self": {
"href": "http://localhost:8080/transactions/5"
},
"category": {
"href": "http://localhost:8080/transactions/5/category"
},
"account": {
"href": "http://localhost:8080/transactions/5/account"
}
}
}
But now the goal is to retrieve only the latest transactions under that URL since I don't want to serialize the whole database table. So I wrote a Controller:
@Controller
public class TransactionController {
private final TransactionRepository transactionRepository;
@Autowired
public TransactionController(TransactionRepository transactionRepository) {
this.transactionRepository = transactionRepository;
}
// return the 5 latest transactions
@RequestMapping(value = "/transactions", method = RequestMethod.GET)
public @ResponseBody List<Transaction> getLastTransactions() {
return transactionRepository.findAll(new PageRequest(0, 5, new Sort(new Sort.Order(Sort.Direction.DESC, "date")))).getContent();
}
}
When I now try to access http://localhost:8080/transactions there's a
java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
because of the circular reference between users and accounts. When I solve this by adding a @JsonBackReference annotation to the account list in User, I can retrieve the transaction list but only with this "classic" format:
{
"id": 5,
"amount": -4.5,
"date": "2014-06-17T21:18:00.000+0000",
"description": "Pizza",
"account": {
"id": 2,
"name": "Account Tilman",
"owner": {
"id": 1,
"name": "Tilman"
},
"categories": [
{
"id": 1,
"name": "Groceries"
},
{
"id": 2,
"name": "Restaurant"
}
],
"users": [
{
"id": 1,
"name": "Tilman"
}
]
},
"category": {
"id": 2,
"name": "Restaurant"
}
}
No HAL links anymore, everything is getting serialized directly by jackson. I tried adding
@EnableHypermediaSupport(type = HypermediaType.HAL)
to the entity classes but that didn't get me anywhere. I just want my controller to return the same objects that the generated API does, with HAL _links instead of every reference being serialized. Any thoughts?
EDIT: OK, after thinking twice I realized that the @EnableHypermediaSupport annotation has to be added to the configuration, of course. This solves the problem of the circular references and I can remove the @JsonBackReference from User. But only the attributes of the object itself are being serialized, there is no _links section:
{
"amount": -4.81,
"date": "2014-06-17T21:18:00.000+0000",
"description": "Pizza"
}
I know that I could write wrapper classes extending ResourceSupport for all my entities but this seems rather pointless. As spring-hateoas is able to magically generate the representations with the _link section for the REST interface that is created automatically there should be a way to return the same representations from a custom controller, right?