我已经使用下面的堆栈进行了工作设置 -
春季MVC 5
JSF Mojarra 2.2.14
Primefaces 6.2.9
- 该应用程序是作为 WAR 构建的。
- 它具有配置了 FacesServlet 的 web.xml 来服务 *.xhtml 请求。 JSF 和 Primefaces 的所有初始化参数都定义为 web.xml 中的上下文参数。
- 它还具有定义了 SpringBeanFacesELResolver 的 faces-config.xml。
- @javax.faces.bean.ManagedBean 与 @ManagedProperty 和 JSF 作用域一起用于所有 JSF Managed Bean。托管 Bean 使用 @managementproperty 获取对 Spring beans 的引用,并进行服务调用以填充要在 JSF XHTML 页面中显示的数据。
- @ManagedBean 类也使用 @PostConstruct 进行初始化。
这在 weblogic 应用服务器和 tomcat 中都运行良好。
我们正在尝试使用最新的 2.7.1 版本将其转换为 Spring boot 项目。作为本次活动的一部分
- web.xml 已替换为 java 配置类,如下所示 -
@SpringBootApplication(scanBasePackages = {"com.demo.spring.boot.jsfprimefaces","com.xxx.eee"})
@ImportResource({"classpath:spring-root-config.xml","classpath:spring-security-config.xml","classpath:spring-restclient-config.xml"})
public class JsfPrimefacesApplication implements ServletContextInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration", Boolean.TRUE.toString());
// Set JSF/Primefaces init params
servletContext.setInitParameter("javax.faces.DEFAULT_SUFFIX", ".xhtml");
servletContext.setInitParameter("javax.faces.STATE_SAVING_METHOD", "client");
servletContext.setInitParameter("javax.faces.PROJECT_STAGE", "Production");
servletContext.setInitParameter("javax.faces.VALIDATE_EMPTY_FIELDS", "false");
servletContext.setInitParameter("javax.faces.FACELETS_SKIP_COMMENTS", "true");
//servletContext.setInitParameter("javax.faces.CONFIG_FILES", "/WEB-INF/faces-config.xml");
servletContext.setInitParameter("javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE", "true");
servletContext.setInitParameter("primefaces.THEME", "aristo");
servletContext.setInitParameter("primefaces.PUBLIC_CAPTCHA_KEY", "DDDDD");
servletContext.setInitParameter("primefaces.PRIVATE_CAPTCHA_KEY", "EEEEE");
servletContext.setInitParameter("primefaces.UPLOADER", "commons");
FacesInitializer facesInitializer = new FacesInitializer();
facesInitializer.onStartup(null, servletContext);
}
public static void main(String[] args) {
SpringApplication.run(JsfPrimefacesApplication.class, args);
}
}
很少有其他 @Configuration 类 -
@Configuration
public class PortalFilterConfiguration {
@Bean
public FilterRegistrationBean<RewriteFilter> rewriteFilter() {
FilterRegistrationBean<RewriteFilter> rwFilter = new FilterRegistrationBean<RewriteFilter>(new RewriteFilter());
rwFilter.setDispatcherTypes(
EnumSet.of(DispatcherType.FORWARD, DispatcherType.REQUEST, DispatcherType.ASYNC, DispatcherType.ERROR));
rwFilter.addUrlPatterns("/*");
return rwFilter;
}
}
@Configuration
public class PortalListenerConfiguration {
@Bean
public ServletListenerRegistrationBean<JsfApplicationObjectConfigureListener> jsfConfigureListener() {
return new ServletListenerRegistrationBean<JsfApplicationObjectConfigureListener>(
new JsfApplicationObjectConfigureListener());
}
static class JsfApplicationObjectConfigureListener extends ConfigureListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
super.contextInitialized(sce);
ApplicationFactory factory = (ApplicationFactory) FactoryFinder
.getFactory(FactoryFinder.APPLICATION_FACTORY);
Application app = factory.getApplication();
app.addELResolver(new SpringBeanFacesELResolver());
}
}
}
@Configuration
public class PortalServletConfiguration {
@Bean
public ServletRegistrationBean<FacesServlet> jsfServletRegistration(ServletContext servletContext) {
ServletRegistrationBean<FacesServlet> srb = new ServletRegistrationBean<FacesServlet>();
srb.setServlet(new FacesServlet());
srb.setUrlMappings(Arrays.asList("*.xhtml"));
srb.setLoadOnStartup(1);
return srb;
}
}
以下是 pom.xml 内容 -
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo.spring.boot</groupId>
<artifactId>jsf-primefaces</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jsf-primefaces</name>
<description>Demo project for Spring Boot JSF Primefaces</description>
<packaging>war</packaging>
<repositories>
<repository>
<id>no-commons-logging</id>
<name>No-commons-logging Maven Repository</name>
<layout>default</layout>
<url>http://repository.jboss.org/</url>
</repository>
<repository>
<id>prime-repo</id>
<name>Prime Repo</name>
<url>http://repository.primefaces.org</url>
</repository>
<repository>
<id>localrepository</id>
<url>file://../3rd-Party-Dependencies</url>
</repository>
</repositories>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<scope>runtime</scope>
</dependency>
<!-- JSF Libraries -->
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.2.14</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.2.14</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!-- Primefaces & its dependent jars -->
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>6.2.9</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>org.ocpsoft.rewrite</groupId>
<artifactId>rewrite-servlet</artifactId>
<version>3.4.1.Final</version>
</dependency>
<dependency>
<groupId>org.ocpsoft.rewrite</groupId>
<artifactId>rewrite-config-prettyfaces</artifactId>
<version>3.4.1.Final</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>net.sf.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.24</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<outputDirectory>src/main/webapp/WEB-INF/classes</outputDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
faces-config.xml 放置在 src/main/webapp/WEB-INF 下。内容如下——
<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 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>
<locale-config>.....
<resource-bundle>.....
</application>
</faces-config>
ISSUE
应用程序启动正常。但似乎没有一个 JSF 托管 bean 被初始化,因为我根本没有看到 @PostContruct 方法被调用。所有使用托管 bean 名称的 EL 引用(例如 #{})都会失败,并出现以下错误:
javax.faces.view.facelets.TagAttributeException Attribute did not evaluate to a String or Locale: null
当我在 @ManagedBean 之上添加 @Component 到 JSF 托管 bean 之一时,这会导致调用 @PostConstruct ,这可能意味着在我们的旧设置中,@ManagedBean 类由 JSF 加载,但在这个新设置中,它们会得到被忽略。
任何人都可以帮忙建议需要做什么才能使这项工作成功吗?
Regards
Jacob
UPDATE 1
根据评论,修改了配置类如下 -
@SpringBootApplication(scanBasePackages = { "com.demo.spring.boot.jsfprimefaces", "com.ddd.efulfillment" })
@ImportResource({ "classpath:spring-root-config.xml", "classpath:spring-security-config.xml",
"classpath:spring-restclient-config.xml" })
public class JsfPrimefacesApplication extends SpringBootServletInitializer {
@Bean
public ServletContextInitializer servletContextInitializer() {
return servletContext -> {
//servletContext.addListener(com.sun.faces.config.ConfigureListener.class);
servletContext.setInitParameter("com.sun.faces.forceLoadConfiguration", Boolean.TRUE.toString());
// Set JSF/Primefaces init params
servletContext.setInitParameter("javax.faces.DEFAULT_SUFFIX", ".xhtml");
servletContext.setInitParameter("javax.faces.STATE_SAVING_METHOD", "client");
servletContext.setInitParameter("javax.faces.PROJECT_STAGE", "Production");
servletContext.setInitParameter("javax.faces.VALIDATE_EMPTY_FIELDS", "false");
servletContext.setInitParameter("javax.faces.FACELETS_SKIP_COMMENTS", "true");
// servletContext.setInitParameter("javax.faces.CONFIG_FILES",
// "/WEB-INF/faces-config.xml");
servletContext.setInitParameter("javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE",
"true");
servletContext.setInitParameter("primefaces.THEME", "aristo");
servletContext.setInitParameter("primefaces.PUBLIC_CAPTCHA_KEY",
"ddd");
servletContext.setInitParameter("primefaces.PRIVATE_CAPTCHA_KEY",
"ssss");
servletContext.setInitParameter("primefaces.UPLOADER", "commons");
FacesInitializer facesInitializer = new FacesInitializer();
facesInitializer.onStartup(null, servletContext);
};
}
public static void main(String[] args) {
SpringApplication.run(JsfPrimefacesApplication.class, args);
}
但仍然存在同样的问题。
在调试时,似乎托管 bean 通过方法“processAnnotations(ManagedBean.class);”在 com.sun.faces.config.processor.ManagedBeanConfigProcessor 类中标识。它有类似于下面的代码
FacesContext ctx = FacesContext.getCurrentInstance();
ApplicationAssociate associate =
ApplicationAssociate.getInstance(ctx.getExternalContext());
AnnotationManager manager = associate.getAnnotationManager();
manager.applyConfigAnnotations(ctx,
annotationType,
ConfigManager.getAnnotatedClasses(ctx).get(annotationType));
我认为 @ManagedBean 注释类的 MAP 为 NULL。不知道为什么。