DigitalJoel

2010/09/12

JSF graphicImage from database

Filed under: development, facelets, java, JSF, JSF2 — digitaljoel @ 8:45 pm

I’ve seen some questions on the webtier mailing list about loading image resources from a database, but no real implementation suggestions.  I ended up needing to figure this out for work, and got permission to post the solution here.  It’s not 100% complete as it doesn’t allow for caching at the client or in the JSF layer, but it’s a starting point.  You won’t be able to take this solution and simply plop a jar in your project and make it go.  You’ll have to implement your own solution, but can base it on this information if it helps you.

In my case, our software manages Programs and Brands.  What those entities represent isn’t important, but know that each program can have a logo and custom css, and each Brand can have a logo.  I wanted to be able to use the regular JSF tags to output these images so the designers wouldn’t have to learn a new tag.  Something like this:


    <h:outputStylesheet library="program_#{user.programName}" name="css" />
    <h:graphicImage library="program_#{user.programName}" name="logo" />

The first step is to implement a custom ResourceHandler.  This would be super awesome if we could just extend ResourceHandlerWrapper like the JSF developers intended.  They built that class precisely for extension, unfortunately, the implementation has what I consider a fatal flaw.  JSF calls handleResourceRequest in order to create a resource when a resource request comes in.  The resource is a representation of your image or css.  In handleResourceRequest, the ResourceHandlerWrapper calls in to the wrapped instance’s handleResourceRequest, and the ResourceHandlerImpl  handleResource calls its own createResource method.

Update: It looks like they have fixed the ResourceHandlerImpl in 2.0.3 so that it now delegates to the configured resource handler for createResource.  This is great in that it means you should be able to now extend ResourceHandlerWrapper instead of ResourceHandlerImpl and get the correct behavior.  You should view this thread http://forums.java.net/jive/thread.jspa?threadID=153490&tstart=0 for more info.

So, if my extension of ResourceHandlerWrapper implements its own createResource method in order to create my own custom resources, then I must also implement my own handleResourceRequest which, if you look at the linked javadoc would be really easy to mess up all resource handling in your application.

The point of all this rambling?  I had to do something I’m not proud of.  I extended ResourceHandlerImpl, which is a non-published API, but it was that or implement my own handleResourceRequest, which I really didn’t want to do.  So, here’s the source of my ResourceHandler.


package yourpackage.jsf;

import com.sun.faces.application.resource.ResourceHandlerImpl;
import javax.faces.application.Resource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *
 * @author Joel.Weight
 */
public class DelegatingResourceHandler extends ResourceHandlerImpl
{
    private ResourceHelper[] helpers = new ResourceHelper[] {
    new ProgramResourceHelper()
    , new BrandResourceHelper()
    };

    private static Log log = LogFactory.getLog( DelegatingResourceHandler.class );

    @Override
    public Resource createResource( String resourceName, String libraryName )
    {
        ResourceHelper helper = getHelper( libraryName );
        if ( helper != null )
        {
            return helper.createResource( resourceName, libraryName );
        }
        // otherwise delegate to the default implementation.
        if ( log.isDebugEnabled() )
        {
            log.debug( "Delegating resource creation to default implementation. name: " + resourceName +
            " and library: " + libraryName );
        }
        return super.createResource( resourceName, libraryName, null );
    }

    @Override
    public boolean libraryExists( String libraryName )
    {
        ResourceHelper helper = getHelper( libraryName );
        if ( helper != null )
        {
            return true;
        }
        return super.libraryExists( libraryName );
    }

    /**
    * Get the helper that handles a given library.
    * @param libraryName
    * @return
    */
    private ResourceHelper getHelper( String libraryName )
    {
        for ( ResourceHelper helper : helpers )
        {
            if ( helper.handlesLibrary( libraryName ))
            {
                return helper;
            }
        }
        return null;
    }
}

Alright, what’s going on here.  First, an array of ResourceHelpers.  Since I want to load images from different entities, I have a helper for each one, which will be responsible for instantiating the resource for the given entity.

Next, the createResource method asks each helper if it handles a given library.  Each helper has a prefix that signals to it that it should handle a given resource request.  For instance, program_ and brand_ are the prefixes I have.  If none of the helpers handle the library, then it delegates to the default handler functionality.

Finally libraryExists asks each helper if it handles the given library.  If none of them, then it delegates to the default handler functionality.

Next is the helper implementation.  I created an abstract class so the Program and Brand helpers could share common functionality.  Here it is.


package yourpackage.jsf;

import javax.faces.application.Resource;
import javax.faces.context.FacesContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *
 * @author Joel.Weight
 */
public abstract class ResourceHelper
{

    protected String prefix;

    private static Log log = LogFactory.getLog( ProgramResourceHelper.class );

    public ResourceHelper( String prefix )
    {
        this.prefix = prefix;
    }

    /**
     * Create a resource with the given name for the given library
     * @param resourceName The resource name, as passed in the JSF tag
     * @param libraryName The library name, as passed in the JSF tag
     * @return The resource, or null if not found.
     */
    public abstract Resource createResource( String resourceName, String libraryName );

    /**
     * remove the prefix from a resourceName
     * @param name resourceName
     * @return the resource name without the prefix, or the original string if it doesn't start with the prefix.
     */
    public String stripPrefix( String name )
    {
        if ( name != null && name.startsWith( prefix ))
        {
            return name.substring( prefix.length() );
        }
        return name;
    }

    /**
     * Test whether this helper handles the given library name.
     * @return true if this helper handles the library, false otherwise.
     */
    public boolean handlesLibrary( String libraryName )
    {
        boolean result = ( libraryName != null
                                && libraryName.toLowerCase().startsWith( prefix )
                                && libraryName.length() > prefix.length());
        if ( log.isDebugEnabled() )
        {
            log.debug( String.format( "Helper with prefix %s handles library %s : %s", prefix, libraryName, result ));
        }
        return result;
    }

    /**
     * Gets a bean from the faces context.
     * @param name name of the bean to get
     * @return bean instance as returned from faces context.
     */
    public Object getBeanFromFacesContext( String name )
    {
        FacesContext context = FacesContext.getCurrentInstance();
        return context.getApplication().getELResolver().getValue( context.getELContext(), null, name );
    }
}

This is pretty simple.  It takes care of a lot of the prefix handling stuff.  The handlesLibrary method is the biggest shared functionality.  It looks at the prefix and determines if the library passed in the graphicImage or outputStylesheet tag should be handled by this helper.

Here is an implementation of the abstract class.  This is the one for Brand.


package yourpackage.jsf;

import awp.data.BrandService;
import awp.view.Brand;
import javax.faces.application.Resource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * ResourceHelper for getting images associated with a Brand.
 * @author Joel.Weight
 */
public class BrandResourceHelper extends ResourceHelper
{

    private BrandService brandService;

    private static Log log = LogFactory.getLog( BrandResourceHelper.class );

    public BrandResourceHelper()
    {
        super( "brand_" );
    }

    @Override
    public Resource createResource( String resourceName, String libraryName )
    {
        Brand brand = getBrandByLibraryName( libraryName );
        if ( brand != null )
        {
            return new BrandResource( resourceName, libraryName, brand );
        }
        return null;
    }

    private Brand getBrandByLibraryName( String libraryName )
    {
        Brand brand = null;
        String brandName = stripPrefix( libraryName );
        if ( brandName != null && brandName.length() > 0 )
        {
            brand = getBrandService().findBrandByName( brandName );
        }
        return brand;
    }

    private BrandService getBrandService()
    {
        if ( brandService == null )
        {
            brandService = (BrandService)getBeanFromFacesContext( "brandService" );
        }
        return brandService;
    }
}

As with the others, it’s quite simple, and the Program implementation looks very similar.  The only thing we really have to implement here is the constructor which sets up the prefix, and the createResource method.  The others are all helper methods.  createResource finds our entity in order to get the image from it.  Your implementation could query for just the image, or do whatever you want here.

Next up is our custom resource implementation.  This one is a little longer because we are extending a fair amount of the functionality in Resource


package yourpackage.jsf;

import yourpackage.DataObject;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.faces.application.Resource;
import javax.faces.application.ResourceHandler;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * base representation of a database backed resource.
 */
public abstract class DataObjectResource<T extends DataObject> extends Resource
{
    protected String name;
    protected String libraryName;
    protected T dataObject;

    private static Log log = LogFactory.getLog( DataObjectResource.class );

    // HTTP Date format required by the HTTP/1.1 RFC
    private static final String LAST_MODIFIED_PATTERN = "EEE, dd MMM yyyy HH:mm:ss zzz";

    public DataObjectResource( String name, String libraryName, T object )
    {
        this.name = name;
        this.libraryName = libraryName;
        this.dataObject = object;
        if ( log.isTraceEnabled() )
        {
            log.trace( "Created new DataObjectResource: libraryName: " + libraryName + " name: " + name );
        }
    }

    /**
    * Get the input stream for this resource.
    * @return
    * @throws IOException
    */
    @Override
    public abstract InputStream getInputStream() throws IOException;

    @Override
    public Map<String, String> getResponseHeaders()
    {
        Map<String, String> result = new HashMap<String, String>( 6, 1.0f );
        SimpleDateFormat format = new SimpleDateFormat( LAST_MODIFIED_PATTERN );
        // make it modified so they always request the whole resource.
        // TODO: make this smarter when going into production.
        result.put( "Last-Modified", format.format( new Date()));
        return result;
    }

    @Override
    public String getRequestPath()
    {
        StringBuilder buf = new StringBuilder(
        FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath() );
        buf.append( ResourceHandler.RESOURCE_IDENTIFIER );
        buf.append( "/" ).append( name ).append( ".faces?ln=" ).append( libraryName );
        if ( log.isDebugEnabled() )
        {
            log.debug( "Request path for program resource " + this.toString() + " : '" + buf.toString() + "'" );
        }
        return buf.toString();
    }

    @Override
    public URL getURL()
    {
        ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
        StringBuilder buf = new StringBuilder( context.getRequestScheme() );
        buf.append( context.getRequestServerName() );
        if ( context.getRequestServerPort() != 80 && context.getRequestServerPort() != 443 )
        {
            buf.append( ":" ).append( context.getRequestServerPort());
        }
        buf.append( getRequestPath());
        URL url = null;
        try
        {
            url = new URL( buf.toString());
            if ( log.isDebugEnabled() )
            {
                log.debug( "Created new URL " + buf.toString() + " for ProgramResource " + this.toString() );
            }
        }
        catch( java.net.MalformedURLException e )
        {
            log.error( "Unable to create URL for ProgramResource " + this.toString(), e);
        }
        return url;
    }

    @Override
    public boolean userAgentNeedsUpdate( FacesContext fc )
    {
        // TODO: always updates the user agent.  fix this to allow for caching.
        return true;
    }

    @Override
    public String toString()
    {
        return String.format( "%s { name=%s libraryName=%s }"
        , this.getClass().getName()
        , name
        , libraryName );
    }
}

This class is pretty dumb, and needs the most help to make it usable in a production system.  It provides default implementations for all of the methods of the Resource, except the getInputStream method.  The good news is that when I get time to come back to this class, it’ll be smarter for every implementation of this abstract class.

Now, to a concrete implementation of our custom Resource class.  This time we’ll look at ProgramResource since it handles css and an image.  I also have an implementation for BrandResource.


package yourpackage.jsf;

import yourpackage.Program;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * JSF Resource implementation used to get information from a Program in the database.
 */
public class ProgramResource extends DataObjectResource<Program>
{
    /**
    * Use this resource name in JSF to get the program logo.
    */
    public static final String LOGO_RESOURCE = "logo";

    /**
    * Use this resource name in JSF to get the program css.
    */
    public static final String CSS_RESOURCE = "css";

    private static Log log = LogFactory.getLog( ProgramResource.class );

    public ProgramResource( String name, String libraryName, Program program )
    {
        super( name, libraryName, program );
    }

    @Override
    public InputStream getInputStream() throws IOException
    {
        if ( LOGO_RESOURCE.equals( this.name ))
        {
            return new ByteArrayInputStream( dataObject.getLogo() );
        }
        else if ( CSS_RESOURCE.equals( this.name ))
        {
            return new ByteArrayInputStream( dataObject.getCss().getBytes());
        }
        else
        {
            if ( log.isWarnEnabled() )
            {
                log.warn( "Attempted to get input stream for ProgramResource, but no correct name specified. " +
                this.toString() );
            }
            return null;
        }
    }
}

First, notice the final static Strings that identify logo and css.  Those are the names of the resources you will use in the graphicImage and outputStylesheet tags.  They tell me where to get the data from for the getInputStream method.  The implementation of getInputStream is quite simple.  We just look at the name of the resource being requested, and use that as a key to figure out which field of our DataObject.

The last part of this puzzle is to tell JSF to use our DelegatingResourceHandler that we implemented at the start.  This is done with the following tag in your faces-config.xml file.  It should be within the application tag.


<resource-handler>yourpackage.jsf.DelegatingResourceHandler</resource-handler>

With all of this in place, I can show a different image in the same place in my application depending on the current context, and pull that image from the database.  For instance, if one user is in Program A, and another is in Program B, I simply use the user’s context to give the program to the graphicImage tag, and the outputStylesheet tag, and I have different styling and images for each of those users, without changing anything in my xhtml.

As I said before, this implementation is far from perfect.  If you attempt to reference a resource library and the helper can’t find it in the database then you will have a problem.  Also if you attempt to reference a resource name that doesn’t tie in to one of your identifiers in your Resource implementation, then you are toast.  Finally, there is no caching currently, so every request will load the image or css from the database.  That’s ugly.  Perhaps when I get back to this code in my current project, I’ll update the source in this blog post.  In the meantime, it ought to be a decent starting point for anyone looking to solve the same problem.

2010/05/01

Guice and JSF 2

Filed under: java, JSF, JSF2 — Tags: , , — digitaljoel @ 8:38 pm

As I’m sure you can tell from previous entries, I’ve been playing with JSF 2 in Google App Engine.  I decided to give Google’s Guice a try for dependency injection instead of Spring.  Why?  This is really just a learning app and why not try something new.

So how do you get Guice to play nicely with JSF?  One solution I saw online was to write a custom ELResolver for JSF that will do the injection.  I found this resource http://snippets.dzone.com/posts/show/7171 that had a full ELResolver implementation.  I had to modify it slightly to get it to work.  Namely, I had to move the Guice Injector creation out of getValue and into a private static variable.  I suspect I could make it not static, but I never gave it a try.  Here’s the source just in case that link dies at some point.  Again, I take no credit for this code other than the small modification mentioned.

/**
 * Bulk of the code taken from
 * http://snippets.dzone.com/posts/show/7171
 **/
package jota.soc.guice;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.servlet.ServletModule;
import java.beans.FeatureDescriptor;
import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.el.ELContext;
import javax.el.ELResolver;

/**
 */
public class GuiceResolver extends ELResolver
{

    Injector injector = Guice.createInjector(
            new ServletModule(),
            new SocGuiceModule() );

    //We only need to see the currently processed Objects in our Thread, that
    //prevents multithread issues without synchronization
    private static ThreadLocal currentlyProcessedThreadLocal = new ThreadLocal()
    {
        @Override
        protected Object initialValue()
        {
            return new LinkedList();
        }
    };

    //Im not sure if the synchronized lists seriously slow down the whole EL
    //resolving process
    private static List<WeakReference> alreadyInjectedObjects = Collections.
            synchronizedList( new LinkedList() );

        @Override
    public Object getValue( ELContext context, Object base, Object property )
    {

        //if the list of currently processed property objects doesnt exist for this
        //thread, create it
        List<Object> currentlyProcessedPropertyObjects = (List<Object>) currentlyProcessedThreadLocal.
                get();

        //Handle only root inquiries, we wont handle property resolving
        if ( base != null )
        {
            return null;
        }

        //checking if this property is currently processed, if so ignore it -> prevent
        //endless loop
        if ( checkIfObjectIsContained( property,
                currentlyProcessedPropertyObjects ) )
        {
            return null;
        }

        //add the to-be-resolved object to the currently processed list
        currentlyProcessedPropertyObjects.add( property );

        //now we can savely invoke the getValue() Method of the composite EL
        //resolver, we wont process it again
        Object resolvedObj = context.getELResolver().getValue( context, base,
                property );

        //ok, we got our result, remove the object from the currently processed list
        removeObject( property, currentlyProcessedPropertyObjects );

        if ( resolvedObj == null )
        {
            return null;
        }

        //ok we got an object
        context.setPropertyResolved( true );

        //check if the object was already injected
        if ( !checkIfObjectIsContainedWeak( resolvedObj, alreadyInjectedObjects ) )
        {
            injector.injectMembers( resolvedObj );
            //prevent a second injection by adding it as weakreference to our list
            alreadyInjectedObjects.add( new WeakReference( resolvedObj ) );
        }

        return resolvedObj;
    }

    /**
     * This method will search for an object in a Weak List. If there are any
     * WeakReferences on the way that were removed by the garbage collection
     * we will remove them from this list
     * @param object
     * @param list
     * @return
     */
    private boolean checkIfObjectIsContainedWeak( Object object,
                                                  List<WeakReference> list )
    {
        for ( int i = 0; i < list.size(); i++ )
        {
            WeakReference curReference = list.get( i );
            Object curObject = curReference.get();
            if ( curObject == null )
            {
                //ok, there is are slight chance that could go wrong, if you
                //have to prevent a double injection by all means, you might
                //want to add a synchronized block here
                list.remove( i );
                i--;
            }
            else
            {
                if ( curObject == object )
                {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * checks if an object is contained in a collection (really the same object '==' not equals)
     * @param object
     * @param collection
     * @return
     */
    private boolean checkIfObjectIsContained( Object object,
                                              Collection collection )
    {
        for ( Object curObject : collection )
        {
            if ( object == curObject )
            {
                return true;
            }
        }
        return false;
    }

    /**
     * removes an object from a list. really removes the given instance, not an other
     * object that fits equals
     * @param object
     * @param list
     */
    private void removeObject( Object object, List list )
    {
        for ( int i = 0; i < list.size(); i++ )
        {
            if ( list.get( i ) == object )
            {
                list.remove( i );
            }
        }
    }

    @Override
    public Class<?> getType( ELContext context, Object base, Object property )
    {
        return null;
    }

    @Override
    public void setValue( ELContext context, Object base, Object property,
                          Object value )
    {
    }

    @Override
    public boolean isReadOnly( ELContext context, Object base, Object property )
    {
        return false;
    }

    @Override
    public Iterator<FeatureDescriptor> getFeatureDescriptors( ELContext context,
                                                              Object base )
    {
        return null;
    }

    @Override
    public Class<?> getCommonPropertyType( ELContext context, Object base )
    {
        return null;
    }
}

That sure looks like a lot of code to me. I know Spring also provides a custom ELResolver for dependency injection. I found two links talking about resource injection here and here and thought I would try writing my own resource injector. Here’s how it ended up:

package jota.soc.guice;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.servlet.ServletModule;

import com.sun.faces.spi.InjectionProvider;
import com.sun.faces.spi.InjectionProviderException;
import com.sun.faces.vendor.WebContainerInjectionProvider;

/**
 * JSF injection provider for Guice.
 * @author Joel Weight
 */
public class GuiceInjectionProvider implements InjectionProvider
{
    public GuiceInjectionProvider()
    {
        System.out.println( "creating guice injection provider" );
    }

    /**
     * default injector provided by the web container.
     */
    private static final WebContainerInjectionProvider con =
                                                       new WebContainerInjectionProvider();

    /**
     * Custom guice injector that will load our modules.
     */
    private static final Injector injector = Guice.createInjector(
            new ServletModule(),
            new SocGuiceModule() );

    @Override
    public void inject( Object managedBean ) throws InjectionProviderException
    {
        // allow the default injector to inject the bean.
        con.inject( managedBean );
        // then inject with the google injector.
        injector.injectMembers( managedBean );
    }

    @Override
    public void invokePostConstruct( Object managedBean )
            throws InjectionProviderException
    {
        // don't do anything here for guice, just let the default do its thing
        con.invokePostConstruct( managedBean );
    }

    @Override
    public void invokePreDestroy( Object managedBean ) throws
            InjectionProviderException
    {
        con.invokePreDestroy( managedBean );
    }
}

It’s a very simple implementation. It delegates everything to the default container InjectionProvider, and then adds a touch of Guice. I then added this to web.xml:

    <context-param>
        <param-name>com.sun.faces.injectionProvider</param-name>
        <param-value>jota.soc.guice.GuiceInjectionProvider</param-value>
    </context-param>

And all my guice injections are occurring as expected. I am no longer using the custom ELResolver implementation. Obviously it’s not a general solution since I am instantiating my guice modules right in the provider rather than configuring it somehow, but it was enough for me right now.

If I run into any problems with this solution I’ll let you know, otherwise I would love to hear from any gurus as to how this could be problematic.

JSF 2 Ajax Submission Exceptions

Filed under: java, JSF2 — Tags: , — digitaljoel @ 7:52 pm

Tonight I was messing around with my pet project.  I have a composite component that I am trying to use in three different places in a page.  I am passing an action into the component, and that action is called via ajax on a command button.  In the first instance on the page, that action was working just fine.  In the second and third it was failing with a strange error message in a javascript popup.

serverError: class javax.faces.el.EvaluationException
blah blah blah with my source file followed by
Property 'myAction' not found on type MyType

MyType is the bean, and myAction is the action method I was attempting to call from the composite component.  I checked, and double checked and triple checked that everything was spelled correctly and everything.  The autocomplete in Netbeans was even showing that the action method was there.  I was especially surprised that it would work in one instance on the page, but not in the others, especially since the usage was identical other than the action method.

I have a co-worker who’s favorite saying is “Read the Error, Fix the Error” and in 99% of the cases, it works great, but not in this case.

The problem ended up being that some code in my action was causing a runtime exception that I wasn’t catching.  Once I resolved that, the error went away.  The reason it took me so long to figure that out is because neither the server log, nor the javascript popup gave me any clue as to the real cause of the error.

So, if you are seeing this strange error and KNOW that your action is defined correctly, set a break point in the action, or add some trace level logging so you can figure out what’s going on much faster than I did.

2010/04/12

JSF 2, JSR-303, and you

Filed under: development, java, JSF, JSF2 — Tags: , — digitaljoel @ 9:21 pm

In JSF 2, they added some nifty stuff.  One of the items they added was that JSF will seamlessly validate input values using a JSR-303 implementation if one is available.  “That’s nifty!” you say, “But how do I get an implementation of JSR-303 into my webapp?”

The reference implementation of JSR-303 is in hibernate validator version 4.  What if you don’t want to use hibernate?  That’s fine, because the validator project stands alone.  You don’t need to use any other parts of hibernate if you don’t want to.  Here’s what you should put in your maven pom in order to get hibernate 4 validators.

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>4.0.2.GA</version>
        </dependency>

Now you should be able to add JSR-303 validators to your project. Something like this should do:

    @NotNull
    @Size(min=3, max=10)
    private String username;

Now, when you tie an input control to that field in the bean, the value will be validated with the NotNull and Size constraints.

Obviously, the next thought is, “Awesome, now I can easily do multi-field constraints.”  For instance, you have a New Password form. You want the user to enter the password, and then to confirm the password. The simple answer is to write a validator that checks that the values of the two fields are equal and place the constraint on the Type, not on the Field. Something like the FieldMatch validator in the answer to this question on stackoverflow would be perfect.

So you implement the FieldMatch validator, and place it on your type. You then deploy your fancy JSF application and test the validator. Strangely your validator is never run. After reading more closely, you discover that JSF does “Field Level” validation using JSR-303 validators. Well, that should be easily enough overcome, right?

Next, you add an f:event tag to the page containing the bean to be validated. The event is preValidate, and you call a method on your bean containing the values. The method you call runs the validator manually. Perfect, right? More testing reveals that the your validator returns true every time, and even more than that, the values it’s testing are both null (which is why they are also equal).

Alright, let’s figure out what’s really going on.

After a half day of reading and testing, you finally go back to JSF basics and remember the JSF lifecycle. Alright, the phases are:

  1. Restore View
  2. Apply Request Values
  3. Process Validations
  4. Update Model Values
  5. Invoke Application
  6. Render Response

Notice that process validations comes before update model values. Well, no wonder putting the type constraint on the bean wasn’t validating the values that were set in the input controls. The values from the controls are validated before they are set on the bean. That explains why JSF 2 only does field level validation. They can take those validators, and apply them to the values that are set on the input controls before they are set in the bean.

So, what’s the answer to this problem? I haven’t decided yet. In this particular case, there are already JSF validators available for just this kind of validation, but what about the general case of type level validators. If I figure anything out, I’ll let you know. If you have any great ideas, chime in on the comments.

Blog at WordPress.com.