Simple answer:
  * you bind Foo to FooImpl
  * FooImpl is bound in RequestScope
    - therefore, you can't inject FooImpl (or Foo) outside of Request Scope
  * you inject Foo into DataServiceProvider
  * you inject DataServiceProvider into ServiceImpl
  * you bind Service to ServiceImpl
  * you get an instance of Service outside of Scope

boom!

If you need an instance of Foo in DataServiceProvider, inject Provider<Foo>,
and don't call get() until you're in scope.

And traverse upwards as need be...

-Fred

On Tue, Feb 1, 2011 at 11:51 PM, Richard Maher <[email protected]> wrote:

> I have a service that takes a request scope object and a singleton. When I
> try to run the code below, I get the following error. How do I fix this?
>
> Exception in thread "main" com.google.inject.ProvisionException: Guice
> provision errors:
>
> 1) Error in custom provider, com.google.inject.OutOfScopeException: Cannot
> access
> Key[type=com.google.analytics.frontend.feed.impl.gami.GuiceTester$FooImpl,
> annotation=[none]] outside of a scoping block
>   at
> com.google.analytics.frontend.feed.impl.gami.GuiceTester$FooImpl.class(GuiceTester.java:30)
>   while locating
> com.google.analytics.frontend.feed.impl.gami.GuiceTester$FooImpl
>   while locating
> com.google.analytics.frontend.feed.impl.gami.GuiceTester$Foo
>     for field at
> com.google.analytics.frontend.feed.impl.gami.GuiceTester$DataServiceProvider.foo(GuiceTester.java:1)
>   while locating
> com.google.analytics.frontend.feed.impl.gami.GuiceTester$DataServiceProvider
>     for field at
> com.google.analytics.frontend.feed.impl.gami.GuiceTester$ServiceImpl.unscopedDataServiceProvider(GuiceTester.java:79)
>   while locating
> com.google.analytics.frontend.feed.impl.gami.GuiceTester$ServiceImpl
>   while locating
> com.google.analytics.frontend.feed.impl.gami.GuiceTester$Service
>
> 1 error
> at com.google.inject.internal.InjectorImpl$4.get(InjectorImpl.java:977)
> at
> com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1003)
> at
> com.google.analytics.frontend.feed.impl.gami.GuiceTester.main(GuiceTester.java:133)
> Caused by: com.google.inject.OutOfScopeException: Cannot access
> Key[type=com.google.analytics.frontend.feed.impl.gami.GuiceTester$FooImpl,
> annotation=[none]] outside of a scoping block
> at
> com.google.common.inject.SimpleScope.getScopedObjectMap(SimpleScope.java:110)
> at com.google.common.inject.SimpleScope.access$000(SimpleScope.java:48)
> at com.google.common.inject.SimpleScope$2.get(SimpleScope.java:94)
> at
> com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:40)
> at com.google.inject.internal.FactoryProxy.get(FactoryProxy.java:54)
> at
> com.google.inject.internal.SingleFieldInjector.inject(SingleFieldInjector.java:53)
> at
> com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:110)
> at
> com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:94)
> at
> com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:254)
> at
> com.google.inject.internal.SingleFieldInjector.inject(SingleFieldInjector.java:53)
> at
> com.google.inject.internal.MembersInjectorImpl.injectMembers(MembersInjectorImpl.java:110)
> at
> com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:94)
> at
> com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:254)
> at com.google.inject.internal.FactoryProxy.get(FactoryProxy.java:54)
> at com.google.inject.internal.InjectorImpl$4$1.call(InjectorImpl.java:968)
> at
> com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1014)
> at com.google.inject.internal.InjectorImpl$4.get(InjectorImpl.java:964)
> ... 2 more
>
> // Code:
>
> public class GuiceTester {
>   public interface DataService {
>
>   }
>
>   public interface Foo {
>   }
>
>   @RequestScoped
>   static class FooImpl implements Foo {
>   }
>
>   public interface Bar {
>   }
>
>   @Singleton
>   static class BarImpl implements Bar {
>   }
>
>   static class DataServiceImpl implements DataService {
>     private final Foo foo;
>     private final Bar bar;
>
>     @Inject
>     DataServiceImpl(Foo foo, Bar bar) {
>       this.foo = foo;
>       this.bar = bar;
>     }
>
>     @Override
>     public String toString() {
>       return "MarsDataService [foo=" + foo + ", bar=" + bar + "]";
>     }
>   }
>
>   public interface Service {
>     Response process(Request request);
>   }
>
>   static class Request {
>     private final Foo foo;
>
>     Request(Foo foo) {
>      this.foo = foo;
>     }
>
>     Foo getFoo() {
>       return foo;
>     }
>   }
>
>   static class Response {
>
>   }
>
>   static class ServiceImpl implements  Service {
>     @Inject @Named("serviceScope") SimpleScope scope;
>     @Inject DataServiceProvider unscopedDataServiceProvider;
>
>     @Override
>     public Response process(Request request) {
>       scope.enter();
>       try {
>         // explicitly seed some seed objects...
>         scope.seed(Key.get(Foo.class), request.getFoo());
>         Provider<DataService> dataServiceProvider =
>             scope.scope(Key.get(DataService.class),
> unscopedDataServiceProvider);
>         DataService dataService = dataServiceProvider.get();
>         System.out.println("DataService: " + dataService);
>       } finally {
>         scope.exit();
>       }
>       return null;
>     }
>   }
>
>   static class DataServiceProvider implements Provider<DataService> {
>     @Inject private Foo foo; // this is request scoped and seeded
>     @Inject private Bar bar; // this is a singleton
>
>     @Override
>     public DataService get() {
>       return new DataServiceImpl(foo, bar);
>     }
>
>   }
>
>   public static void main(String[] args) {
>     Injector injector =
>         Guice.createInjector(Stage.DEVELOPMENT, new AbstractModule() {
>           @Override
>           protected void configure() {
>             bind(Service.class).to(ServiceImpl.class);
>             bind(Foo.class).to(FooImpl.class);
>             bind(Bar.class).to(BarImpl.class);
>             bind(DataServiceProvider.class);
>
>             SimpleScope serviceScope = new SimpleScope();
>
>             // tell Guice about the scope
>             bindScope(RequestScoped.class, serviceScope);
>
>             // make our scope instance injectable
>             bind(SimpleScope.class)
>                 .annotatedWith(Names.named("serviceScope"))
>                 .toInstance(serviceScope);
>           }
>         });
>     Service service = injector.getInstance(Service.class);
>     Request request = new Request(new FooImpl());
>     service.process(request);
>   }
> }
>
> // End code
>
> Thanks,
>
> Richard
>
>
>  --
> You received this message because you are subscribed to the Google Groups
> "google-guice" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected]<google-guice%[email protected]>
> .
> For more options, visit this group at
> http://groups.google.com/group/google-guice?hl=en.
>

-- 
You received this message because you are subscribed to the Google Groups 
"google-guice" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-guice?hl=en.

Reply via email to