Improve OutOfScopeException so that it tells you which key it was trying to
get.
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=62699406
diff --git a/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java b/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java
index a439dba..5249fac 100644
--- a/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java
+++ b/extensions/servlet/src/com/google/inject/servlet/GuiceFilter.java
@@ -19,7 +19,9 @@
 import com.google.common.base.Preconditions;
 import com.google.common.base.Throwables;
 import com.google.inject.Inject;
+import com.google.inject.Key;
 import com.google.inject.OutOfScopeException;
+import com.google.inject.internal.Errors;
 
 import java.io.IOException;
 import java.lang.ref.WeakReference;
@@ -142,27 +144,27 @@
     }
   }
 
-  static HttpServletRequest getOriginalRequest() {
-    return getContext().getOriginalRequest();
+  static HttpServletRequest getOriginalRequest(Key<?> key) {
+    return getContext(key).getOriginalRequest();
   }
 
-  static HttpServletRequest getRequest() {
-    return getContext().getRequest();
+  static HttpServletRequest getRequest(Key<?> key) {
+    return getContext(key).getRequest();
   }
 
-  static HttpServletResponse getResponse() {
-    return getContext().getResponse();
+  static HttpServletResponse getResponse(Key<?> key) {
+    return getContext(key).getResponse();
   }
 
   static ServletContext getServletContext() {
     return servletContext.get();
   }
 
-  private static Context getContext() {
+  private static Context getContext(Key<?> key) {
     Context context = localContext.get();
     if (context == null) {
-      throw new OutOfScopeException("Cannot access scoped object. Either we"
-          + " are not currently inside an HTTP Servlet request, or you may"
+      throw new OutOfScopeException("Cannot access scoped [" + Errors.convert(key) 
+          + "]. Either we are not currently inside an HTTP Servlet request, or you may"
           + " have forgotten to apply " + GuiceFilter.class.getName()
           + " as a servlet filter for this request.");
     }
diff --git a/extensions/servlet/src/com/google/inject/servlet/InternalServletModule.java b/extensions/servlet/src/com/google/inject/servlet/InternalServletModule.java
index 8043ca9..046b8b6 100644
--- a/extensions/servlet/src/com/google/inject/servlet/InternalServletModule.java
+++ b/extensions/servlet/src/com/google/inject/servlet/InternalServletModule.java
@@ -20,6 +20,7 @@
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
+import com.google.inject.Key;
 import com.google.inject.Provider;
 import com.google.inject.Provides;
 import com.google.inject.Singleton;
@@ -102,15 +103,15 @@
   }
 
   @Provides @RequestScoped HttpServletRequest provideHttpServletRequest() {
-    return GuiceFilter.getRequest();
+    return GuiceFilter.getRequest(Key.get(HttpServletRequest.class));
   }
 
   @Provides @RequestScoped HttpServletResponse provideHttpServletResponse() {
-    return GuiceFilter.getResponse();
+    return GuiceFilter.getResponse(Key.get(HttpServletResponse.class));
   }
 
   @Provides HttpSession provideHttpSession() {
-    return GuiceFilter.getRequest().getSession();
+    return GuiceFilter.getRequest(Key.get(HttpSession.class)).getSession();
   }
 
   @SuppressWarnings("unchecked") // defined by getParameterMap()
diff --git a/extensions/servlet/src/com/google/inject/servlet/ServletScopes.java b/extensions/servlet/src/com/google/inject/servlet/ServletScopes.java
index cd593bf..9d4e278 100644
--- a/extensions/servlet/src/com/google/inject/servlet/ServletScopes.java
+++ b/extensions/servlet/src/com/google/inject/servlet/ServletScopes.java
@@ -103,7 +103,7 @@
           // {@code GuiceFilter.getRequest()}.
           //
           // This _correctly_ throws up if the thread is out of scope.
-          HttpServletRequest request = GuiceFilter.getOriginalRequest();
+          HttpServletRequest request = GuiceFilter.getOriginalRequest(key);
           if (REQUEST_CONTEXT_KEYS.contains(key)) {
             // Don't store these keys as attributes, since they are handled by
             // GuiceFilter itself.
@@ -144,11 +144,11 @@
    * HTTP session scope.
    */
   public static final Scope SESSION = new Scope() {
-    public <T> Provider<T> scope(Key<T> key, final Provider<T> creator) {
+    public <T> Provider<T> scope(final Key<T> key, final Provider<T> creator) {
       final String name = key.toString();
       return new Provider<T>() {
         public T get() {
-          HttpSession session = GuiceFilter.getRequest().getSession();
+          HttpSession session = GuiceFilter.getRequest(key).getSession();
           synchronized (session) {
             Object obj = session.getAttribute(name);
             if (NullObject.INSTANCE == obj) {
@@ -217,7 +217,8 @@
 
     // Snapshot the seed map and add all the instances to our continuing HTTP request.
     final ContinuingHttpServletRequest continuingRequest =
-        new ContinuingHttpServletRequest(GuiceFilter.getRequest());
+        new ContinuingHttpServletRequest(
+            GuiceFilter.getRequest(Key.get(HttpServletRequest.class)));
     for (Map.Entry<Key<?>, Object> entry : seedMap.entrySet()) {
       Object value = validateAndCanonicalizeValue(entry.getKey(), entry.getValue());
       continuingRequest.setAttribute(entry.getKey().toString(), value);
diff --git a/extensions/servlet/test/com/google/inject/servlet/ServletTest.java b/extensions/servlet/test/com/google/inject/servlet/ServletTest.java
index ae1750b..beb0873 100644
--- a/extensions/servlet/test/com/google/inject/servlet/ServletTest.java
+++ b/extensions/servlet/test/com/google/inject/servlet/ServletTest.java
@@ -16,6 +16,7 @@
 
 package com.google.inject.servlet;
 
+import static com.google.inject.Asserts.assertContains;
 import static com.google.inject.Asserts.reserialize;
 import static com.google.inject.servlet.ServletTestUtils.newFakeHttpServletRequest;
 import static com.google.inject.servlet.ServletTestUtils.newFakeHttpServletResponse;
@@ -35,6 +36,11 @@
 import com.google.inject.Key;
 import com.google.inject.Module;
 import com.google.inject.Provider;
+import com.google.inject.Provides;
+import com.google.inject.ProvisionException;
+import com.google.inject.internal.Errors;
+import com.google.inject.name.Named;
+import com.google.inject.name.Names;
 import com.google.inject.servlet.ServletScopes.NullObject;
 import com.google.inject.util.Providers;
 
@@ -68,7 +74,6 @@
   private static final Key<Map<String, String[]>> REQ_PARAMS_KEY
       = new Key<Map<String, String[]>>(RequestParameters.class) {};
 
-  private static final Key<InRequest> IN_REQUEST_KEY = Key.get(InRequest.class);
   private static final Key<InRequest> IN_REQUEST_NULL_KEY = Key.get(InRequest.class, Null.class);
   private static final Key<InSession> IN_SESSION_KEY = Key.get(InSession.class);
   private static final Key<InSession> IN_SESSION_NULL_KEY = Key.get(InSession.class, Null.class);
@@ -78,6 +83,39 @@
     //we need to clear the reference to the pipeline every test =(
     GuiceFilter.reset();
   }
+  
+  public void testScopeExceptions() throws Exception {
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      @Override protected void configure() {
+        install(new ServletModule());        
+      }
+      @Provides @RequestScoped String provideString() { return "foo"; }
+      @Provides @SessionScoped Integer provideInteger() { return 1; }
+      @Provides @RequestScoped @Named("foo") String provideNamedString() { return "foo"; }
+    });
+    
+    try {
+      injector.getInstance(String.class);
+      fail();
+    } catch(ProvisionException oose) {
+      assertContains(oose.getMessage(), "Cannot access scoped [java.lang.String].");
+    }
+    
+    try {
+      injector.getInstance(Integer.class);
+      fail();
+    } catch(ProvisionException oose) {
+      assertContains(oose.getMessage(), "Cannot access scoped [java.lang.Integer].");
+    }
+    
+    Key<?> key = Key.get(String.class, Names.named("foo"));
+    try {
+      injector.getInstance(key);
+      fail();
+    } catch(ProvisionException oose) {
+      assertContains(oose.getMessage(), "Cannot access scoped [" + Errors.convert(key) + "]");
+    }
+  }
 
   public void testRequestAndResponseBindings() throws Exception {
     final Injector injector = createInjector();
@@ -183,7 +221,7 @@
   public void testRequestAndResponseBindings_matchesPassedParameters() throws Exception {
     final int[] filterInvoked = new int[1];
     final boolean[] servletInvoked = new boolean[1];
-    final Injector injector = createInjector(new ServletModule() {
+    createInjector(new ServletModule() {
       @Override protected void configureServlets() {
         final HttpServletRequest[] previousReq = new HttpServletRequest[1];
         final HttpServletResponse[] previousResp = new HttpServletResponse[1];
@@ -340,8 +378,7 @@
     assertTrue(invoked[0]);
   }
 
-  public void testHttpSessionIsSerializable()
-      throws IOException, ClassNotFoundException, ServletException {
+  public void testHttpSessionIsSerializable() throws Exception {
     final Injector injector = createInjector();
     final HttpServletRequest request = newFakeHttpServletRequest();
     final HttpSession session = request.getSession();