xiaodududu / google-guice

Automatically exported from code.google.com/p/google-guice
Apache License 2.0
0 stars 0 forks source link

Simplify ServletScopes.scopeRequest() #680

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
I spent a week trying to figure out how to get ServletScopes.scopeRequest() 
working. The only code samples I could find were the unit tests and even then I 
found the API very confusing (see [1] for a detailed explanation).

We need to differentiate between two types of variables being passed to the 
Callable:

1. Injected stuff (configured by the main Module)
2. User-supplied arguments

This is similar to AssistedInject in that #1 comes from a Module and #2 comes 
from the user. The problem is that ServletScopes.scopeRequest()'s seedMap 
forces us to reference #2 in the Module (where it doesn't really belong).

I'd like to propose an alternative API (see attachment) with the following 
characteristics:

1. The main module is kept free of user-supplied variables.
2. Replace seedMap with a child Module. The Binder API is easier to use and 
more flexible.
3. In the old API, the user Callable is injected outside the request scope, 
while call() is invoked inside the request scope. This forces users to inject 
Provider<Foo> instead of Foo. The new API allows users to inject Foo directly.

What do you think?

[1] The current API is extremely fragile. If the user misconfigures the 
slightest thing in the Module he'll get a cryptic error or the wrong values 
will get injected.

Common configuration mistakes:

1. Define user-supplied variables in seedMap but not in main Module. Guice will 
complain:

  No implementation for java.lang.String annotated with @com.google.inject.name.Named(value=username) was bound.

2. If user uses the following code (based on the unit tests):

  bindConstant().annotatedWith(Names.named("username")).to("wrong_value");
  bind(String.class).in(RequestScoped.class);

Username will get value "wrong_value".

3. The magical formula to get this working is:

* Put user-supplied variables into seedMap.
* Remove bindConstant() and use the following code in the main Module:

  bind(String.class).annotatedWith(Names.named("username")).to(String.class).in(RequestScoped.class);

Anything else will result in runtime exceptions or the variable getting the 
wrong value. It's very unintuitive.

Original issue reported on code.google.com by cow...@bbs.darktech.org on 25 Jan 2012 at 5:56

Attachments:

GoogleCodeExporter commented 9 years ago
I forgot to attach RequestInjector...

Original comment by cow...@bbs.darktech.org on 3 Feb 2012 at 12:46

Attachments: