Use ISO-8859-1 encoding with JSF 2 on Jboss - jsf

I have a JSP Page which uses the following directive:
<%#page contentType="text/html; charset=iso-8859-1" pageEncoding="iso-8859-1"%>
Hence, forms within the page are sent using ISO-8859-1 encoding and the beans receive (in the setXXX() methods) Strings encoded according to this format.
I want to "translate" the JSP into JSF 2, which uses UTF-8 as default. How can I force JSF to use ISO-8859-1 and hence simulate the page directive?
I use Mojarra + richfaces on jboss 6.
Thank you!

Set the encoding attribute of the <f:view>.
<f:view encoding="ISO-8859-1">
Sticking to a non-Unicode encoding is however not recommended anymore these days. Your webapp would be not ready for world domination and you'd risk Mojibake when an enduser attempts to send Unicode-encoded data anyway (e.g. Hebrew, Cyrillic, Chinese, etc).

I didn't really understand the problem, but this allowed me to avoid Mojibake while using UTF-8 instead of ISO-8859-1:
public class EncodingFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
if (req.getCharacterEncoding() == null) {
req.setCharacterEncoding("UTF-8");
}
chain.doFilter(req, resp);
}
#Override
public void destroy() {
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
Strangely, without this filter I got Mojibakes although I didn't specify any kind of encoding. I also noticed that (filterConfig.getInitParameter("encoding")) in the init() method always returned null.

Related

Setting the header referrer on Primefaces action

This is a follow up to a previous question: Error using JSF protected views when opening a new tab
I am using faces-config protected views to protect against CSRF. I ran into problems earlier with links opened in a new tab that I resolved by adding
rel="noopener noreferrer"
to all new tab links.
But now I' running into the same issue with commandButtons.
I have
<p:commandButton value="Submit"
action="#{bean.submit}" />
And submit() returns a string with the new view. But I still get the following error:
javax.faces.application.ProtectedViewException: JSF1099: Referer [sic] header value http://.../updatestatus.xhtml?javax.faces.Token=1534516398157&cr=45309 does not appear to be a protected view. Preventing display of viewId /finance/commitmentregister/view.xhtml
at com.sun.faces.lifecycle.RestoreViewPhase.maybeTakeProtectedViewAction(Unknown Source)
Is there a way to set no referer or opener on the Primefaces commandbutton?
Edit:
Maybe not the answer I was looking for, but I got around the problem by adding a servlet request wrapper in a filter to return null when asked for the referer.
Further edit:
Adding the rough outline of how my code looks with the wrapper fix:
#WebFilter(filterName = "UserLoginFilter", urlPatterns = { "*.xhtml" })
public class UserLoginFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(httpServletRequest) {
#Override
public String getHeader(String name) {
if (name.equalsIgnoreCase("referer")) {
return null;
} else {
return super.getHeader(name);
}
}
};
chain.doFilter(wrapper, response);
}
}

Google maps autocomplete with JSF error with ÄÖÜ

we're using google maps autocomplete in our JSF application, but when we choose a name with öäü the backingBean gets eg. Ã as value. We have set our meta info of the site to utf-8, but this didn't help in this case.
we added it like this:
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places&key=AIzaSyChQPYNPhodC79W6-oGzlVgQJEwfFMG_bs" />
<script type="text/javascript" charset="utf-8">
function addGMapAutoComplete(componentId) {
var component = document.getElementById('createRequest:' + componentId);
if (component) {
new google.maps.places.Autocomplete(component);
}
}
</script>
and used as
<p:inputText id="pickupLocation"
value="#{createRequest.pickupLocation}" required="true"
onfocus="addGMapAutoComplete('location')"
style="width:350px" />
can anyone help with this issue?
This is a known issue with PrimeFaces. It's incorrectly using server's default encoding (which is often ISO-8859-1) for decoding POST request data of ajax requests, even though JSF/Facelets by itself already by default uses UTF-8 through all layers.
To overcome this, you need to manually set the POST request body encoding to UTF-8 by calling ServletRequest#setCharacterEncoding() with a value of "UTF-8" as early as possible in the request processing (before the parameters are ever parsed out of the POST request body). Most straightforward way would be using a servlet filter for this:
#WebFilter("/*")
public class CharacterEncodingFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
// ...
}
Or, if you happen to use JSF utility library OmniFaces already, then just use its ready-to-use CharacterEncodingFilter by adding the following entries to your webapp's web.xml:
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.omnifaces.filter.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Primefaces component not respond after the session expired

I have a filter which checks the session. My filter:
public class FilterLogin implements Filter{
FilterConfig fc;
#Override
public void init(FilterConfig filterConfig) throws ServletException {
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
fc = filterConfig;
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
HttpSession session = req.getSession(true);
if (session.getAttribute("loginMB") == null) {
resp.sendRedirect("/home.xhtml");
} else {
chain.doFilter(request, response);
}
}
#Override
public void destroy() {
//throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
}
web.xml:
<filter>
<filter-name>filter</filter-name>
<filter-class>pl.ePrzychodnia.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/protected/*</url-pattern>
</filter-mapping>
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/home.xhtml</location>
</error-page>
When the session is expired I should go to the site home.xhtml. But when the session is expired and I want click the navigation menu in the page, the component is not reacting to the click...
When I do not use Primefaces everything works correctly. When I use primefaces in my project I have this error. What could be the cause?
I try use a global exception handler but i have a little problem. I copy class from this site http://wmarkito.wordpress.com/2012/04/05/adding-global-exception-handling-using-jsf-2-x-exceptionhandler/
and edited in class CustomExceptionHandler:
try {
//log error ?
log.log(Level.SEVERE, "Critical Exception!", t);
//redirect error page
requestMap.put("exceptionMessage", t.getMessage());
nav.handleNavigation(fc, null, "/home");
fc.renderResponse();
// remove the comment below if you want to report the error in a jsf error message
//JsfUtil.addErrorMessage(t.getMessage());
}
I change: nav.handleNavigation(fc, null, "/error"); to nav.handleNavigation(fc, null, "/home");
But when session timeout i not reditect to home.xhtml page only go to the page when I clicked and i have a example error:
SEVERE: Critical Exception!
javax.faces.application.ViewExpiredException: viewId:/protected/admin/about.xhtml - View /protected/admin/about.xhtml could not be restored.
when i clicked reference to about page when my session expired. I see a incomplete about.xhtml page instead home.xhtml
Most possibly, you make an ajax call to the managed bean. That is why error navigation does not work in web xml. The error will be send to JavaScript callback onerror if the action is invoked as ajax request.
You can add a global exception handler to application if you want to handle errors on server side. Adding global exception handling using JSF tutorial is a good one to follow.
Furthermore, you can use FullAjaxExceptionHandler feature of OmniFaces

Removing JSESSIONID in URL without using Filter and Wrapper

I have created a Filter listening on an url-pattern of /* which replaces the HttpServletRequest with a HttpServletRequestWrapper implementation.
I have a Servlet and in this Servlet am using h:graphicImage to render images fetching from Apache web server.
<h:graphicImage value="/locationInMyWebServer/myImage.jgp"></h:graphicImage>
When I hit the URL for accessing this page (containing image), the image was not getting displayed as JSESSIONID was getting appended to my image name. The URL that was getting formed was like below.
http:/myDomain/myServlet/../myImage.jpg;JSESSIONID=ABCDEFGHIJKLMM
Hence, I have used the Filter (more details about this filter is here) as stated in the beginning of my question.
From this Servlet there is a link for logging in. When a User logs in, same JSESSIONID is getting retained even after authentication. Since, Session ID is same before logging in and after a user logs in, this is leading to Session-fixation attacks.
How can I avoid using this filter and also solve my problem of JSESSIONID getting appended to images when I use h:graphicImage
PS: I can't use <img src> because my h:graphicImage is inside h:commandLink
Session Id was different before logging in and after logging in , before using this Filter
I have added the relevant code below.
Below code is from my web.xml which has entry for Filter
<filter>
<filter-name>URLSessionFilter</filter-name>
<filter-class>myPackage.web.filter.URLSessionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>URLSessionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
Code in my URLSessionFilter is below,
public class URLSessionFilter implements Filter
{
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
if (!(request instanceof HttpServletRequest))
{
chain.doFilter(request, response);
return;
}
HttpServletResponse httpResponse = (HttpServletResponse)response;
HttpServletResponseWrapper wrappedResponse = new HttpServletResponseWrapper(httpResponse)
{
public String encodeRedirectUrl(String url)
{
return url;
}
public String encodeRedirectURL(String url) {
return url; }
public String encodeUrl(String url) {
return url; }
public String encodeURL(String url) {
return url;
}
};
chain.doFilter(request, wrappedResponse);
}
public void init(FilterConfig filterConfig)
{
}
public void destroy()
{
}
}
There is a link in my Servlet on click of which login page will be displayed. Code is below,
<h:commandLink action="#{myBean.myMethod}">
<h:graphicImage value="/myLocInWebserver/myImage.jpg">
</h:commandLink>
In myBean.myMethod , am doing some DB clean up activities and redirecting to login page.
Another way is avoid the servlet container interpreting something as a URL. To accomplish that, you would avoid any of the special JSP or JSF tags, and directly use HTML tags. In your case - that could look like follows:
<h:commandLink action="#{myBean.myMethod}">
<img src="#{request.contextPath}/myLocInWebserver/myImage.jpg"/>
</h:commandLink>
No more <h:graphicImage> ...
You would still want your context path to be prefixed without any hardcoding - hence the use of #{request.contextPath}.
I recently came to this solution, as I was integrating JavaMelody with my application, and provided a link for admins to the tool. However somehow JavaMelody fails with the ;jsessionid appended. Hence, I am currently generating the URL as follows:
<a href="#{request.contextPath}/monitoring"
target="_blank"
class="ui-link ui-widget"
>
Java Melody Performance Monitoring
</a>
instead of the typical JSF solution
<p:link value="Java Melody Performance Monitoring"
href="/monitoring"
target="_blank"
/>
Which simply won't work.
The benefit of this solution is that I can now control this on a URL by URL basis, and I do not have to worry about setting <tracking-mode>COOKIE</tracking-mode> globally.

Embedding a link (or other html) in a JSF message

I want to embed a link in a JSF message, is this possible?
When I try it, the rendered html of the h:messages tag escapes the html characters. I tried setting the escape attribute of the h:messages tag to false, but that didn't help.
Unfortunately, this is not possible in the standard JSF implementation. The component and the renderer doesn't officially support this attribute. You can however homegrow a renderer which handles this.
Since this is a pretty common requirement/wish, I thought to take a look what's all possible.
First some background information: JSF by default uses ResponseWriter#writeText() to write the tag body, which escapes HTML by default. We'd like to let it use ResponseWriter#write() instead like as with <h:outputText escape="false" />. We'd like to extend the MessagesRenderer of the standard JSF implementation and override the encodeEnd() method accordingly. But since the MessagesRenderer#encodeEnd() contains pretty a lot of code (~180 lines) which we prefer not to copypaste to just change one or two lines after all, I found it better to replace the ResponseWriter with a custom implementation with help of ResponseWriterWrapper wherein the writeText() is been overriden to handle the escaping.
So, I ended up with this:
package com.example;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.context.ResponseWriterWrapper;
import javax.faces.render.FacesRenderer;
import com.sun.faces.renderkit.html_basic.MessagesRenderer;
#FacesRenderer(componentFamily="javax.faces.Messages", rendererType="javax.faces.Messages")
public class EscapableMessagesRenderer extends MessagesRenderer {
#Override
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
final ResponseWriter originalResponseWriter = context.getResponseWriter();
try {
context.setResponseWriter(new ResponseWriterWrapper() {
#Override
public ResponseWriter getWrapped() {
return originalResponseWriter;
}
#Override
public void writeText(Object text, UIComponent component, String property) throws IOException {
String string = String.valueOf(text);
String escape = (String) component.getAttributes().get("escape");
if (escape != null && !Boolean.valueOf(escape)) {
super.write(string);
} else {
super.writeText(string, component, property);
}
}
});
super.encodeEnd(context, component); // Now, render it!
} finally {
context.setResponseWriter(originalResponseWriter); // Restore original writer.
}
}
}
In spite of the #FacesRenderer annotation, it get overriden by the default MessagesRenderer implementation. I suspect here a bug, so I reported issue 1748. To get it to work anyway, we have to fall back to the faces-config.xml:
<render-kit>
<renderer>
<component-family>javax.faces.Messages</component-family>
<renderer-type>javax.faces.Messages</renderer-type>
<renderer-class>com.example.EscapableMessagesRenderer</renderer-class>
</renderer>
</render-kit>
Then, to trigger it, just do:
<h:messages escape="false" />
And it works! :)
Note: the above affects <h:messages> only. To do the same for <h:message>, just do the same, but replace anywhere "Messages" by "Message" (component family, renderer type and classnames).
The escape="false" attributed you need is provided by the OmniFaces <o:messages> component. The OmniFaces utility library is available for JSF 2.
I posted this solution mentioned by #BalusC's comment as an answer since this is the most straightforward solution.

Resources