Thursday, December 13, 2012

Setting JSF ProjectStage with JNDI

One nice feature of JSF2 is the ProjectStage setting.  It lets the JSF implementation and the application developer optimize and customize behavior based on whether JSF is running in Development, Production, SystemTest, or UnitTest.  The usual way to tell JSF about which ProjectStage to use is through a context param in web.xml.
<context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
</context-param>
But you would rather not muck with web.xml for something like this.  It's much cleaner to define your ProjectStage based on what kind of server environment you are running.  In other words, wouldn't it be nice if JSF could know whether your server is running in Development, Test, Production, etc?  Then you wouldn't need to change your application at all.

A little-known but handy feature of JSF2 is the ability to use JNDI to set the JSF ProjectStage.  Here is how you do that in JBoss AS7.

First, add a resource reference in web.xml.
<resource-ref>
   <res-ref-name>jsf/ProjectStage</res-ref-name>
   <res-type>java.lang.String</res-type>
</resource-ref>
Then, create a jboss-web.xml file and place it beside web.xml in your WEB-INF directory. The file should bind the resource reference to JNDI like this:
<?xml version="1.0" encoding="ISO-8859-1"?>
<jboss-web>
    <resource-ref>
        <res-ref-name>jsf/ProjectStage</res-ref-name>
        <res-type>java.lang.String</res-type>
        <jndi-name>java:/env/jsf/ProjectStage</jndi-name>
    </resource-ref>
</jboss-web> 
Next, add the JNDI value to JBoss AS7 in the naming subsystem of your configuration file, such as standalone.xml:
      <subsystem xmlns="urn:jboss:domain:naming:1.1">
            <bindings>
                <simple name="java:/env/jsf/ProjectStage" value="Development"/>
            </bindings>
        </subsystem>

You can also add the JNDI value using CLI:
/subsystem=naming/binding=java\:\/env\/jsf\/ProjectStage/:add(binding-type=simple,value=Development,class=java.lang.String)
But I like to use CLI GUI for this because it automatically handles the escape characters:

Now we are done, but you might also want to change the value of ProjectStage on your server. Again, you can do that in XML or you can use CLI: 
/subsystem=naming/binding=java\:\/env\/jsf\/ProjectStage/:write-attribute(name=value,value=UnitTest)

Monday, November 26, 2012

Multi-JSF is here! Use any JSF in JBoss AS

Multi-JSF is a JBoss AS feature that I've wanted to implement for a very, very long time.  Basically, it allows you to use any JSF implementation as if it were the impl that ships with JBoss AS.  This works with almost any version of MyFaces or Mojarra.  You can even install multiple JSF implementations and tell each app which one to use.

Until now, if you wanted to use a different JSF version, you could hack AS7.  But this only worked for Mojarra implementations.  If you wanted to use MyFaces, you had to resort to bundling JSF with your web app and setting WAR_BUNDLES_JSF_IMPL in web.xml.

Both methods had potential integration problems if you wanted to use JEE5 features such as @EJB , or JEE6 features like CDI and bean validation.  What's worse is that if you wanted to use more than one JSF version you would end up bundling JSF with every WAR.

In short, it was messy and it didn't always work.  Plus, WAR_BUNDLES_JSF_IMPL isn't even officially supported.

Multi-JSF is now in the latest nightly build of 7.2.0-Alpha1.  You can get all the details on how to use it at  https://community.jboss.org/wiki/DesignOfAS7Multi-JSFFeature.

I hope you'll try it out and provide some feedback before AS7.2 goes final.

So long and thanks for all the fish,

Stan