If a user decides to delete text that was entered in an inputTextbox, it magically reappears when the component is re-rendered.

     <!-- this allows a user to delete the value in an inputText and have that
           saved instead of the previous value magically disappearing. -->
     <context-param>
           <param-name>javax.faces.VALIDATE_EMPTY_FIELDS</param-name>
           <param-value>true</param-value>
     </context-param>

The f:ajax render attribute doesn’t work if the component specified is the component holding the f:ajax component – the component specified has to have a different container/parent. The solution is to add an extra wrapper around the component. The wrapper must be referred to with the full id (including the form id).

   <!-- this wrapper needs to be here for the f:ajax to re-render.
    from http://stackoverflow.com/questions/2424757/ajax-render-attribute-dont-work-in-a-hdatatable-in-jsf2.
    the bad grammar is not my fault. -->
   <h:panelGroup id ="dataTableDiagCodesWrapper">
   <h:dataTable value="#{controller.claim.diagnosisCodes}" var="d"
      id="dataTableDiagCodes" rowClasses="color1,color2">
 
       <h:column>
           <h:outputText id="header_diagnosisCode" value="Diagnosis Code" />
           <h:inputText value="#{d.code}" escape="false" id="aDiagnosisCode">
                <f:ajax execute="@this @form" render=":form:dataTableDiagCodesWrapper" />
           </h:inputText>
       </h:column>
   </h:dataTable>
   </h:panelGroup>

Issue: The date saved when using f:convertDateTime is off by one day, or off by some number of hours.

The issue is due to the default date/time converter in JSF using GMT instead of the system’s default time zone, so you can

1) specify the time zone directly in the converter, e.g.

<f:convertDateTime pattern="MM/dd/yyyy" timeZone="#{bean.timeZone}"/>

using

public TimeZone getTimeZone() {
     return TimeZone.getDefault();
}

in the bean (from http://www.mail-archive.com/users@myfaces.apache.org/msg27626.html), or you could

2) use a custom converter for the Date values, which looks like this:

faces-congif.xml:

<converter>
  <converter-for-class>java.util.Date</converter-for-class>
  <converter-class>com.coaccess.utilities.CustomDateTimeConverter</converter-class>
</converter>

com.coaccess.utilities.CustomDateTimeConverter.java:

public class CustomDateTimeConverter extends DateTimeConverter {

    /** Constructor. */
    public CustomDateTimeConverter() {
        super();

        // set the default timezone to the system time zone instead of GMT
        super.setTimeZone(TimeZone.getDefault());
        setPattern("MM/dd/yyyy");
    }
}

With this second method you remove the <f:convertDateTime> from the date fields completely and the usage of <f:convertDateTime> overrides the specified default (if you don’t remove the convertDateTime tag then the specified default won’t be used and the problem will persist). From http://www.ibm.com/developerworks/library/j-jsf3/.

Explanation

Searching for “JBoss 5 with JSF 2” results in a bunch of messages explaining that “it can’t be done,” or “it shouldn’t be done,” or some other nonsense like “just remove JSF from JBoss” which obviously will break any already existing web application and is not an option in a production environment. The following is the solution and allows a web app in JBoss 5.0.1GA to use JSF 2 while leaving the built in JSF 1.2 on JBoss alone. So I think this is what people are actually looking for when they search for “JSF 2 with JBoss 5.” Note: I haven’t tried getting this to work with “MyEclipse,” only plain old Eclipse.

  1. Add the following three things to web.xml
    <!-- JSF 2: this tells JBoss 5 to use the jsf jars included in the app -->
    <context-param>
       <param-name>org.jboss.jbossfaces.WAR_BUNDLES_JSF_IMPL</param-name>
       <param-value>true</param-value>
    </context-param>

    <!-- JSF 2: this needs to be included to avoid an error message -->
    <context-param>
       <param-name>com.sun.faces.injectionProvider</param-name>
       <param-value>org.jboss.web.jsf.integration.injection.JBossInjectionProvider</param-value>
    </context-param>

    <!-- JSF 2: use pages named .xhtml instead of .jsp. -->
    <context-param>
       <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
       <param-value>.xhtml</param-value>
    </context-param>
  2. Download the latest version of JBoss 6 (which I’ve heard you should upgrade to as soon as practical).
  3. Copy the following jars from JBoss 6 into the WEB-INFlib directory.
    jboss-6.0.0.20100911-M5commonlibjboss-mc-int-servlet.jar
    jboss-6.0.0.20100911-M5serverdefaultdeployersjsf.deployerMojarra-2.0jsf-libsjboss-faces.jar
    jboss-6.0.0.20100911-M5serverdefaultdeployersjsf.deployerMojarra-2.0jsf-libsjsf-api-2.0.2-FCS.jar
    jboss-6.0.0.20100911-M5serverdefaultdeployersjsf.deployerMojarra-2.0jsf-libsjsf-impl-2.0.2-FCS.jar
  4. Rejoice in JSF 2 goodness.

Notes

If you read the stuff you were copying and pasting then you’ll notice that .xhtml is used instead of the default .jsp. The additional information above should be everything necessary to get a basic example to work – the one at http://www.coreservlets.com/JSF-Tutorial/jsf2/#Getting-Started is the one I used.

Common Error Messages

You may run into these when trying to use JSF 2 on JBoss 5 without doing what’s listed above.

  • java.lang.ClassCastException: com.sun.faces.config.WebConfiguration cannot be cast to com.sun.faces.config.WebConfiguration

    • Make sure all entries exist in the web.xml. This means JBoss found both versions of JSF and doesn’t know which one to use. JBoss 5 has JSF 1.2 as part of it’s normal libs, so including JSF 2 with an app will cause problems unless we tell JBoss to only use the jars from our app.
  • java.lang.NoClassDefFoundError: org/jboss/mc/servlet/vdf/spi/VDFConnector

    • Make sure all of the specified jar files were copied and are included. JBoss is saying “what is this class VDFConnector? Never heard of it..
  • java.lang.NoClassDefFoundError: (anything)

    • Make sure all of the specified jar files were copied and are included.
  • JSF1029: The specified InjectionProvider implementation ‘org.jboss.web.jsf.integration.injection.JBossInjectionProvider’ does not implement the InjectionProvider interface.

    • Make sure all entries exist in the web.xml. I have no idea why we need to specify the exact thing it can’t find in order to make it work. Any clarification is encouraged.
  • java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory:

    • Try adding

      <listener>
               <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
      </listener>

      to the web.xml. This was contributed by Kley in the comments. Let me know if it works..

Credits

The WAR_BUNDLES_JSF_IMPL option is from Shivaji Byrapaneni at http://community.jboss.org/message/54085.
I can’t find the URL where I found the JBossInjectionProvider option.
The fact that the jboss-mc-int-servlet.jar is necessary is from http://community.jboss.org/thread/2656.
The rest is from me.

© 2012 Stinky Cheese