users@jersey.java.net

Re: [Jersey] Simplifying Jersey life-cycle and IoC integration

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Mon, 27 Oct 2008 12:33:46 +0100

On Oct 23, 2008, at 12:15 PM, Paul Sandoz wrote:

> Hi,
>
> It is clear that the integration of IoC frameworks is more
> complicated that it should be, especially when the Jersey life-cycle
> annotations need to sync up with the IoC life-cycles.
>
> I propose the following simplifications:
>
> 1) Jersey should get out of the way when an IoC integrates such that
> Jersey always defers the IoC life-cycle
> mechanisms of the IoC. The Jersey specific life-cycle
> annotations should only be used when an IoC such as
> Spring, Guice or WebBeans is not integrated. Of course this does
> not mean that someone could write their
> own special IoC that re-used Jersey's life-cycle support (e.g.
> for proxies of components) or an IoC integration
> could provide some support for transitioning to the IoC.
>
> 2) Jersey should never defer to an IoC (if present) for the
> instantiation of internal Jersey components.
>
> 3) Unify ResourceProvider/ResourceProviderFactory with
> ComponentProvider and clearly differentiate
> between Jersey and IoC component providers.
>

1 and 3 are done. End users using Jersey or Spring should require no
additional changes, unless overriding of the default Jersey life-cycle
is configured. The property is now called:

     /**
      * If set the default resource component provider factory for the
      * life-cycle of resource classes.
      * <p>
      * The type of this property must be a Java class that
implementations
      * {_at_link
com.sun.jersey.server.spi.component.ResourceComponentProviderFactory}.
      * <p>
      * If not set the default resource component provider factory
will be the
      * per-request resource component provider factory.
      */
     public static final String
PROPERTY_DEFAULT_RESOURCE_COMPONENT_PROVIDER_FACTORY_CLASS
             =
"com
.sun
.jersey.config.property.DefaultResourceComponentProviderFactoryClass";


For those using the previous integration mechanism i hope this new
approach will be an improvement. It should be much easier to integrate
Guice or WebBeans. I plan to JavaDoc all the new interfaces/classes.

I have tried to capture all the existing functionality that i am aware
that developers have utilized:

1) Components managed by the IoC framework. Jersey will perform
injection.

2) Components instantiated by the IoC framework, but managed by
Jersey. The Jersey-Spring Autowire
     feature does this.

3) Components instantiated and managed by Jersey but the components
are proxied. This enables one to use
     constructors with injected parameters while still creating a
proxy interface. Ryan, IIRC you have this general
     proxy requirement?

See here for the Spring implementation.

https://jersey.dev.java.net/source/browse/*checkout*/jersey/trunk/jersey/contribs/spring/src/main/java/com/sun/jersey/spi/spring/container/servlet/SpringComponentProviderFactory.java

An example of proxies is presented in the following test:

https://jersey.dev.java.net/source/browse/*checkout*/jersey/trunk/jersey/jersey-tests/src/test/java/com/sun/jersey/impl/resource/MethodIAnnotationnheritenceTest.java

If any one has a try with all this please give feedback on how it goes,
Paul.

> The proposed interfaces for 3) are at the end of the email. There
> are specifics to IoC integration that Jersey needs to know if it has
> to perform injection of Jersey specific artifacts (if the IoC does
> not support this). The interface IoCComponentProvider represents
> those specifics.
>
> The Jersey life-cycle annotations will declare specific
> ComponentProvider classes.
>
> @Target({ElementType.TYPE})
> @Retention(RetentionPolicy.RUNTIME)
> @Documented
> @ResourceProvider(PerRequestComponentProvider.class)
> public @interface PerRequest {}
>
> This should also make the integration with an IoC a little more
> efficient since validation can be performed once by the
> ComponentProvider and not each and every time an instance is
> requested.
>
> Paul.
>
> /**
> * A factory for obtaining component providers
> */
> interface ComponentProviderFactory<C extends ComponentProvider> {
>
> /**
> * Get the component provider for a class.
> *
> * @param c the class
> * @return the component provider for the class
> */
> C getComponentProvider(Class c);
>
> /**
> * Get the component provider for a class.
> *
> * @param cc the component context to obtain annotations and
> * annotated object (if present).
> * @param c the class
> * @return the component provider for the class
> */
> C getComponentProvider(ComponentContext cc, Class c);
> }
>
>
> /**
> * Provide instances of a component.
> *
> */
> interface ComponentProvider {
> /**
> * Get the instance.
> *
> * @return the instance.
> */
> Object getInstance();
> }
>
> /**
> * An IoC-specific factory for obtaining IoC-specific component
> providers.
> *
> */
> interface IoCComponentProviderFactory extends
> ComponentProviderFactory<IoCComponentProvider> {
> }
>
>
> /**
> * Provide instances of a IoC-specfic component.
> *
> */
> interface IoCComponentProvider extends ComponentProvider {
> /**
> * Get the scope.
> * <p>
> * The Scope is required so that Jersey can correctly inject on
> an instance
> * returned from an application specfic component provider.
> *
> * @return the scope
> */
> Scope getScope();
>
> /**
> * Get the injectable instance that Jersey can perform field and
> method
> * setter injection on.
> *
> * @param o the instance returned from getInstance.
> * @return the injectable instance. May be the same as o. If null
> * then Jersey will perform no injection.
> */
> Object getInjectableInstance(Object o);
> }
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>