Category: JSF

JSF graphicImage from database

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.

Advertisements

Guice and JSF 2

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, JSR-303, and you

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.

JSF 2 Custom Converter

I ran into a very strange problem in my little Google App Engine application. I’m using JSF 2 as the presentation layer. I’m using Google’s low level api for accessing the data store and have written some little utilities to convert from my objects to Google’s Entity objects.

I thought I had the mapping working OK, but had only tried setting simple String properties on my data objects. I finally tried to map a simple association, where one object would have a list of keys of other objects. In my case I have Tables. Each table can be associated with zero or more Genres. So, my Table data object has a List of Keys for the genres that it is a part of, like this:

public class Table
        extends DataObjectAbstract
        implements Serializable
{
    @Persistent
    private List<Key> genres;

    // other private attributes here

    public List<Key> getGenres()
    {
        return genres;
    }

    public void setGenres( List<Key> genres )
    {
        this.genres = genres;
    }

    // other public getters and setters and other methods here
}

You can safely ignore DataObjectAbstract and the @Persistent annotation. They aren’t part of this blog post.

The strange behavior I was seeing was that when I would get the genre list from the data store, it would be a List<String> instead of the List<Key> I was expecting. After some debugging, I finally discovered that I was setting it as a List<String> because Strings are what I was getting from my JSF page, and thanks to Java’s type erasure with generics, my code didn’t know any better. So, the solution is a custom converter, which will allow me to pass the Keys to and from the browser.

Fortunately, in JSF 2, custom converters are even easier than they are in JSF 1.x. Here’s my simple converter class for the com.google.appengine.api.datastore.Key class. Making this even more simple is the fact that Google offers a KeyFactory that takes care of giving a URL safe representation of their Key object.

package jota.soc.ui.converter;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;

/**
 * Converter for Google Key.
 * @author Joel.Weight
 */
@FacesConverter( value="keyConverter" )
public class KeyConverter implements Converter {

    /**
     * converts the String representation of the key back to the Object
     */
    public Object getAsObject( FacesContext context, UIComponent component,
                               String value )
    {
        // will throw new IllegalArgumentException if it can't parse.
        return KeyFactory.stringToKey( value );
    }

    /**
     * converts the Key object into its String representation.
     */
    public String getAsString( FacesContext context, UIComponent component,
                               Object value )
    {
        if ( value instanceof Key )
        {
            return KeyFactory.keyToString( (Key)value );
        }
        else
        {
            throw new IllegalArgumentException( "Cannot convert non-key object in KeyConverter" );
        }
    }
}

With the @FacesConverter annotation, you don’t have to register the converter in faces-config or anything. You can simply reference it using the id.

Here’s the code that uses the converter.

<h:selectManyListbox id="genresBox" value="#{createTable.table.genres}">
    <f:converter converterId="keyConverter" />
    <f:selectItems value="#{createTable.genres}"
        var="item"
        itemValue="#{item.key}"
        itemLabel="#{item.name}" />
</h:selectManyListbox>

And just like that, I’m storing Keys in the data store instead of Strings.

JSF 2.0.2 and Google App Engine

I spent a couple hours today trying to get a JSF 2 based webapp up in app-engine.  Of course, it wasn’t as easy as simply following the instructions in

configuring jsf 2.0 to run on the google app engine using netbeans

I ran into the problem detailed here  ( JNDI problem in jsf 2.0 and google app engine ) right off the bat.  I tried to use his packaged jar, but app-engine kept giving me an exception that it couldn’t load the zip file. Perhaps it was corrupted when I downloaded it or something.

If you follow his link to the WebConfiguration.java file, you will see that he created a new WebConfiguration.java file within the same package as the existing one and copied the implementation, commenting out the offending code.  I decided to try a different approach. I’m sure there is nothing wrong with Josh’s approach, and if it weren’t for his blog and all the ground work he had already done in finding the offending code, I probably wouldn’t have even bothered going further with JSF 2 in app engine. In any case, here’s what I did.

I downloaded the JSF 2.0.2 source from here ( jsf 2.0.2 source ) and expanded it.  I then found the WebConfiguration.java file and decided to modify it.  Rather than comment out all the source, I added a new config enumeration value to the BooleanWebContextInitParameter enumerations as follows

// around line 1071 in the finished file, after the previously final enum value AllowTextChildren
EnableJNDI(
"com.sun.faces.enableJNDI",
true
);

Then, I check for the value of that parameter in private constructor, around line 113

        // add the isOptionEnabled call to this conditional statement
        if ( isOptionEnabled( BooleanWebContextInitParameter.EnableJNDI ) && canProcessJndiEntries()) {
            processJndiEntries(contextName);
        }

When that is done, simply compile, and you have a new jsf-api/build/lib/jsf-api.jar and jsf-ri/build/lib/jsf-impl.jar that you can use in your project. For my compile, I simply copied the build.properties.glassfish.orig to build.properties and set the jsf.build.home property to the directory in which the source was checked out.

Finally, put a new context-param in web.xml with the name com.sun.faces.enableJNDI and a value of false.

All I’ve got so far is the hello world, so we’ll see if I run into other difficulties as I use further functionality.

Sharing JSF 2 Composite Components

Let’s say you have created some awesome composite components in JSF 2 that you want to share between one webapp and another.  One option would be to simply copy all of the .xhtml files from one webapp to the other.  Yuck.  Then you have two versions of each file.  Changes in one are not reflected in the other, and what happens when you are up to 6 webapps that all want to share your awesome components?  That’s ugly.

A better solution is to jar them all up into a new component library.  Sounds complicated huh?  Not really.

Each of your composite components should be in a resources directory.  In order to redistribute those components, you simply add them to a jar under META-INF/resources, and then make sure that your META-INF directory also contains a faces-config.xml file.

The faces-config.xml file ensures that JSF scans the jars for components and annotated classes.  The following ant target, which I added to the build.xml file in a netbeans project automatically takes the resources directory, and creates an empty faces-config.xml file and plops them into a jar.  Now, you simply include that jar as a library in your new webapp.

    <target name="create-lib-jar">
        <property name="stage-dir" value="create-lib-jar-temp" />
        <property name="dist.dir" value="." />
        <property name="lib.jar" value="${dist.dir}/jsfLibrary.jar" />
        <mkdir dir="${stage-dir}" />

        <echo file="${stage-dir}/faces-config.xml" ><![CDATA[<?xml version='1.0' encoding='UTF-8'?>
<faces-config
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
    version="2.0">
</faces-config>]]></echo>

        <jar destfile="${lib.jar}">
            <metainf dir="${stage-dir}">
                <include name="faces-config.xml" />
            </metainf>

            <metainf dir="web" includes="resources/">
            </metainf>

        </jar>

        <delete dir="create-lib-jar-temp" />

    </target>

Think of the possibilities.  Now, you have a simple project in which to build your core, re-usable composite components, all running in their own little webapp, testable with junit for the java classes and selenium for the web portions.  Then, you package them up for use in all your webapps.  That’s awesome sauce.

This build target doesn’t get any java class files.  When I get to that part of my project, I’ll update it.

Make sure to modify the properties to fit your environment so it is pulling from the correct directories and all that jazz.

<target name=”create-lib-jar”>
<property name=”stage-dir” value=”create-lib-jar-temp” />
<property name=”dist.dir” value=”.” />
<mkdir dir=”${stage-dir}” /> 

<echo file=”${stage-dir}/faces-config.xml” ><![CDATA[<?xml version=’1.0′ encoding=’UTF-8′?>
<faces-config
xmlns=”http://java.sun.com/xml/ns/javaee&#8221;
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221;
xsi:schemaLocation=”http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd&#8221;
version=”2.0″>
</faces-config>]]></echo>

<jar destfile=”${dist.dir}/jsfLibrary.jar”>
<metainf dir=”${stage-dir}”>
<include name=”faces-config.xml” />
</metainf>

<metainf dir=”web” includes=”resources/”>
</metainf>

</jar>

<delete dir=”create-lib-jar-temp” />

</target>

Using ui:insert to include children

Let’s say you have a custom facelets component that wraps an h:selectOneListbox. As a part of using this component, you read the list of items that should be displayed in the list from a database table. Your bean reads the results of the database query and creates listItems, that are then passed back to the h:selectOneListbox, through your my:customListbox component. For instance:

            <my:customListbox
              fieldName="itemValue"
              entity="#{myBean}"
              items="#{myDatabaseBean.listItems}" />

In this example, the value of the h:selectOne would be set in myBean.setItemValue, and the list of selectItems would be returned from myDatabaseBean.getListItems.

Now, you decide that you want to provide some defaults for the lists that are in your UI, but not in the database. You could modify myDatabaseBean.getListItems to manually add a custom default selectItem. The value of the defaultItem could be null, or empty string, that way, when the list is displayed, if myBean.getItemValue returns null or empty string, the default value would be selected in the UI. Pretty slick, except for you have to write java in EVERY instance where you are creating your listItems from the database. Now, add in internationalization and your database bean now has to use the correct resource bundle to read the default value display string. That’s not real difficult, but it’s just more java code that has to be introduced everywhere you are creating those lists.

So, is there another way? Here’s what I did.

In my customListbox component I included a well placed, anonymous ui:insert. This magically made my composition include the children of my customListbox in place of the unnamed ui:insert. For instance, within customListbox.xhtml my h:selectOneListbox now looks like this:

    <h:selectOneListbox value="#{entity[fieldName]}">
      <ui:insert />
      <f:selectItems value="#{items}" />
    </h:selectOneListbox>

Then I can include multiple f:selectItem elements as a child of my:customListbox such as:

<my:customListbox
    fieldName="itemValue"
    entity="#{myBean}"
    items="#{myDatabaseBean.listItems}" >
    <f:selectItem itemValue="" itemLabel="#{bundle.defaultBlahValue}" />
</my:customListbox>

Now, I’ve been able to add a custom default value to my custom listbox with a single line in xhtml, and a single resource bundle value, and no java.