Sto provando a creare un'API RESTful con Spring Boot utilizzando spring-boot-starter-data-rest. Ci sono alcune entità: account, transazioni, categorie e utenti - solo le solite cose.Abilita serializzazione HAL in Spring Boot per il metodo di controllo personalizzato
Quando ho recuperare gli oggetti in http://localhost:8080/transactions tramite l'API che è stato generato per impostazione predefinita, tutto va bene un ottengo una lista con tutte le transazioni come oggetti JSON come quella:
{
"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"
}
}
}
Ma ora il l'obiettivo è recuperare solo le ultime transazioni sotto quell'URL poiché non desidero serializzare l'intera tabella del database. Così ho scritto un 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();
}
}
Quando io ora cerco di accesso http://localhost:8080/transactions c'è una
java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
a causa del riferimento circolare tra gli utenti e gli account. Quando ho risolvere questo con l'aggiunta di un'annotazione @JsonBackReference all'elenco conto utente, posso recuperare la lista delle transazioni ma solo con questo formato "classico":
{
"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"
}
}
Nessun link HAL più, tutto è sempre serializzato direttamente jackson. Ho provato ad aggiungere
@EnableHypermediaSupport(type = HypermediaType.HAL)
alle classi di entità, ma questo non mi ha portato da nessuna parte. Voglio solo che il mio controller restituisca gli stessi oggetti che l'API generata fa, con HAL _links invece di ogni riferimento serializzato. qualche idea?
EDIT: OK, dopo aver pensato due volte mi sono reso conto che l'annotazione @EnableHypermediaSupport deve essere aggiunto alla configurazione, naturalmente. Questo risolve il problema dei riferimenti circolari e posso rimuovere @JsonBackReference dall'utente. Ma solo gli attributi dell'oggetto stesso vengono serializzati, non ci sono sezioni _links:
{
"amount": -4.81,
"date": "2014-06-17T21:18:00.000+0000",
"description": "Pizza"
}
So che avrei potuto scrivere classi wrapper che si estendono ResourceSupport per tutti i miei soggetti ma questo sembra piuttosto inutile. Poiché spring-hateoas è in grado di generare magicamente le rappresentazioni con la sezione _link per l'interfaccia REST che viene creata automaticamente, ci dovrebbe essere un modo per restituire le stesse rappresentazioni da un controller personalizzato, giusto?
Ciò è stato molto utile, grazie! Il 'ResourcesSupport' è documentato ovunque? – hzpz
Sì: http://docs.spring.io/spring-hateoas/docs/current/reference/html/#fundamentals.resources –
@OliverGierke Grazie mille, davvero! Informazioni sui commenti: (1.) Sì, la risorsa restituisce un elenco, ovviamente. Ho appena accorciato l'output per illustrare il formato. (2.) Sì, ho un PagingAndSortingRepository ma, come avete indovinato, voglio (3.) fornire e togliere la possibilità per il client di interrogare l'intera tabella del database in una sola volta. – Tilman