dev@javaserverfaces.java.net

RE: InjectionProviders

From: <jacob_at_hookom.net>
Date: Tue, 02 Jan 2007 13:55:22 -0500
It might be worthwhile to abstract this factory one step further and have a single meta-inf entry for all RI-based Factories:

/META-INF/services/com.sun.faces.spi.factories

com.sun.enterprise.InjectionManager:com.sun.faces.vendor.GlassFishInjection
some other type: some other implementation





  Hey All,

Thought I would throw this out to see if anyone would care to comment on
some ideas/work I've done on the InjectionProvide system in the RI.

Currenly, vendors can implement the InjectionProvider interface and explicitly
configure it via a context initialization parameter or system property.

The above system is fine, however, it's somewhat limiting if I want to add
InjectionProvider implementations for Tomcat6 and Jetty6.  We'd have to
document how to configure the provider for their container.  Ideally, it would
just work without any steps by the developer.

To that end, I have the following coded up in my local workspace:

Added a new Abstract class called DiscoverableInjectionProvider that implements
InjectionProvider and provides a static method:

   
/**
     * @param delegateClass the name of the delegate used by the
     *  <code>InjectionProvider</code> implementation.
     * @return returns <code>true</code> if the
     *  <code>InjectionProvider</code> instance
     *  is appropriate for the container its currently
     *  deployed within, otherwise return <code>false</code>
     */
    public static boolean isProviderAppropriate(String delegateClass)

This method would be called by the InjectionProviderFactory (see below) to determine
if this particular InjectionProvider could be used.  More on the 'delegateClass' argument
later.

Modifications to InjectionProviderFactory:

  * The factory algorithm will check the following,
     in order, to provide the appropriate provider
        - If explicitly configured, return that InjectionProvider
        - If no explicit configuration, check META-INF/services/com.sun.faces.spi.injectionprovider.
          The format of the entries within the 'com.sun.faces.spi.injectionprovider file is:
                    <InjectionProviderImplementation>:<DelegateClass>
           So an example for GlassFish would be:
                    com.sun.faces.vendor.GlassFishInjectionProvider:com.sun.enterprise.InjectionManager
           When processing, the factory will split the two, and pass the <DelegateClass> portion to
           DiscoverableInjectionProvider.isProviderAppropriate(String).  If it returns true, then we
           return this InjectionProvider. 
          NOTE:  Any InjectionProvider declared in the services file must extends DiscoverableInjectionProvider.
                       The appropriate messages would be logged if this was not the case
      - If no provider is found in the services configuration, check to see if the PostConstruct and PreDestroy
        annotations are present, if so, provide support for those two annotations *only*.
     - If no provider has been found at this point, no resource injection will be provided.


I've tested the above locally, and so far, it all seems to work.

The other part to this issue, is how to handle the build if we provide these
InjectionProvider implementations for other containers.  These providers
will obviously be dependent on container specific classes, so I see a two
options:

1.  Have a separate set of targets to build a jsf-ri-iprovider.jar that is checked
     into the workspace.  When the RI itself is built, then the classes contained
     in the jsf-ri-provider.jar would be included. 

2.  Update the dependencies.xml to download tomcat6, glassfish, and jetty
     so that the classes are always built. 

Number one so far seems like the best choice.  There are issues with choice 2
and the glassfish installation with regards to automation as there is a graphical
popup to accept the CDDL licence. 

Number 2 means a little more overhead in ensuring that that particular part
of the build doesn't break - so it would have to be a manual step done once
a week or so to ensure it's valid.

The other question I had - do we want to include the provider implementations
within the RI jar itself, or have it as a separate project of sorts where it has
a JAR (jsf-ri-iproviders.jar) that people can install separately.  This could
allow for more flexibility if the vendors happen to change their internal API.

I think this covers all of what I had in my notes.  Comments?