Author: limpbizkit
Date: Fri Sep 19 09:35:09 2008
New Revision: 621

Added:
    wiki/Scopes.wiki

Log:
Created wiki page through web user interface.

Added: wiki/Scopes.wiki
==============================================================================
--- (empty file)
+++ wiki/Scopes.wiki    Fri Sep 19 09:35:09 2008
@@ -0,0 +1,135 @@
+#summary Overview of writing custom scopes for Guice
+
+= Introduction =
+
+Scopes are one of Guice's most powerful features.
+
+
+= Best Practices =
+
+Prefer to bind with the scope annotation rather than the scope instance:
+{{{
+  // good:
+  bind(Foo.class).in(ServletScopes.REQUEST);
+
+  // better:
+  bind(Bar.class).in(RequestScoped.class);
+}}}
+This way you can reuse the module in a non-servlets environment by  
specifying a different scope to implement for `RequestScoped.class`
+
+
+= Custom Scopes =
+
+It is generally recommended that users *do not* write their own custom  
scopes -- the built-in scopes should be sufficient for most applications.  
If you're writing a web application, the `ServletModule` provides simple,  
well tested scope implementations for HTTP requests and HTTP sessions.
+
+In the rare case that you do need a custom scope, `SimpleScope` is a  
decent starting point. Copy this class into your project and tweak it to  
suit your needs.
+
+{{{
+/**
+ * Scopes a single execution of a block of code. Apply this scope with a
+ * try/finally block: <pre>   [EMAIL PROTECTED]
+ *
+ *   scope.enter();
+ *   try {
+ *     // explicitly seed some seed objects...
+ *     scope.seed(Key.get(SomeObject.class), someObject);
+ *     // create and access scoped objects
+ *   } finally {
+ *     scope.exit();
+ *   }
+ * }</pre>
+ *
+ * The scope can be initialized with one or more seed values by calling
+ * <code>seed(key, value)</code> before the injector will be called upon to
+ * provide for this key. A typical use is for a servlet filter to  
enter/exit the
+ * scope, representing a Request Scope, and seed HttpServletRequest and
+ * HttpServletResponse.  For each key inserted with seed(), it's good  
practice
+ * (since you have to provide <i>some</i> binding anyhow) to include a
+ * corresponding binding that will throw an exception if Guice is asked to
+ * provide for that key if it was not yet seeded: <pre>   [EMAIL PROTECTED]
+ *
+ *   bind(key)
+ *       .toProvider(SimpleScope.<KeyClass>seededKeyProvider())
+ *       .in(ScopeAnnotation.class);
+ * }</pre>
+ *
+ * @author Jesse Wilson
+ * @author Fedor Karpelevitch
+ */
+public class SimpleScope implements Scope {
+
+  private static final Provider<Object> SEEDED_KEY_PROVIDER =
+      new Provider<Object>() {
+        @Override
+        public Object get() {
+          throw new IllegalStateException("If you got here then it means  
that" +
+              " your code asked for scoped object which should have been" +
+              " explicitly seeded in this scope by calling" +
+              " SimpleScope.seed(), but was not.");
+        }
+      };
+  private final ThreadLocal<Map<Key<?>, Object>> values
+      = new ThreadLocal<Map<Key<?>, Object>>();
+
+  public void enter() {
+    checkState(values.get() == null, "A scoping block is already in  
progress");
+    values.set(Maps.<Key<?>, Object>newHashMap());
+  }
+
+  public void exit() {
+    checkState(values.get() != null, "No scoping block in progress");
+    values.remove();
+  }
+
+  public <T> void seed(Key<T> key, T value) {
+    Map<Key<?>, Object> scopedObjects = getScopedObjectMap(key);
+    checkState(!scopedObjects.containsKey(key), "A value for the key %s  
was " +
+        "already seeded in this scope. Old value: %s New value: %s", key,
+        scopedObjects.get(key), value);
+    scopedObjects.put(key, value);
+  }
+
+  public <T> void seed(Class<T> clazz, T value) {
+    seed(Key.get(clazz), value);
+  }
+
+  @Override
+  public <T> Provider<T> scope(final Key<T> key, final Provider<T>  
unscoped) {
+    return new Provider<T>() {
+      @Override
+      public T get() {
+        Map<Key<?>, Object> scopedObjects = getScopedObjectMap(key);
+
+        @SuppressWarnings("unchecked")
+        T current = (T) scopedObjects.get(key);
+        if (current == null && !scopedObjects.containsKey(key)) {
+          current = unscoped.get();
+          scopedObjects.put(key, current);
+        }
+        return current;
+      }
+    };
+  }
+
+  private <T> Map<Key<?>, Object> getScopedObjectMap(Key<T> key) {
+    Map<Key<?>, Object> scopedObjects = values.get();
+    if (scopedObjects == null) {
+      throw new OutOfScopeException("Cannot access " + key
+          + " outside of a scoping block");
+    }
+    return scopedObjects;
+  }
+
+  /**
+   * Returns a provider that always throws exception complaining that the  
object
+   * in question must be seeded before it can be injected.
+   *
+   * @return typed provider
+   */
+  @SuppressWarnings({"unchecked"})
+  public static <T> Provider<T> seededKeyProvider() {
+    return (Provider<T>) SEEDED_KEY_PROVIDER;
+  }
+
+}
+}}}
\ No newline at end of file

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"google-guice-dev" 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-dev?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to