L'environnement:
Tomcat 8
Spring Boot 1.5
JSF 2.2
Apache MyFaces
Spring MVC
Code:
J'intègre Spring Boot et JSF 2.2 dans l'environnement Servlet 3.0.
Classes de configuration:
JSFConfig.Java - Configuration pour JSF.
@Configuration
@ComponentScan({"com.atul.jsf"})
public class JSFConfig {
@Bean
public ServletRegistrationBean servletRegistrationBean() {
FacesServlet servlet = new FacesServlet();
return new ServletRegistrationBean(servlet, "*.jsf");
}
}
Classe principale Spring Boot:
@SpringBootApplication
@Import({ // @formatter:off
JPAConfig.class,
ServiceConfig.class, // this contains UserServiceImpl.Java class.
WebConfig.class,
JSFConfig.class,
})
public class SpringbootJpaApplication extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(SpringbootJpaApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SpringbootJpaApplication.class);
}
}
Bean géré:
UserBean.Java - Bean géré pour JSF
@ManagedBean
@SessionScoped
public class UserBean implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
@ManagedProperty(value="#{userServiceImpl}")
private UserServiceImpl userServiceImpl;
public void addUser(){
System.out.println("User Gets added "+this.name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public UserServiceImpl getUserServiceImpl() {
return userServiceImpl;
}
public void setUserServiceImpl(UserServiceImpl userServiceImpl) {
this.userServiceImpl = userServiceImpl;
}
}
Facelets:
home.xhtml - page d'accueil
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://Java.Sun.com/jsf/core"
xmlns:h="http://Java.Sun.com/jsf/html">
<h:head>
<title>JSF 2.0 Hello World</title>
</h:head>
<h:body>
<h2>JSF 2.0 Hello World Example - hello.xhtml</h2>
<h:form>
<h:inputText value="#{userBean.name}"></h:inputText>
<h:commandButton value="Submit" action="#{userBean.addUser}"></h:commandButton>
</h:form>
</h:body>
</html>
faces-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
<lifecycle>
<phase-listener>org.springframework.web.jsf.DelegatingPhaseListenerMulticaster</phase-listener>
</lifecycle>
</faces-config>
Problème :
1) lorsque je soumets un formulaire dans home.xhtml , userBean.addUser
est appelé. 2) userBean.name
est défini avec les valeurs entrées par l'utilisateur. 3) Mais userServiceImpl
est NULL. 4) Est-ce à dire que Spring et JSF ne s'intègrent pas? J'ai également enregistré SpringBeanFacesELResolver
comme mentionné dans
faces-config.xml
J'ai également essayé de supprimer toutes les annotations spécifiques JSF de UserBean.Java et j'ai utilisé uniquement des annotations spécifiques à Spring comme ci-dessous -
@Component
@SessionScoped
public class UserBean implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
@Autowired
private UserServiceImpl userServiceImpl;
}
Mais lorsque je soumets un formulaire, j'obtiens une erreur cible inaccessible pour #{userBean)
. Cela signifie que userBean
n'est pas détectable pour Spring
5) Est-ce que je manque quelque chose ici? 6) Je n'utilise pas Tomcat intégré fourni avec Spring Boot
C'est ainsi que JSF travaille avec Spring Boot (complet exemple de projet chez Github, mis à jour avec JSF 2.3 et Spring Boot 2 ):
1. Dépendances
En plus de la dépendance standard du démarreur Web, vous devrez inclure le jasper intégré Tomcat marqué comme fourni (merci @Fencer pour avoir commenté ici ). Sinon, vous obtiendrez une exception au démarrage de l'application, car JSF dépend du processeur JSP (voir également le premier lien à la fin de ma réponse).
<dependency>
<groupId>org.Apache.Tomcat.embed</groupId>
<artifactId>Tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2. Enregistrement de servlet
Enregistrez le servlet JSF et configurez-le pour qu'il se charge au démarrage (pas besoin de web.xml). Si vous travaillez avec JSF 2.2, le mieux est d'utiliser *.xhtml
mappage, au moins lors de l'utilisation de facettes:
@Bean
public ServletRegistrationBean servletRegistrationBean() {
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(
new FacesServlet(), "*.xhtml");
servletRegistrationBean.setLoadOnStartup(1);
return servletRegistrationBean;
}
Faites en sorte que votre classe de configuration implémente ServletContextAware
afin que vous puissiez définir vos paramètres init. Ici, vous devez forcer JSF à charger la configuration:
@Override
public void setServletContext(ServletContext servletContext) {
servletContext.setInitParameter("com.Sun.faces.forceLoadConfiguration",
Boolean.TRUE.toString());
servletContext.setInitParameter("javax.faces.FACELETS_SKIP_COMMENTS", "true");
//More parameters...
}
3. Intégration EL
Déclarez le résolveur EL dans faces-config.xml. Cela va être le lien entre vos fichiers de vue et vos propriétés et méthodes de bean géré:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver
</el-resolver>
</application>
</faces-config>
4. La portée de la vue
Écrivez une portée Spring personnalisée pour émuler la portée de la vue JSF (gardez à l'esprit que vos beans seront gérés par Spring, pas JSF). Cela devrait ressembler à ceci:
public class ViewScope implements Scope {
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
Map<String, Object> viewMap = FacesContext.getCurrentInstance()
.getViewRoot().getViewMap();
if (viewMap.containsKey(name)) {
return viewMap.get(name);
} else {
Object object = objectFactory.getObject();
viewMap.put(name, object);
return object;
}
}
@Override
public String getConversationId() {
return null;
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
}
@Override
public Object remove(String name) {
return FacesContext.getCurrentInstance().getViewRoot().getViewMap().remove(name);
}
@Override
public Object resolveContextualObject(String arg0) {
return null;
}
}
Et enregistrez-le dans votre classe de configuration:
@Bean
public static CustomScopeConfigurer viewScope() {
CustomScopeConfigurer configurer = new CustomScopeConfigurer();
configurer.setScopes(
new ImmutableMap.Builder<String, Object>().put("view", new ViewScope()).build());
return configurer;
}
5. Prêt à partir!
Vous pouvez maintenant déclarer vos beans gérés comme indiqué ci-dessous. N'oubliez pas d'utiliser @Autowired
(de préférence dans les constructeurs) au lieu de @ManagedProperty
, parce que vous avez affaire à des haricots de printemps.
@Component
@Scope("view")
public class MyBean {
//Ready to go!
}
Toujours en attente de réalisation
Je n'ai pas pu faire fonctionner les annotations spécifiques JSF dans le contexte Spring Boot. Alors @FacesValidator
, @FacesConverter
, @FacesComponent
, etc. ne peut pas être utilisé. Pourtant, il y a la possibilité de les déclarer dans faces-config.xml (voir xsd ), à l'ancienne.
Voir aussi: