pretty faces configuration to remove folder from URL (JSF2.2 application deployed on Glassfish) - jsf

I have JSF 2.2 application deployed on glassfish.
I wan't to beautify the URL
http://MyWebsite/test/SOMEFOLDER/login.xhtml
to be
http://MyWebsite/test/login.xhtml
I am using pretty faces using the follow configuration
<url-mapping id="login">
<pattern value="/login.xhtml" />
<view-id value="/SOMEFOLDER/login.xhtml" />
<!-- Non JSF View Id -->
</url-mapping>
I am not adding anything in the web.xml

Related

PrettyFaces 404 page without URL redirect

In our app with PrettyFaces 2.0.12.Final, we have our redirects set up in pretty-config.xml.
<url-mapping id="foo">
<pattern value="/foo/#{alias}" />
<view-id value="/foo.xhtml" />
</url-mapping>
We have a custom 404 page set up in our web.xml.
<error-page>
<error-code>404</error-code>
<location>/404.xhtml</location>
</error-page>
When a user receives a 404 Not Found error, for a foo "alias" that doesn't exist, they're redirected to "/404.xhtml", and the browser URL bar does not retain the offending address.
Is there a way maintain the URL of "/foo/aliasdoesnotexist" in the browser URL bar and still display the 404 page?
One way to handle this scenario is to handle the Exception in your application and perform an internal forward to the error page:
You can set up a PrettyFaces mapping for the 404 page:
<url-mapping id="foo">
<pattern value="/foo/#{alias}" />
<view-id value="/foo.xhtml" />
</url-mapping>
Then in your application code:
catch ( Exception e )
{
String contextName = FacesContext.getCurrentInstance().getExternalContext().getContextName();
FacesContext.getCurrentInstance().getExternalContext().dispatch(contextName + "/404");
}
If you want to catch the exception globally, you'll need to create a servlet filter to do this. See the following topic for how to create a filter that catches all exceptions:
how do I catch errors globally, log them and show user an error page in J2EE app
Hope this helps!
~Lincoln

PrettyFaces fails in Wildfly 8.1.0 but works in 8.0.0

PrettyFaces kills the session on every request that involves a redirect when the application is deployed on Wildfly 8.1.0.Final. The same app deploys and works properly on Wildfly 8.0.0.Final.
On 8.1.0 PrettyFaces appears to prevent the servlet stack from retreiving the session ID.
The log shows no exceptions in either case. The URL rewrites occur, but session information (including login information) is gone. This is my pretty-config.xml
<pretty-config xmlns="http://ocpsoft.org/schema/rewrite-config-prettyfaces"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ocpsoft.org/schema/rewrite-config-prettyfaces
http://ocpsoft.org/xml/ns/prettyfaces/rewrite-config-prettyfaces.xsd">
<url-mapping id="user-settings">
<pattern value="/protected/user/settings/"/>
<view-id value="/protected/usersettings.xhtml"/>
</url-mapping>
<url-mapping id="thread-edit">
<pattern value="/protected/threads/edit/#{stitchId}/" />
<view-id value="/protected/threads/stitch.xhtml" />
<action>#{stitchEditBean.editStitchFromId(stitchId)}</action>
</url-mapping>
<url-mapping id="threads-index">
<pattern value="/protected/threads/" />
<view-id value="/protected/threads/index.xhtml" />
</url-mapping>
</pretty-config>
The failure occurs for both PrettyFaces 2.0.12.Final and 3.0.0.Alpha2
As Ken noted, the underlying problem is related to https://issues.jboss.org/browse/WFLY-3448
Adding an explicit cookie path to web.xml works around the issue and is safe.
<session-config>
<session-timeout>30</session-timeout>
<cookie-config>
<!--
A bug in wildfly 8.1.0.final requires this path to be set explicitly or occasionally the default is
incorrect and the system will generate one cookie per directory incorrectly.
-->
<path>/</path>
</cookie-config>
</session-config>
You may have to manually clear the bad cookies in EACH directory of your app, or flush all your session cookies. Otherwise the old session cookies might hang around causing the issue.
This is a bug in WildFly 8.1.0, addressed here: https://issues.jboss.org/browse/WFLY-3448
After you are on a version that has that bug fixed, you will need to use Rewrite 3.0.0.Alpha3 or newer to resolve additional issues for handling the root context path.

Create a link to a JSF page in a subfolder

I have a Java web app with the following structure:
- Project
- Web Pages
+ WEB-INF
+ resources
- administration
systemsettings.xhtml
userhandling.xhtml
login.xhtml
index.xhtml
menubar.xhtml
...
+ Source Packages ...
I recently added the administration folder to the Web Pages, and I moved there the two .xhtml pages so I can write more specific URL pattern for my administrator authorization filter.
However, I don't know what is the path for the pages in the administration folder. While <a href='index.xhtml'> works, <a href='administration/systemsettings.xhtml'> doesn't, throws java.io.FileNotFoundException.
Update:
The content of the systemsettings.xhtml was:
<h:body>
<ui:insert name="header" >
<ui:include src="menubar.xhtml" />
</ui:insert>
<div>Administration - System settings</div>
</h:body>
I forgot to update the path to the included page, after the refactor. This can be fixed, as #BalusC suggested, by changing the <ui:include src="menubar.xhtml" /> to <ui:include src="/menubar.xhtml" />.
If a link does not start with a scheme like http://, then it's a relative link which is relative to the current request URI as you see in browser's address bar. If a relative link starts with /, then it's relative to the domain root in request URI. If a relative link does not start with / then it's relative to the currently opened folder in request URI.
If you can't tell about the currently opened folder for sure, then you need to make it a domain-relative link by explicitly prepending the context path as available by #{request.contextPath}.
settings
An alternative is to just use JSF <h:link> component. It will automatically prepend the context path (and also automatically apply the JSF mapping!). The following <h:link> examples generate equivalent HTML.
<h:link value="settings" outcome="/administration/systemsettings.xhtml" />
<h:link value="settings" outcome="/administration/systemsettings" />

Set HTTP headers properly to force caching on JS, CSS and PNG files

How can I tell to GlassFish server, to store all JS, CSS and PNG files into browser cache in order to reduce HTTP GET requests?
I am using JSF and PrimeFaces.
Just make use of JSF builtin resource handler. I.e. use <h:outputStylesheet name>, <h:outputScript name> and <h:graphicImage name> with files in /resources folder instead of "plain vanilla" <link rel="stylesheet">, <script> and <img>.
<h:outputStylesheet name="css/style.css" />
<h:outputScript name="js/script.js" />
<h:graphicImage name="images/logo.png" />
This way you don't need to worry about resource caching at all. JSF builtin resource handler has already set the necessary response headers. The expiration time defaults already to 1 week.
In Mojarra you can control the expiration time by the following context parameter (the value is in millis):
<context-param>
<param-name>com.sun.faces.defaultResourceMaxAge</param-name>
<param-value>3628800000</param-value> <!-- 6 weeks. -->
</context-param>
And in MyFaces:
<context-param>
<param-name>org.apache.myfaces.RESOURCE_MAX_TIME_EXPIRES</param-name>
<param-value>3628800000</param-value> <!-- 6 weeks. -->
</context-param>
See also:
How to reference CSS / JS / image resource in Facelets template?
What is the JSF resource library for and how should it be used?

Spring Webflow JSF View Location

i´m trying to setup a JSF application with Spring Web Flow.
I´m using Spring 3.1
Spring faces 2.3.1
JSF (api,impl) 2.1.6
My problem is the following that the program is not taking the correct
location of my jsf views.
I have found some tutorials like
or http://dgparsons.org/jsf-and-spring-webflow.html
for integrating jsf and spring web flow.
In one of these view resolving is done with:
<bean id="faceletsViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.faces.mvc.JsfView"/>
<property name="prefix" value="/WEB-INF/views" />
<property name="suffix" value=".xhtml" />
</bean>
And so I put my xhtml files in the folder /WEB-INF/views/
My Flow is in the directory /WEB-INF/config/flow/start.flow
When I gave it a try the program always wants to open the start.xhtml
from the folder /WEB-INF/config/flow/start.xhtml
So it seems it is completly ignoring the UrlBasedViewResolver.
My FlowBuilderServices is configured as following:
<beans:bean id="flowBuilderServices"
class="org.springframework.webflow.engine.builder.support.FlowBuilderServices">
...
<beans:property name="viewFactoryCreator">
<beans:bean
class="org.springframework.faces.webflow.JsfViewFactoryCreator" />
</beans:property>
...
</beans:bean>
In the tutorials there is no JsfViewFactoryCreator and I cant find a tutorial about it.
As from the javadoc JsfViewFactoryCreator/JsfViewFactory is responsible for the RESTORE_VIEW phase.
So I dived into the source code of the getView() Method of the JsfViewFactory.
JsfViewFactory.java
In line 105
UIViewRoot viewRoot = viewHandler.restoreView(facesContext, viewName);
a FlowViewHandler is called, which generates the wrong path relative to the path of my flow files.
resourcePath = resolveResourcePath(RequestContextHolder.getRequestContext(), viewId);
So my question is now. How can I associate the UrlBasedViewResolver correctly with the flowRegistry/flowbuilderservices so that it takes /WEB-INF/views/*.xthml as my path to the xhtml files.
Or if it is maybe old fashioned to use UrlBasedViewResolver (as I didnt see it in the spring web flow documentation for jsf) how can the webflow beans be configured correctly to use the directories i defined.
For completeness here is my webflow-config.xml file
<!-- Executes flows: the central entry point into the Spring Web Flow system -->
<flow-executor id="flowExecutor">
<flow-execution-listeners>
<listener ref="facesContextListener" />
<listener ref="securityListener" />
</flow-execution-listeners>
</flow-executor>
<!-- The registry of executable flow definitions -->
<flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices"
base-path="/WEB-INF/config/flow">
<flow-location-pattern value="/*.xml" />
</flow-registry>
<beans:bean id="flowBuilderServices"
class="org.springframework.webflow.engine.builder.support.FlowBuilderServices">
<beans:property name="expressionParser">
<beans:bean
class="org.springframework.webflow.expression.el.WebFlowELExpressionParser">
<beans:constructor-arg>
<beans:bean class="com.sun.el.ExpressionFactoryImpl" />
</beans:constructor-arg>
</beans:bean>
</beans:property>
<beans:property name="viewFactoryCreator">
<beans:bean
class="org.springframework.faces.webflow.JsfViewFactoryCreator" />
</beans:property>
<beans:property name="conversionService">
<beans:bean
class="org.springframework.binding.convert.service.DefaultConversionService">
</beans:bean>
</beans:property>
</beans:bean>
So finally I found the way to it myself and it was quite simple.
As written in the documentation of spring webflow under - Specifying view identifiers
Spring Webflow Documentation
the solution is to use an absolute view identifier in the flow definition:
<view-state id="enterBookingDetails" view="/WEB-INF/hotels/booking/bookingDetails.xhtml">
Thus there is no need for a URLBasedViewResolver or a special configuration of JSFViewFactoryCreator.

Resources