Recentemente stavo lavorando ad un progetto che consisteva nell'esporre dei metodi dello strato remoto dei servizi per essere consumati da un client REST.
Praticamente tutte le entità possedevano campi di tipo long
che rappresentavano foreign key verso altre entità; pertanto all'interno delle varie classi *Impl
dei modelli avevo definito altrettanti metodi getter per recuperare gli oggetti referenziati dalle foreign key. E fino a questo punto non c'era nulla di insolito...
Invocando però i metodi REST esposti mi sono accorto che alcune entità venivano serializzate in modalità shallow ossia presentavano unicamente i campi definiti nel file service.xml
; altre entità invece venivano serializzate in modailtà deep ossia presentavano anche il contenuto di tutti gli oggetti restituiti dai metodi custom che avevo definito nelle classi *Impl
.
L'unica differenza tra queste entità era che per le prime (modalità shallow) avevo definito remote-service="true"
nel service.xml
mentre per le seconde (modalità deep) avevo definito remote-service="false"
dal momento che si trattava di semplici DTO che non dovevano avere uno strato di persistenza.
Indagando un pò ho scoperto che se un'entità viene definita con remote-service="true"
allora l'attributo json-enabled
viene messo di default a true
; viceversa rimane a false
.
Avere l'attributo json-enabled="true"
significa che il Service Builder andrà ad annotare le classi *ModelImpl
con @JSON(strict = true)
; questa annotation fa sì che solamente i campi dichiarati nel service.xml
vengano serializzati, facendo quindi una serializzazione shallow. Peccato che nel caso opposto (ossia json-enabled="false"
), in cui l'entità non dovrebbe supportare la serializzazione JSON, la supporta ugualmente ed addirittura in modalità deep
! Sarà un bug o una feature?
Quindi come facciamo ad avere noi il controllo di quello che viene serializzato? Innanzitutto dobbiamo partire dal fatto che per essere serializzabile in formato JSON, un'entità deve avere json-enabled="true"
; quindi le definiamo così:
<entity name="Entity1" remote-service="true" ...>
...
</entity>
<entity name="Entity2" remote-service="false" json-enabled="true" ...>
...
</entity>
Facendo in questo modo, come abbiamo già visto sopra, otterremo una semplice serializzazione shallow; ma se volessimo spingerci oltre dobbiamo dire al Service Builder quali metodi custom includere nella serializzazione. Quindi se nella classe Entity1Impl
abbiamo definito dei metodi custom, sarò sufficiente annotarli con @JSON(include = true)
ed il risultato di tali metodi verrà serializzato in formato JSON insieme al resto dell'entità.
Bella lì!