2013-06-30 21 views
11

Sto avendo e problema con il riferimento circolare.Json e Java - Riferimento circolare

ho riposare Webservices che restituisce gli oggetti al front-end, il problema è quando provo a restituire gli oggetti che hanno diversi riferimenti così come il risultato che ottengo una risposta infinita, che generano

java.lang.IllegalStateException: 
    Cannot call sendError() after the response has been committed 

Gli oggetti sono generati automaticamente da Hibernate Code Generation e ho bisogno di avere il riferimento circolare nel back-end, ho solo bisogno di rimuoverlo prima di inviare le informazioni al frontend usando Jackson.

Il metodo intestazione controller è:

@RequestMapping(value="/list", method=RequestMethod.POST) 
public @ResponseBody eventResponse list(@RequestBody String sessionID) { 

non sto facendo nulla esplicita per convertire a JSON, sono un newby con questo e credo che Jackson ha risolto questo automaticamente.

+1

http://wiki.fasterxml.com/JacksonFeatureBiDirReferences –

risposta

23

Ci sono due modi per procedere. Se devi esporre la tua entità al mondo esterno, ti consiglio di aggiungere @JsonIgnore alla proprietà che sta causando il riferimento circolare. Questo dirà a Jackson di non serializzare quella proprietà.

Un altro modo è utilizzare le funzionalità bidirezionali fornite da Jackson. È possibile utilizzare @JsonManagedReference o @JsonBackReference. @JsonManagedReference è la parte "forward" della proprietà e verrà serializzata normalmente. @JsonBackReference è la parte "indietro" del riferimento; non sarà serializzato, ma verrà ricostruito quando il tipo "avanti" è deserializzato.

È possibile controllare gli esempi here.

Questo indirizzo il tuo commento: Penso che quello che potresti voler fare in questo caso è usare un DTO che è visibile al mondo esterno. Mi piace questo approccio perché non voglio esporre le mie entità all'esterno. Ciò significa che le annotazioni di Jackson sarebbero sul DTO e non sull'unità. Avresti bisogno di una sorta di mappatore o convertitore che converta l'entità nel DTO. Ora quando apporti modifiche alla tua entità, non verranno propagati al DTO a meno che tu non modifichi il tuo mappatore/convertitore. Penso che sia ok, perché quando apporti una modifica alla tua entità puoi decidere se vuoi che la modifica sia esposta o meno.

UPDATE

C'è un buon post sul blog here che va in dettaglio sui vari modi in cui è possibile gestire le relazioni bidirezionali a Jackson. Descrive le soluzioni che utilizzano @JsonIgnore, @JsonManagedReference e @JsonBackReference, @JsonIdentityInfo, @JsonView e un serializzatore personalizzato. È una descrizione abbastanza completa delle varie tecniche che è possibile utilizzare.

+0

Sì, ho letto di questo. Ma il fatto è che non voglio "toccare" le entità generate da Hibernate. Perché il database continua a crescere così ogni volta che vorrei aggiungere qualcosa dovrò modificare di nuovo tutte le entità. Come ho capito, devo modificare le entità per entrambe le opzioni, giusto? – Faabass

+0

Perché il downvote? –

5

Una singola annotazione @JsonIdentityInfo risolve il problema. Gestisce anche riferimenti circolari. Reference

+0

l'unico problema è quando il campo identità è nullo. quindi sei tornato al punto 1 - riferimento circolare. – anton1980