users@jersey.java.net

Re: [Jersey] Guice access to Jersey-created objects

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Mon, 17 Aug 2009 09:20:53 +0200

On Aug 14, 2009, at 10:44 PM, Richard Wallace wrote:
>
> But I'm not convinced that will solve your problem either. It sounds
> more like the WebApplication instance that is being created by Guice
> is not the one that is being used by Jersey. You said it's a Java SE
> app and so doesn't use any of the servlet stuff. But however you are
> kicking off Jersey, whether creating a GrizzlyContainer or something
> else, you'll need to be sure it uses the WebApplication instance Guice
> creates.
>

Yes, that could be it.

Craig, if you are using the low-level Grizzly support with Adapter and
ContainerFactory then it is not currently possible to obtain the
WebApplication instance that is utilized:

public final class ContainerFactory {

     ...

     public static <A> A createContainer(Class<A> type, ResourceConfig
resourceConfig,
             IoCComponentProviderFactory factory)
     throws ContainerException, IllegalArgumentException {
         WebApplication wa =
WebApplicationFactory.createWebApplication();

         // Reverse the order so that applications may override
         LinkedList<ContainerProvider> cps = new
LinkedList<ContainerProvider>();
         for (ContainerProvider cp :
ServiceFinder.find(ContainerProvider.class, true))
             cps.addFirst(cp);

         for (ContainerProvider<A> cp : cps) {
             A c = cp.createContainer(type, resourceConfig, wa);
             if (c != null) {
                 // Initiate the web application
                 if (!wa.isInitiated()) {
                     wa.initiate(resourceConfig, factory);
                 }

                 // Register a container listener
                 Object o = resourceConfig.getProperties().get(
                         ResourceConfig.PROPERTY_CONTAINER_NOTIFIER);
                 if (o instanceof ContainerNotifier &&
                         c instanceof ContainerListener) {
                     ContainerNotifier crf = (ContainerNotifier)o;
                     crf.addListener((ContainerListener)c);
                 }
                 return c;
             }
         }

         throw new IllegalArgumentException("No container provider
supports the type " + type);
     }


public class GrizzlyContainerProvider implements
ContainerProvider<Adapter> {

     public GrizzlyContainerProvider() {
         Class<?> c = Adapter.class;
     }

     public Adapter createContainer(Class<Adapter> type,
             ResourceConfig resourceConfig,
             WebApplication application) throws ContainerException {
         if (type != Adapter.class)
             return null;

         return new GrizzlyContainer(application);
     }
}


One possible solution is to create your own ContainerProvider that
reuses GrizzlyContainerProvider and returns an Adapter and the
WebApplication. Or create your own ContainerFactory

public class WebAppGrizzlyContainerProvider implements
ContainerProvider<MyType> {

     public MyType createContainer(Class<Adapter> type,
             ResourceConfig resourceConfig,
             WebApplication application) throws ContainerException {
         if (type != MyType.class)
             return null;

         // Reverse the order so that applications may override
         LinkedList<ContainerProvider> cps = new
LinkedList<ContainerProvider>();
         for (ContainerProvider cp :
ServiceFinder.find(ContainerProvider.class, true))
             cps.addFirst(cp);

         for (ContainerProvider<Adapter> cp : cps) {
                Adapter c = cp.createContainer(Adapter.class,
resourceConfig, wa);
                if (c != null) {
                  return new MyType(c, application);
                }
         }
     }
}

Or just fork the grizzly container code directly.

We could modify the containers so that they can be cast to a special
interface to get access to the WebApplication?

Paul.