Java Server Faces (JSF) Web-Applications: Tuning and Configuration
Learn how to increase the security and UI/UX of your Java-based web application using XML and the Java Server Faces framework.
Join the DZone community and get the full member experience.
Join For FreeIntroduction
Recently, and during helping many organizations in government, banking and educational domains developing Java web-based applications using Java Server Faces (JSF) technology, I have noticed that most developers and technical teams misconfigure different aspects of JSF applications, which dramatically affected the behavior, performance, and security of those applications.
In this article, I will present the required configurations and tuning to ensure the stability, security, and performance of JSF applications.
Note: For more information about building high-quality JSF applications, it is highly recommanded that you read “Java Server Faces in Real-life applications.” article.
Web-Application (Servlets) Version
You can configure Java web applications (Servlets container) to use either version 3.0 or 3.1, which should be configured based on your web server version.
This can be done by:
Creating web.xml in WEB-INF folder if it doesn't already exist.
Ensure that web-app tag contains the following configurations:
For servlet 3.0
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
</web-app>
For servlets 3.1
<?xml version="1.0" encoding="UTF-8"?>
<web-app
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-app_3_1.xsd"
version="3.1">
</web-app>
JSF Version
To force JSF to use version 2.2 :
- Create a faces-config.xml file in the WEB-INF folder if doesn't already exist.
- Be sure that the faces-config tag is configured as follows:
<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">
</faces-config>
View-Expired Exception
One of the issues that developers frequently face during development or testing is the ViewExpiredException which is caused by losing the state of the JSF view during the servlet container restarts. This issue can easily be solved by adding the following context parameter to WEB-INF/web.xml :
<context-param>
<param-name>com.sun.faces.enableRestoreView11Compatibility</param-name>
<param-value>true</param-value>
</context-param>
Time Zone
In JSF, the default time-zone is UTC time-zone, not the system time-zone, which will cause many issues, especially in the calendar, date and time components.
This can be solved by adding the following context parameter to WEB-INF/web.xml:
<context-param>
<param-name>javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE</param-name>
<param-value>true</param-value>
</context-param>
Development Mode
To force the page to reload and refresh the mode for all JSF views without the need to restart the server or redeploy the web application, add the following context parameters to the WEB-INF/web.xml:
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>facelets.REFRESH_PERIOD</param-name>
<param-value>0</param-value>
</context-param>
Production Mode
In production mode, reloading the pages and JSF views in every request will dramatically and negatively affect the performance of the application. To increase the performance, in this case, the solution is view caching. To do so, change the development mode tags to be as follows in the WEB-INF/web.xml:
<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>facelets.REFRESH_PERIOD</param-name>
<param-value>-1</param-value>
</context-param>
JSF Tree and Components Caching
Another main issue that most JSF developers face is the overhead caused by the view components tree (JSF tree) processing during the JSF life cycle. However, most of the JSF tree components are do not need to be processed every time; for example, the dynamic header, footer and application scope menus will not change during the application scope. Also, the user level menu will be the same during the user session in most of the applications, and processing these components in the JSF tree doesn’t make sense, and can be avoided using OmniFaces cache components.
OmniFaces cache can be used as follows:
- Add the Omnifaces dependency to your pom.xml (assuming you use maven).
- Add xmlns to your HTML tag in the JSF view.
xmlns:of=http://omnifaces.org/ui
3. Encapsulate the block you want to cache inside the <of:cache> tag , for example:
<of:cache scope="session" reset="#{mb.resetCache}">
...
...
</of:cache>
This example will cache the encapsulated tags during the session. The second parameter will reset the cache for this object of the method, and resetCache() will return as true. Of course, you can cache the components in different scopes, such as the application's view scopes.
Ajax Exception, Debugging and Error-Pages
Another common issue is the handling exception during Ajax requests, where Faces's servlet behavior, in this case, is strangely just eating the exception.
To solve this issue:
- Add OmniFaces dependency to your maven project as mentioned in the previous section.
- Cause the exception thrown during the Ajax request to be handled the same way as a normal request by using the Omnifaces FullAjax handler, and by adding the following to WEB-INF/faces-config.xml file:
<factory>
<exception-handler-factory>org.omnifaces.exceptionhandler.FullAjaxExceptionHandlerFactory</exception-handler-factory>
</factory>
3. Add the following section to WEB-INF/web.xml:
<error-page>
<exception-type>com.sun.faces.context.FacesFileNotFoundException</exception-type>
<location>/pages/error/file-not-found.xhtml</location>
</error-page>
<error-page>
<exception-type>java.lang.RuntimeException</exception-type>
<location>/pages/error/bug.xhtml</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/pages/error/error.xhtml</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/pages/error/page-not-found.xhtml</location>
</error-page>
4. Create the error and exception handler pages in the /pages/error folder. These pages could include code like this (this code has been taken from Omni-faces website):
<ul>
<li>Date/time: #{of:formatDate(now, 'yyyy-MM-dd HH:mm:ss')}</li>
<li>User agent: #{header['user-agent']}</li>
<li>User IP: #{request.remoteAddr}</li>
<li>Request URI: #{requestScope['javax.servlet.error.request_uri']}</li>
<li>Ajax request: #{facesContext.partialViewContext.ajaxRequest ? 'Yes' : 'No'}</li>
<li>Status code: #{requestScope['javax.servlet.error.status_code']}</li>
<li>Exception type: #{requestScope['javax.servlet.error.exception_type']}</li>
<li>Exception message: #{requestScope['javax.servlet.error.message']}</li>
<li>Stack trace:
<pre>#{of:printStackTrace(requestScope['javax.servlet.error.exception'])}</pre>
</li>
</ul>
Conclusion
Java Server Faces (JSF) is the standard technology for building web applications in Java. However, during the development and deployment of JSF applications, there are many tuning and configurations that should be implemented to make the applications more secure, reliable, and efficient. In this article, we covered the required tunings and configurations that can be used as a unified reference for JSF developers.
Opinions expressed by DZone contributors are their own.
Comments