Thursday, December 08, 2011

JSF 1.2 (myFaces) + RichFaces 3.3.x + IE 9 = troubles

Note: below description uses Eclipse Indigo, Tomcat 7.0.28, MyFaces 1.2.12, RichFaces 3.3.3 (Final).

Requirements:
  • working JSF 1.2 sample application from here
  • RichFaces 3.3.x added to the project
You will learn:
  • how to fix problems with RichFaces 3.3.x for IE 9
Let's assume that You develop JSF 1.2 web application. It does not matter if Your application uses .jsp pages or Facelets with .xhtml pages. I assume that .jsp pages are in use. Then You decided to add some Ajax capabilities, new components and so on. So You simply take RichFaces and add them to the project. This is simple thing:
a) download latest RichFaces 3.3.3 (final), take those jars: richfaces-api-3.3.3.Final.jar, richfaces-impl-3.3.3.Final.jar, richfaces-ui-3.3.3.Final.jar and place them in WEB-INF\lib folder of Your web application. 
b) modify your web.xml file by adding there:
 <filter>
  <display-name>RichFaces Filter</display-name>
  <filter-name>richfaces</filter-name>
  <filter-class>org.ajax4jsf.Filter</filter-class>
 </filter>

 <filter-mapping>
  <filter-name>richfaces</filter-name>
  <servlet-name>Faces Servlet</servlet-name>
  <dispatcher>REQUEST</dispatcher>
  <dispatcher>FORWARD</dispatcher>
  <dispatcher>INCLUDE</dispatcher>
 </filter-mapping>
c) add proper taglib directives to each Your jsp page (note that for .xhtml pages syntax is different):
<%@ taglib uri="http://richfaces.org/a4j" prefix="a4j"%>
<%@ taglib uri="http://richfaces.org/rich" prefix="rich"%>
Now You can use RichFaces components. Let's try to modify our sample JSF 1.2 application by creating new web project named "JSFRichFaces". Then let's add ajax button (<a4j:commanButton>) and expandable toggle panel (<rich:simpleTogglePanel>). All modifications are shown below:




Everything works OK under Firefox, Chrome, IE 7, IE 8 - unless You use Internet Explorer 9. You can observe two problems: with RichFaces ajax components and RichFaces components layout.

RichFaces 3.3.x does not fully support IE 9. RichFaces developers encourage everyone to migrate into RichFaces 4.x which are IE 9 compatible. The main problem is that RichFaces 4.x works only with JSF 2.x application, and this is not so easy to migrate If You have many clients where You already delivered Your application...

Problem 1: ajax components do not work (some JavaScript errors).


When You try to press ajax button named "Go (RichFaces) " under IE 9, You can observe following error (open IE Developer's Toolbar Java Script console before):





Solution: You have to force IE 9 to act as IE 8, where RichFaces 3.3.x works OK. In order to do it You have to define X-UA-Compatible header for each page. You can do it in two ways:
a) add a special <meta> element for each page or
b) write a special filter which adds this header to the HTTP response

In our simple case it is sufficient to add a <meta> into the page <head> section:

<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" />
Remember that this <meta> must be placed as first element in <head> section!

Problem 2: RichFaces components have broken layout (problems with CSS).


When You open our sample application under IE 9, toggle panel has no CSS styles set at all. Under Chrome or Firefox everything looks OK. Checking HTTP request/response headers shows that for IE 9 proper CSS for RichFaces component (CSS located in the .jar file) is not loaded and server returns error:





Console under Eclipse shows that exception is thrown:



Under Firefox everything looks OK:






Why it happens? Accroding to that article, there was a change in IE 9 for MIME type handling. IE 9 ignores CSS styles if they are not delivered with a text/css MIME type.

Why it works for previous IE 7 and IE 8? Because also HTTP Request Accept header sent by IE 9 is different than sent from IE 7 or 8. IE 7/8 sent text/css, */* as Accept, where IE 9 sends only text/css as Accept.
Knowing that it is time to look inside myFaces source, to find the code which produces mentioned exception. Everything is located in HtmlRendererUtils.java (located in myfaces-impl-1.2.11.jar) in the selectContentType() method. It works for IE 7/8 because */* sent in Accept by IE 7/8 is on supported content type list, where text/css is not recognized at all.

Solution: add text/css support, then recompile HtmlRendererUtils.java and replace it in myfaces-impl-1.2.11.jar (or build complete myfaces-impl-1.2.11.jar). In order to avoid this mumbo-jumbo with Maven to build whole .jar, just create simple Java Project, create a HtmlRendererUtils.java in certain package, change it and compile, then replace compiled class in myfaces-impl-1.2.11.jar ;-)





Or download recompiled myfaces-impl-1.2.11.jar from here.


That's all. IE 9 works again without need to add Your web page to its compatibility view list or something. And You have time to migrate to JSF 2.x and RichFaces 4.x before IE 10 comes to market...