Fino allo scorso capitolo abbiamo visto la parte principale relativa all'implementazione dei servizi. Quando ci si trova ad implementare un sistema reale però, ci si imbatterà in una serie di questioni riguardanti la sicurezza, i log, file di configurazione e parametri custom per ambienti diversi.
Per lavorare ad un livello diverso sui servizi, Jersey ci viene in aiuto tramite i Filtri ed i Listener.
Se facciamo qualche passo indietro, ricordiamo che alla base di tutto c'è la classe LibraryApplication
che estende ResourceConfig
. All'interno di questa classe abbiamo inizializzato il nostro progetto. Sempre nel costruttore è possibile registrare, tramite il metodo register(final Class<?> componentClass)
delle classi per far sì che queste vengano istanziate ed utilizzate all'interno del contesto come componenti custom JAX-RS.
La classe che andiamo ad aggiungere implementerà un'interfaccia, mettendo a disposizione un'implementazione relativa ad alcune funzionalità.
Request & Response
Per intercettare la request e la response possiamo implementare una classe che utilizza le interfacce ContainerRequestFilter
e ContainerResponseFilter
, implementando quindi i metodi;
public void filter(ContainerRequestContext requestContext)
throws IOException;
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
throws IOException;
all'interno dei quali avremmo a disposizione, appunto, request e response.
Gestione delle eccezioni
Per intercettare gli errori, e quindi le eccezioni, possiamo sfruttare l'interfaccia ExceptionMapper
. Questa chiederà di implementare il metodo:
Response toResponse(E exception);
che verrà invocato dal framework al verificarsi delle eccezioni. Come possiamo intuire dal parametro restituito dal metodo, saremo quindi responsabili della risposta restituita agendo sull'oggetto Response
.
Ciclo di vita del Container
L'interfaccia ContainerLifecycleListener
invece, ci consente di lavorare nelle fasi di startup, shutdown e reload del container in cui abbiamo deployato. Dobbiamo sviluppare una classe che implementa un'interfaccia andando a fornire l'implementazione dei metodi di seguito:
public void onStartup(Container container);
public void onReload(Container container);
public void onShutdown(Container container);
Altre funzionalità
Sulla guida ufficiale è possibile trovare tutte le classi da estendere per risolvere ogni necessità di progetto. Fra queste ce ne sono alcune che dovremmo semplicemente registrare per attivare o disattivare determinate funzionalità. Ad esempio per poter lavorare con comunicazioni HTTP di tipo multipart è necessario registrare il provider MultiPartFeature
senza necessità di specificare alcuna implementazione. Stessa cosa per abilitare la gestione dei ruoli sui servizi tramite le Annotation.