Poco tempo fa abbiamo visto insieme un e adesso scopro che con JBoss 7 (al momento 7.0.2) alcune cose sono cambiate, fortunatamente in meglio! Vediamole da vicino.
I contesti
Come nel post precedente, possiamo distinguere i servizi REST che risiedono in un modulo Web o in un modulo EJB: questa volta le differenze sono davvero minime, ma trattiamole ancora in due sezioni distinte per chiarezza.
La grande novità della nuova versione di RESTEasy sta nel fatto che è possibile creare un servizio REST in ben 3 modi, come riportato nella specifica JAR-RS 1.1, sezione 2.3.2 (sembra che l’abbia letta no? 😉 ). Il tutto ruota intorno alla nuova classe javax.ws.rs.core.Application
, che serve per definire il path che farà da entrypoint alla nostra applicazione REST, creando una sorta di namespace. Vediamo nel dettaglio i tre modi:
- javax.ws.rs.core.Application + @ApplicationPath
-
Come prima alternativa possiamo estendere la calsse
Application
e annotarla con@ApplicationPath
come segue:
@ApplicationPath("/app") public class MyRESTApp extends Application { }
Questo significa che tutti gli URL REST della nostra applicazione saranno mappati su /myWebContextPath/app. I sotto-URL, come per esempio “/app/echo-service” seguiranno la stessa logica definita dall’annotazione@Path
che abbiamo già incontrato. Da notare che nell’EAR deve esistere una ed una sola classe che estendeApplication
. Volendo, questa classe può rimanere così com’è anche vuota! - javax.ws.rs.core.Application + web.xml
-
Rispetto alla versione precedente, invece che definire il mapping dell’applicazione con l’annotazione, lo definiamo tramite il web.xml
public class MyRESTApp extends Application { }
it.cosenonjaviste.services.rest.MyRESTApp /app/* - POJO + web.xml
- Invece che legarsi alla classe Application, possiamo fare un semplice POJO e aggiungere il seguente mapping al web.xml
-
javax.ws.rs.core.Application /app/*
Un po’ di pratica
Apprese le novità, vediamo come applicarle.
Servizio nel modulo Web
Per il modulo Web, l’approccio che preferisco è il POJO + web.xml, perché così possiamo creare classi indipendenti da REST e configurare il tutto con poche righe di XML. Possiamo quindi riprendere il servizio visto nel post su JBoss 6:
@Path(value="/service") public class MyRESTService { @GET @Path(value="/echo/{message}") public String echo(@PathParam(value="message") String message) { return "Echo " + message; } }
che, una volta mappata nel web.xml la classe Application
come visto poco fa, risponderà all’URL del tipo
JBossWebServiceProducerWeb/app/service/echo/sayonara
Se stiamo migrando quindi i servizi da JBoss 6 al 7, con questo approccio gli impatti lato server saranno pressoché nulli. Diversamente sarà il caso del client, perché in questo caso l’URL sarà diverso da prima… (c’è un /app/ in più!)
Servizio nel modulo EJB
Ovvero come un EJB mi diventa un servizio web! Ebbene si, la promessa di svincolare RESTEasy dal web.xml per gli EJB è stata mantenuta e in JBoss 7 vediamo i risultati! Se stiamo creando una applicazione che non prevede una interfaccia grafica, possiamo benissimo fare a meno del modulo Web e usare l’approccio javax.ws.rs.core.Application + @ApplicationPath. Vediamo come le annotazioni necessarie si distribuiscono tra l’interfaccia e l’implementazione dell’EJB.
@Local @Path(value="/ejb") public interface EchoEJBLocal { @GET @Path(value="/{text}") String echo(String textToEcho); }
L’interfaccia conterrà le annotazioni tipiche del REST. Dobbiamo adesso prevedere che esista una ed una sola classe che estende Application
. Questa potrebbe essere un qualsiasi POJO all’interno del modulo EJB
@ApplicationPath(value ="/app") public class MyEJBApp extends Application { }
oppure l’implementazione di EchoEJB stessa:
@Stateless @ApplicationPath(value ="/app") public class EchoEJB extends Application implements EchoEJBLocal { @Override public String echo(String textToEcho) { return "Echo " + textToEcho; } }
Conclusioni
Anche se a prima vista sembra strano avere ben tre modi per istanziare un servizio REST, due di questi, almeno secondo me, sono quasi necessari se vogliamo mantenere la struttura dei nostri progetti “pulita” e le classi facilmente riusabili. A questo punto un dubbio potrebbe essere: “Che ci metto nella classe che estende Application, come nel caso di MyEJBApp”? Potrebbe essere sfruttata per esempio per mappare il percorso di root del servizio (@Path("/")
) e dare qualche informazione sul servizio stesso.