Nell’articolo Primi Passi con Spring Boot abbiamo visto come realizzare una semplice applicazione con Spring Boot per l’esposizione di servizi rest. Poi in Utilizzo di Spring in JSF 2.0 abbiamo mostrato come sia possibile integrare JSF con Spring Core.
In questo post vogliamo integrare le tecnologie JSF e Spring Boot al fine di realizzare una applicazione standalone che non solo espone servizi rest ma dispone anche di una interfaccia web (ad esempio di configurazione).
Ritengo si tratti di un progetto molto utile per tutte quelle situazioni in cui abbiamo la necessità di realizzare un client che svolge operazioni per le quali è coordinato da un server centrale e che necessiti di minime interfacce di gestione.
Dipendenze
Partendo dal progetto presentato in Primi Passi con Spring Boot, apriamo il pom.xml
ed inseriamo le dipendenze necessarie a JSF.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<dependency> <groupId>com.sun.faces</groupId> <artifactId>jsf-api</artifactId> <version>${jsf.version}</version> </dependency> <dependency> <groupId>com.sun.faces</groupId> <artifactId>jsf-impl</artifactId> <version>${jsf.version}</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> |
Le prime due dipendenze jsf-api
e jsf-impl
sono rispettivamente la specifica delle interfacce JSF e la loro implementazione. Mentre tomcat-embed-jasper
è necessaria alla Java Virtual Machine per il parsing e l’esecuzione delle viste JSF.
Configurazione di JSF
Nell’articolo Utilizzo di Spring in JSF 2.0 abbiamo configurato il framework JSF definendo la relativa servlet servletjavax.faces.webapp.FacesServlet
di gestione nel file web.xml
. Trattandosi di un progetto Spring Boot, e quindi non web, dobbiamo procedere alla configurazione in modo differente utilizzando le caratteristiche di Spring.
Innanzitutto creiamo una classe JsfConfig
annotata con @Configuration
in cui mettiamo tutti i metodi factory per la generazione dei Bean
di configurazione.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
@Configuration public class JsfConfig extends SpringBootServletInitializer implements ServletContextAware { @Override public void onStartup(ServletContext servletContext) throws ServletException { super.onStartup(servletContext); servletContext.setInitParameter("javax.faces.PROJECT_STAGE", "Development"); } @Override public void setServletContext(ServletContext servletContext) { servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration", Boolean.TRUE.toString()); } @Bean public ServletRegistrationBean facesServlet() { FacesServlet servlet = new FacesServlet(); ServletRegistrationBean registration = new ServletRegistrationBean(servlet, "*.xhtml"); registration.setName("FacesServlet"); registration.setLoadOnStartup(1); return registration; } @Bean public ServletListenerRegistrationBean<ConfigureListener> jsfConfigureListener() { return new ServletListenerRegistrationBean<ConfigureListener>(new ConfigureListener()); } } |
Il metodo facesServlet()
genera un bean di tipo ServletRegistrationBean
che permette di registrare la servlet FacesServlet
e di configurarla per gestire i file con estensione xhtml
.
I metodi onStartup()
e setServletContext()
, che sovrascrivono quelli definiti nell’interfaccia ServletContextAware
, consentono invece di definire ulteriori parametri di configurazione.
Per completezza definiamo anche una classe WebConfig
che estende WebMvcConfigurerAdapter
al fine di registrare un controller che mappa l’url “/” a “/index.xhtml”.
1 2 3 4 5 6 7 8 9 |
@Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("forward:/index.xhtml"); registry.setOrder(Ordered.HIGHEST_PRECEDENCE); super.addViewControllers(registry); } } |
Implementazione delle Viste
In una tradizionale applicazione web con maven avremmo utilizzato il plug-in maven-war-plugin
per la generazione del pacchetto WAR da peloyare sull’application server. Plug-in che recupera i fileda inserire nel pacchetto e che implementano le viste (XHTML
nel nostro caso) dalla cartella src/main/webapp
.
Nel nostro caso però utilizziamo Spring Boot per genera un JAR eseguibile da avviare da riga di comando con il servlet engine Tomcat embedded. Non possiamo quindi utilizzare la stressa struttura. Il segreto è quello di inserire i file includere nel pacchetto di deploy nella cartella src/main/resources
creando una cartella META-INF
ed una META-INF/resources
. La buona notizia è che è sufficiente copiare, praticamente senza modifiche, il file faces-config.xml
presente nel post Utilizzo di Spring in JSF 2.0 nella prima cartella e tutti i file XHTML nella cartella, come mostrato nell’immagine seguente.
Logica Applicativa
Stesso discorso è applicabile al codice java, nel progetto infatti possiamo semplicemente copiare le classi EmployeeManagedBean
, EmployeeService
e le altre classi di servizio definite in Utilizzo di Spring in JSF 2.0 all’interno del nostro progetto. Unica differenza è che essendo stata rimossa la dipendenza a CDI e bean sono stati annotati come @Component
ed iniettati con @Autowired
.
Build ed Esecuzione
Per l’esecuzione da riga di comando eseguiamo semplicemente le seguenti istruzioni maven all’interno della cartella del nostro progetto.
1 2 |
mvn clean package java -jar target/javaboss-boot-1.0-SNAPSHOT.jar |
Application.java
e dal menù contestuale (tasto destro) selezionare l’azione Run As -> Java Application
.
Una volta avviato il server tomcat embedded in SpringBoot testiamo la nostra applicazione aprendo un browser ed verificando le URL:
- http://localhost:8080 che è reindirizzata su
index.xhtml
e che visualizza la pagina di ricerca del personale implementata in Utilizzo di Spring in JSF 2.0. - http://localhost:8080/api/messages che esegue uno dei servizi rest definiti nel progetto descritto in Primi Passi con Spring Boot.
Codice Sorgente
Il codice sorgente completo del progetto è scaricabile qui javaboss-boot-jsf.