Resource Handler problems with JSF2 + Richfaces4 + SpringMVC + WebFlow (SWF)
I've been trying to get the above mentioned setup working for days now with minimal success. My issues appears to be with the resource handler. Ie.
<h:outputStylesheet name="header.css" library="page"/>
does not work, NOR can RichFaces resolve any of the resources it uses internally. So i've done some investigating and the tag above should be resolving to "/project/javax.faces.resource/header.css?ln=page" but it is not. 2 obvious issues are occuring.
1) Something in the Resource Handler chain, possibly the richfaces handler, is expecting a ".jsf" suffix to be added to the requested url, which does happen when using the old EXTERNAL facelets w/ JSF2 & RichFaces 3.3.x, but with Richfaces 4 & builtin facelets that doesn't take place. As a result, one of the handlers (RichFaces' I believe) is stripping the .css suffix off thinking it's an extra suffix like how it used to work. (Consequently this causes missing MIME type errors)
2) When the library & name attributes are resolved, the are resolved under the current path instead of the servlet context root. Ie. it should be resolving to "/project/javax.faces.resource/..." but instead it resolves to "/project/index/javax.faces.resource/..." when viewing a page in the /index directory.
Can anyone please give me some insight here? I'm banging my head against the wall on this one & not making any real ground.
btw here is my basic config....
faces-config.xml
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
web.xml
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servle开发者_Go百科t-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Spring MVC Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Spring MVC Servlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
servlet-context.xml
<beans:bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<beans:property name="viewClass" value="org.springframework.faces.mvc.JsfView"/>
<beans:property name="prefix" value="/WEB-INF/content/" />
<beans:property name="suffix" value=".xhtml" />
</beans:bean>
<beans:bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<beans:property name="order" value="2"/>
<beans:property name="flowRegistry" ref="flowRegistry" />
</beans:bean>
<beans:bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
<beans:property name="flowExecutor" ref="flowExecutor" />
<beans:property name="ajaxHandler">
<beans:bean class="org.springframework.faces.richfaces.RichFacesAjaxHandler"/>
</beans:property>
</beans:bean>
<beans:bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<beans:property name="viewClass" value="org.springframework.faces.mvc.JsfView"/>
<beans:property name="prefix" value="/WEB-INF/content/" />
<beans:property name="suffix" value=".xhtml" />
</beans:bean>
<beans:bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<beans:bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<beans:property name="order" value="3" />
<beans:property name="alwaysUseFullPath" value="true" />
<beans:property name="mappings">
<beans:value>
</beans:value>
</beans:property>
<beans:property name="defaultHandler">
<beans:bean class="org.springframework.web.servlet.mvc.UrlFilenameViewController" />
</beans:property>
</beans:bean>
webflow-config.xml
<faces:resources/>
<beans:bean id="facesContextListener" class="org.springframework.faces.webflow.FlowFacesContextLifecycleListener"/>
<flow-executor id="flowExecutor">
<flow-execution-listeners>
<listener ref="facesContextListener"/>
</flow-execution-listeners>
</flow-executor>
<flow-registry id="flowRegistry" base-path="/WEB-INF/content" flow-builder-services="flowBuilderServices">
<flow-location-pattern value="/**/flow.xml" />
</flow-registry>
<flow-builder-services id="flowBuilderServices" development="true" />
Ok so I FINALLY nailed this one... with a little help from Rich Faces. So for anyone who is interested in running JSF2 + Rich Faces + SpringMVC + Spring WebFlow on Tomcat6+, well here is what you need...
WEB.XML
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/appServlet/servletContext.xml</param-value>
</context-param>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<servlet>
<servlet-name>faces</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>faces</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<context-param>
<param-name>javax.faces.FACELETS_VIEW_MAPPINGS</param-name>
<param-value>*.xhtml</param-value>
</context-param>
servletContext.xml
<mvc:annotation-driven />
<context:component-scan base-package="com.package.subpackage"/>
<mvc:resources location="/" mapping="/resources/**" />
<faces:resources order="0" />
<bean id="flowHandlerMapping"
class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<property name="flowRegistry" ref="flowRegistry" />
<property name="order" value="3" />
<property name="defaultHandler" ref="defaultHandler" />
</bean>
<bean class="org.springframework.faces.webflow.JsfFlowHandlerAdapter">
<property name="flowExecutor" ref="flowExecutor" />
<property name="ajaxHandler">
<bean class="org.springframework.faces.richfaces.RichFacesAjaxHandler" />
</property>
</bean>
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.faces.mvc.JsfView"/>
<property name="prefix" value="/WEB-INF/pageContent/" />
<property name="suffix" value=".xhtml" />
</bean>
springmvc-config.xml
<bean name="jsfResourceHandlerHack" class="org.springframework.faces.webflow.JsfResourceRequestHandler" />
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="order" value="1" />
<property name="mappings">
<value>
/rfRes/**=jsfResourceHandlerHack
</value>
</property>
</bean>
spring-webflow-config.xml
<!-- Executes flows: the central entry point into the Spring Web Flow system -->
<flow-executor id="flowExecutor">
<flow-execution-listeners>
<listener ref="facesContextListener"/>
</flow-execution-listeners>
</flow-executor>
<flow-registry id="flowRegistry" base-path="/WEB-INF/content" flow-builder-services="facesFlowBuilderServices">
<flow-location-pattern value="/**/flow.xml" />
<flow-location id="parent-flow" path="parent-flow.xml"/>
</flow-registry>
<faces:flow-builder-services id="facesFlowBuilderServices" development="true"/>
<beans:bean name="facesContextListener" class="org.springframework.faces.webflow.FlowFacesContextLifecycleListener" />
spring-beans-config.xml `
<bean name="defaultHandler" class="org.springframework.web.servlet.mvc.UrlFilenameViewController" >
</bean>`
The Jar versions are as follows... Spring Core 3.0.5 Spring Web Flow 2.2.1 JSF RI 2.0.3 and most importantly... Rich Faces 4.0.0.20101226-M5
So the key to making this work seemed to be the version of RichFaces. RichFaces 4 is not production ready yet, so hopefully once that happens everything will be working smoothly but in the meantime, now that Milestone 5 has been released, this setup seems to work. The part to take note of is the JsfResourceHandlerHack mapping. Richfaces attempts to resolve some of its resources (the ones created on the fly I believe) using the keyword "rfRes" by default. The problem I had was the "rfRes" key is not being mapped to the resource handler. There is a way to configure it, but that didn't seem to be working. So the quick fix is to create another resource handler instance and map it manually. So for anyone who is interested, there it is.
I think your question is answered in https://jira.springsource.org/browse/SWF-1366.
Good luck
精彩评论