Atom Feed SITE FEED   ADD TO GOOGLE READER

Strict vs. Forgiving APIs

Suppose it's the early 1990's and you're James Gosling implementing String.substring(int, int) for the first time. What should happen when the index arguments are out-of-range? Should these tests pass? Or throw?
  public void testSubstring() {
assertEquals("class", "superclass".substring(5, 32));
assertEquals("super", "superclass".substring(-2, 5));
assertEquals("", "superclass".substring(20, 24));
assertEquals("superclass", "superclass".substring(10, 0));
}


Forgiving APIs


In a forgiving API, these tests pass. The implementation would recognize the out-of-range indices and correct for them. Benefits of forgiving APIs:
  • Fault-tolerant. An off-by-one mistake won't bring a production system to its knees.
  • Easier to code against. If you don't know what to use for a given argument, just pass null and the implementation will do something reasonable.


Strict APIs


In a strict APIs, the out-of-range arguments to substring are forbidden and the method throws an IllegalArgumentException. Benefits of strict APIs:
  • Fail-fast. An off-by-one mistake will be caught in unit tests, if they exist.
  • Easier to maintain. By limiting the number of valid inputs, there's less behaviour to maintain and test.
  • More Predictable. Mapping invalid inputs to behaviour is an artform. In the example, should substring(10, 0) return the empty string? Or "superclass"? What would the caller expect?


For maintainability, I almost always prefer strict APIs. I like to think of the classes in my code as the gears in a fine Swiss watch. Everything fits together tightly, with firm constraints on both the inputs and the outputs. I can refactor with confidence because the system simply won't work if I've introduced problems into it. With a forgiving API, I could introduce bugs and not find out about them until much later.

What's a Hierarchical Injector?

Our application has two implementations for one interface. EnergySource is implemented by both Plutonium and LightningBolt:
class DeLorean {
@Inject TimeCircuits timeCircuits;
@Inject FluxCapacitor fluxCapacitor;
@Inject EnergySource energySource;
}

interface FluxCapacitor {
boolean isFluxing();
}

@Singleton
class RealFluxCapacitor implements FluxCapacitor {
@Inject TimeCircuits timeCircuits;
boolean isFluxing;

public boolean isFluxing() {
return isFluxing;
}
}

class TimeCircuits {
Date whereYouveBeen;
Date whereYouAre;
Date whereYourGoing;
}

interface EnergySource {
void generateOnePointTwentyOneGigawatts();
}

class Plutonium implements EnergySource { ... }

class LightningBolt implements EnergySource { ... }

And to allow for sequels, we assume other implementations of EnergySource are possible. We'd like to create an Injector immediately and create a Plutonium-powered DeLorean. Shortly thereafter, we'd like to re-use that same Injector, but with a lightning bolt for energy.


Option one: Factory classes


We can solve this problem by introducing a DeLorean.Factory interface that accepts an EnergySource as its only parameter:
class DeLorean {
private final TimeCircuits timeCircuits;
private final FluxCapacitor fluxCapacitor;
private final EnergySource energySource;

DeLorean(TimeCircuits timeCircuits,
FluxCapacitor fluxCapacitor,
EnergySource energySource) {
this.timeCircuits = timeCircuits;
this.fluxCapacitor = fluxCapacitor;
this.energySource = energySource;
}

static class Factory {
@Inject TimeCircuits timeCircuits;
@Inject FluxCapacitor fluxCapacitor;

DeLorean create(EnergySource energySource) {
return new DeLorean(timeCircuits, fluxCapacitor, energySource);
}
}
}

This works for our specific problem, but in general it's quite awkward:
  • It requires a gross amount of boilerplate code.
  • It discourages refactoring of the DeLorean class.
  • It increases the complexity of getting an EnergySource.
  • It doesn't work unless EnergySource is a direct dependency of the DeLorean class. Otherwise you need to create lots of little factories that cascade.
  • And EnergySource is no longer in-the-club—it doesn't participate in Guice's injection, AOP, scoping, etc.


Option two: AssistedInject


AssistedInject is a Guice extension that's intended to reduce the boilerplate of option one. Instead of a factory class, we write a factory interface plus annotations:
class DeLorean {
TimeCircuits timeCircuits;
FluxCapacitor fluxCapacitor;
EnergySource energySource;

@AssistedInject
DeLorean(TimeCircuits timeCircuits,
FluxCapacitor fluxCapacitor,
@Assisted EnergySource energySource) {
this.timeCircuits = timeCircuits;
this.fluxCapacitor = fluxCapacitor;
this.energySource = energySource;
}

interface Factory {
DeLorean create(EnergySource energySource);
}
}

This fixes some problems. But the core issue still remains: getting an instance of EnergySource is difficult. Unlike regular Guice (@Inject is the new new), you need to change all callers if you add a dependency on EnergySource.

Option three: Hierarchical Injectors


The premise is simple. @Inject anything, even stuff you don't know at injector-creation time. So our DeLorean class would look exactly as it would if EnergySource was constant:
class DeLorean {
TimeCircuits timeCircuits;
FluxCapacitor fluxCapacitor;
EnergySource energySource;

@Inject
DeLorean(TimeCircuits timeCircuits,
FluxCapacitor fluxCapacitor,
EnergySource energySource) {
this.timeCircuits = timeCircuits;
this.fluxCapacitor = fluxCapacitor;
this.energySource = energySource;
}
}

To use it, we start with an Injector that had bindings for everything except for EnergySource. Next, we create a second injector that extends the first, and binds either Plutonium or LightningBolt. This second injector fills in its missing binding.

The injectors share singletons, so we don't have to worry about having multiple TimeCircuits. Static analysis is applied to both injectors as a whole, where complete information is known. And all objects are in-the-club and get Guice value-adds like injection, scoping and AOP.

This is the solution to the mystical Robot Legs problem, wherein we have a RobotLeg class, that needs be injected with either a LeftFoot or a RightFoot, depending on where the leg will ultimately be used.

Criticism of Hierarchical Injectors


They suggest competing bindings. One parent injector could have relations with multiple child injectors. In our example, the parent injector binds DeLorean and TimeCircuits, and each child binds a different EnergySource.

They require abstract Injectors. The parent injector in our example wouldn't be able to create an instance of DeLorean, since it doesn't have all of the prerequisite bindings. This is just weird.

They're complex. Guice was born out of making code simpler. Does the conceptual weight of hierarchical injectors justify their inclusion?

Going forward


Today's Guice includes a simplified implementation of hierarchical injectors written by Dan Halem. It doesn't cover the interesting (but complex) case where the parent injector cannot fulfill all of its bindings. I'm studying the use cases, trying to come up with a balance between ease-of-use and power.

For example, one idea is to require users to explicitly call-out bindings that child injectors will provide:
  public void configure() {
bind(EnergySource.class).throughChildInjector();
}

I'd also like to do something similar to AssistedInject's factory interfaces. This way the second injector would be created, used and discarded transparently, so the user never needs to see it. From the user's perspective, this would just be like AssistedInject, but the assisted parameters could be injected anywhere.

If you have suggested use-cases or ideas, I'd love to hear 'em.

Wanted: Guice Injector Graphing

One of the nice new features of Guice 2.0 is the new introspection API. It's the equivalent of java.lang.reflect for Guice - it lets you inspect your application at runtime. Our goal is to make it easy to write rich tools for Guice. A natural use case is visualizing an application. The right graph can reveal the structure of your application. I've opened a feature request for this, Issue 213. I created a proof-of-concept to drum-up excitement for this idea.

Example Graph: Application Code


class DeLorean {
@Inject TimeCircuits timeCircuits;
@Inject FluxCapacitor fluxCapacitor;
@Inject EnergySource energySource;
}

class FluxCapacitor {
@Inject TimeCircuits timeCircuits;
}

class TimeCircuits {
Date whereYouveBeen;
Date whereYouAre;
Date whereYourGoing;
}

interface EnergySource {
String generateOnePointTwentyOneGigawatts();
}

class Plutonium implements EnergySource {
public String generateOnePointTwentyOneGigawatts() {
return "newk-you-ler";
}
}

Example Graph: Guice Configuration


    Injector injector = Guice.createInjector(new AbstractModule() {
protected void configure() {
bind(EnergySource.class).to(Plutonium.class);
bind(FluxCapacitor.class);
bind(DeLorean.class);
}
});


.dot File


My Grapher code takes the above Injector and outputs a .dot file that describes a graph:
digraph injector {
"FluxCapacitor" -> "FluxCapacitor.()" [arrowhead=onormal];
"FluxCapacitor" -> "TimeCircuits" [label=timeCircuits]
"DeLorean" -> "DeLorean.()" [arrowhead=onormal];
"DeLorean" -> "TimeCircuits" [label=timeCircuits]
"DeLorean" -> "FluxCapacitor" [label=fluxCapacitor]
"DeLorean" -> "EnergySource" [label=energySource]
"EnergySource" -> "Plutonium" [arrowhead=onormal];
}


The Rendered Graph


Finally, Graphviz renders the .dot file to a pretty picture:


This graph is a good start, but there's a long way to go. Unfortunately, I don't have the bandwidth to take this project to completion and am seeking a contributor. If you're interested, post a note on the issue. Coding is its own reward!

Integer.class and int.class as Guice Keys

Shortly after fixing arrays, I've found another multiple representations bug. This problem is probably familiar - I'm confusing primitive types (like int) with wrapper types (like Integer).

It's one binding


The critical question: should these tests pass?
    assertEquals(Key.get(int.class), Key.get(Integer.class));
assertEquals(TypeLiteral.get(int.class), TypeLiteral.get(Integer.class));
Currently these are non-equal, so Guice has special cases so that they both work. But some special cases are missing! Consider issue 116:
    Injector injector = Guice.createInjector(new AbstractModule() {
protected void configure() {
bind(injector.class).toInstance(1984);
}
});
assertEquals(1984, (int) injector.getInstance(int.class)); /* passes */
assertEquals(1984, (int) injector.getInstance(Integer.class)); /* passes */
assertEquals(1984, (int) injector.getInstance(Key.get(int.class))); /* passes */
assertEquals(1984, (int) injector.getInstance(Key.get(Integer.class))); /* passes */
assertNotNull(injector.getBinding(Key.get(int.class))); /* passes */
assertNotNull(injector.getBinding(Key.get(Integer.class))); /* fails! */

Should Key be fixed?


Yes. I think I'll change Key so that it always uses Integer.class, regardless of whether it was created with int.class or Integer.class. Otherwise, this stuff is just too prone to bugs. For example, our new Binder SPI can return Provider<int>, even though that's not a valid type.

Should TypeLiteral be fixed?


Probably not. I'm leaning towards leaving it as-is. Consider an interface with these methods:
    public boolean remove(Integer value)
public Integer remove(int index);
If I change TypeLiteral, then the "remove" method is ambiguous when I know the TypeLiteral of the parameter type. But as a side effect of being inconsistent with Key, this test will always fail:
  TypeLiteral<Integer> primitive = TypeLiteral.get(int.class);
TypeLiteral<Integer> wrapper = new TypeLiteral<Integer>() {};
assertEquals(Key.get(primitive), Key.get(wrapper));
assertEquals(primitive, wrapper);
I think it's a fair compromise.

Fixing the right thing


By making my changes to Key and TypeLiteral, I can make Guice behave consistently throughout all of its APIs. I won't have to worry about users who bind both int.class and Integer.class. And I should be able to rip out some special cases both Guice and its extensions.

If there's a Guice issue that's you'd like fixed, this is a great time to get your feelings heard. I'm spending a lot of time on the issues list, trying to decide what will make the cut for 2.0.

Wanted: javax.interceptor extension for Guice

I'm feverishly preparing Guice for the 2.0 release later this summer, and tonight I scanned through our issues list. There's a whole bunch of good features that I won't get to before our release. So I'm looking for Guice users to help out with development!

Introducing javax.interceptor


javax.interceptor is a fairly-simple method interception package for modern Enterprise Java stacks. These examples show how it works. Create a class with an @Interceptors annotation:
@Interceptors(AuditInterceptor.class)
public class AccountBean implements Account {
private int balance = 0;

public void deposit(int amount) {
balance += amount;
}
public void withdraw(int amount) {
balance -= amount;
}
}
Then create the interceptor:
public class AuditInterceptor {
@AroundInvoke
public Object audit(InvocationContext invocationContext) throws Exception {
System.out.println("Invoking method: " + invocationContext.getMethod());
return invocationContext.proceed();
}
}

If everything works as intended, the interceptor's audit() method will intercept all calls to deposit() and withdraw().

Guice's MethodInterceptor


Guice has another API for this, MethodInterceptor. Guice uses Matchers to support arbitrary selection of interceptable methods.

Wanted: an Extension for javax.interceptor


I believe this feature could be implemented as an extension to Guice. The extension would certainly require some clever tricks, but it should not require changes to the Guice internals. Here's what I guess the implementation could look like:
public class JavaxInterceptorModule extends AbstractModule {
public void configure() {
JavaxInterceptor interceptor = new JavaxInterceptor();
injectMembers(interceptor);
bindInterceptor(Matchers,any(), new InterceptMethodsMatcher(), interceptor);
}

static class JavaxInterceptor {
/**
* Loop over all the injector's bindings, looking for @Interceptor.
* Then verify that the interceptor classes are either injectable (ie.
* they have bindings), or they have a no-arg constructor. This
* isn't strictly necessary, but it allows us to fail faster, which is
* always a Guicy thing to do.
*/
@Inject void initialize(Injector injector) { ... }

/**
* Validate that the target method is intercepted. We need to
* consider just-in-time bindings that might not have been
* checked during initialize(). We also need to check for the
* ExcludeClassInterceptors etc. annotations.
*
* <p>Instantiate all of the injectors for this method, then
* run 'em. We'll need our own implementation of InvocationContext
* to pass to the interceptors.
*/
Object invoke(MethodInvocation invocation) { ... }
}
}

Of course it's not this simple. The implementation needs be tested to be consistent with the Java EE implementations. It needs to have reasonable error handing. And there's nuances related to inheritance etc. It also needs thorough unit tests.

Recruiting Contributors


Does writing this code sound fun to you? If it does, we'd love your help. Post your interest on the bug! You'll need to checkout the Guice code, write the code and tests, and upload a patch. I'll code review the patch (a fairly involved process) and we'll iterate until it's perfect.

In return, you'll get to see your @author line in the Guice source code. You'll probably learn a lot about AOP, Guice and reflection. It's resume padding. And of course, coding is its own reward.

Bug pattern: multiple ways to represent the same data

There's a class of bugs that come up when one logical datatypes has representations in multiple classes. The best example of this is 1 vs. 1L. Both ones represent the same data. But new Integer(1) is not equal to new Long(1) according to the corresponding equals() methods.

Calling contains(1) on a List<Long> compiles just fine, it just won't ever return true. Similarly for Map.get() and Set.contains(). Anything that depends on equals() is broken if you mix different types to express 'one'.

The problem is that each defines an equals method that is local to its class. This is a fair design - but as a consequence these types should not be mixed.

A short catalog of tricky types


...that can cause you pain if you mix them. These types can all represent the same logical value. But if you mix them, you will certainly get burned:
  • "0" : Byte, Short, Integer, Long
  • "0.0" : Float, Double
  • "Jan 1, 1970 12:00.00am UTC" : Date, long, Calendar
  • "http://publicobject.com" : URI, URL
  • "integer type" : int.class, Integer.class
  • "ABC" : StringBuffer, StringBuilder, CharSequence, String
  • "natural order" : Comparators.naturalOrder(), null
  • "String[].class" : GenericArrayType, Class (both of which implement Type)


A shorter catalog of good types


Fortunately, in a few places the JDK has interfaces that dictate how equals and hashCode must be implemented. As a consequence, you can freely intermix these types without consequence:
  • Sets: HashSet, LinkedHashSet, TreeSet
  • Maps: ConcurrentHashMap, HashMap, Collections.emptyMap()
  • Lists: ArrayList, LinkedList, Vector, Arrays.asList

Defining this behaviour for interfaces is somewhat difficult - use these classes as a guide. All implementations must implement the spec exactly or behaviour will be unreliable.

Recommendations


Avoid creating classes that allow one logical datatype to be represented by different classes. If you must, consider writing an interface to specify equals and hashCode at that level.

Choose a preferred, canonical form for your data. For example, if you consider 'null' and 'empty string' to be equal, choose one form and stick to it. Throw IllegalArgumentExceptions to callers that use the wrong one. If you're using collections, always use the canonical type for inserts and lookups.

Use an smart IDE like IntelliJ IDEA. It'll warn you when you mix types.

An Aside...


It turns out that Guice 1.0 suffered an ugly bug because of this problem. You can represent arrays in two different ways using Java 5's Types API. Either as an instance of Class or as an instance of GenericArrayType. The two are equivalent but not equals(). As a consequence, some injections would incorrectly fail with 'missing bindings' exceptions.

Guice talk, tomorrow morning at Google I/O

Bob and I are giving a talk at Google's developer conference tomorrow. From the session summary:
Wed 11:15am - 12:15pm
Bob Lee, Jesse Wilson

Guice (pronounced 'juice') is a Jolt award-winnning, lightweight dependency injection framework for Java 5 and above. Put simply, Guice alleviates the need for factories and the use of new in your Java code. Think of Guice's @Inject as the new new. You will still need to write factories in some cases, but your code will not depend directly on them. Your code will be easier to change, unit test and reuse in other contexts.

Calling a method that always throws

Kasper complains that it's hard to call methods that always throw. In particular, code like this won't compile because findGetter is missing a return statement:
  public Method findGetter() throws CsvException {
try {
return type.getMethod("get"
+ fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1));
} catch(SecurityException e) {
noSuchGetter(e);
} catch (NoSuchMethodException e) {
noSuchGetter(e);
}
}

public void noSuchGetter(Exception cause) throws CsvException {
String message = String.format("Unable to lookup getter"
+ " for field %s on %s", fieldName, type.getName());
throw new CsvException(message, cause);
}

The problem is that noSuchGetter always throws, but javac doesn't consider that when building this code. Making that method private or final doesn't help -- javac does not look at the body of a method when deciding whether the callers are valid.

Adding return null; to the end of this method appeases the compiler, but it sure isn't pretty:
  public Method findGetter() throws CsvException {
try {
return type.getMethod("get"
+ fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1));
} catch(SecurityException e) {
noSuchGetter(e);
} catch (NoSuchMethodException e) {
noSuchGetter(e);
}
return null; /* never executes! (this method never returns null.) */
}

As Kasper explains, this workaround sucks! In particular, it suggests to the code reader that he should check for null when calling this method. We need to add a big ugly comment to flag what's going on. Another workaround is to throw AssertionErrors on unreachable lines. This is an improvement but we still have dead code in our program. This line won't ever execute, adding noise to code coverage reports.

Fortunately, there's a clever fix. Declare that noSuchGetter returns a RuntimeException and prefix call to it with throw:
  public Method findGetter() throws CsvException {
try {
return type.getMethod("get"
+ fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1));
} catch(SecurityException e) {
throw noSuchGetter(e);
} catch (NoSuchMethodException e) {
throw noSuchGetter(e);
}
}

public CsvException noSuchGetter(Exception cause)
throws CsvException {
String message = String.format("Unable to lookup getter"
+ " for field %s on %s", fieldName, type.getName());
throw new CsvException(message, cause);
}

Now the code reader can see that the noSuchGetter calls always throw without reading that method's body. And the compiler will complain if you add any code after that call. We can optionally tweak this so noSuchGetter returns CsvException rather than throwing it.

Methods that always throw should return what they throw. If the method always throws a RuntimeException, we'd return that type.

Overriding Bindings in Guice

In our functional tests, we prefer to launch an application that closely resembles the production one. This means using the production modules in a proper staging environment. Even with automating scripts, setting up the environment is time consuming and tedious - it requires database install and configuration, permissions, SSL certificates, and remote services to be running and available:
public class ProductionModule extends AbstractModule {
protected void configure() {
bind(LoginService.class).to(RemoteLoginService.class);
bind(DataStore.class).to(MySqlDatabase.class);
bind(BillerConnection.class).to(SecureBillerConnection.class);
bind(LoggingEngine.class).to(DistributedLoggingEngine.class);
}
}

Since proper functional tests are so labour intensive, we take shortcuts! We can make a decent approximation of production by replacing some production services with lightweight fakes. For example, all of our functional tests require a login server to authenticate users. But for most tests login isn't interesting and this is just a wasted effort. We'd rather just fake login for unrelated functional tests.

Modular Modules


The best solution to this problem is to split the login stuff into its own module:
public class ProductionLoginModule extends AbstractModule {
protected void configure() {
bind(LoginService.class).to(RemoteLoginService.class);
}
}

In the functional test server we can use a FakeLoginModule rather than the ProductionLoginModule. It provides the same bindings, but its entirely in-memory and configuration free. This approach is simple, manageable and maintainable. It's the best way to mix production and test code.

Overrides via Inheritance


There's also a quick-and-dirty approach to creating test versions of servers. Extract each offending binding to its own method, and override that method in a subclass:
public class ProductionModule extends AbstractModule {
protected void configure() {
bindLoginService();
bind(DataStore.class).to(MySqlDatabase.class);
bind(BillerConnection.class).to(SecureBillerConnection.class);
bind(LoggingEngine.class).to(DistributedLoggingEngine.class);
}
protected void bindLoginService() {
bind(LoginService.class).to(RemoteLoginService.class);
}
}

public class TestModule extends ProductionModule {
@Override protected void bindLoginService() {
bind(LoginService.class).to(FakeLoginService.class);
}
}

This does this trick, but it's not elegant. We end up with different subclasses for each combination of fake bindings. It's fragile and makes for more work to divide the module later.

New: overrideModule


Sam Berlin has contributed a feature to Guice that provides a simple mechanism to replace bindings. To use it, we create a module with binding overrides:
public class OverridesModule extends AbstractModule {
@Override protected void configure() {
bind(LoginService.class).to(FakeLoginService.class);
}
}

We can combine our original, unmodified ProductionModule with the overrides to create a third module:
    Module functionalTestModule 
= Guice.overrideModule(new ProductionModule(), new OverridesModule());

In this example, we get the DataStore, BillerConnection and LoggingEngine bindings from ProductionModule, but the FakeLoginService from OverridesModule. The bindings in the overriding module replace bindings of the same key from the production module.

It's not as clean as modular modules, but it is more convenient. In particular, this approach doesn't require changes to the production module - great if that's provided by another team or a third party. It's also handy for testing the module itself!

This code is in SVN now if you're interested. It uses the new commands API to get a lot done in a small amount of code.

Fair Warning: I've been blogging about a lot of new Guice APIs lately. These APIs aren't final. If you depend on unreleased APIs from Guice svn, be aware that those APIs will probably change for 2.0.

MapBinder checked in!

Building out the Multibindings extension, David P. Baker has written a new class that simplifies Map binding. MapBinder uses an API that's consistent with Multibinder:
public class SnacksModule extends AbstractModule {
protected void configure() {
MapBinder<String, Snack> mapBinder
= MapBinder.newMapBinder(binder(), String.class, Snack.class);
mapBinder.addBinding("twix").toInstance(new Twix());
mapBinder.addBinding("snickers").toProvider(SnickersProvider.class);
mapBinder.addBinding("skittles").to(Skittles.class);
}
}

Like Multibinder...


Keys must be non-null and unique. Values must be non-null. Values get resolved at injection-time, so they can be scoped. Bindings from different modules will be aggregated, which makes it usable for an application registry.

Unlike Multibinder...


For the example above, an extra binding is made for Map<String, Provider<Snack>>. This makes it so that if values are expensive to provide, you can get just the ones you need.

This API is available in Guice svn right now. The API is subject to change before version 2. I suspect we'll probably rename Multibinder to either SetBinder or MultiBinder. Any preferences?

Elite Guice 3: Private Bindings

In the first and second parts of this series, I discussed hooks for extending Guice. In this post I introduce private bindings.

Don't emulate Guice


The key to a good extension is tight integration with Guice. In particular, the extension shouldn't copy functionality from Guice; doing so can lead to subtle differences between the extension and Guice itself. The assisted inject extension reimplements constructor injection and that causes problems:
  • Standard Guice can inject private constructors, but I forgot to do configure this in assistedinject.
  • AOP doesn't work for assistedinject-created objects

These differences aren't dealbreakers, but they do make the extension harder to use, and they violate the principal of least surprise. A better assistedinject would have used Guice's constructor injection.

The Injector is just a bunch of bindings


In the Multibindings extension, we secretly create a binding for each element in the set. These bindings are implementation details of the extension, but they need to be bound in the shared injector.

We have to somehow create the bindings without a chance of conflicting with user-supplied bindings. If Multibinder and the user both bound the same key, injector creation would fail.

Private Annotations to the rescue


The fix is to create a binding annotation type with a narrow scope, such as package scope. Other code won't have access to this annotation, and therefore we can be confident that only our extension can create bindings with this annotation.

In the Multibindings extension, there's a custom annotation called @Element that's secretly applied to all elements. Each annotation instance is given a unique ID to ensure that the hosting keys are distinct. Unless they're using a tool that interrogates the Injector, the users of Multibinder never see these bindings. They're created internally and used internally. But they allow all of Guice's features to work naturally on the bound elements.

Implementing the annotation type is code-intensive, but there's thorough instructions that describe how equals, hashCode and even toString() should be implemented.

This technique is also used in InterceptingInjectorBuilder, in order to let InjectionController work its magic.

Why no Multibindings for Lists or Arrays?

The Multibindings code I checked in last week has been well received. There's even a screencast introducing the new code.

But there are missing features. We're still figuring out exactly what's the right balance of functionality and simplicity. One particular omission is the lack of support for Lists and arrays.

This is intentional. The deal breaker with Lists and arrays is that they imply an explicit order of their elements. But Multibinder has no idea how to order the elements. It could try to keep elements of the same module in the same order they were bound, but all bets are off when the bindings come from multiple modules. And it would be very annoying if reordering your modules changed the behaviour of your program.

But if you really want a List...


Its not to hard to make a List<String> binding using the Set<String> binding that Multibinder gives you.
    bind(new TypeLiteral<List<String>>() {})
.to(new Provider<List<String>>() {
@Inject Provider<Set<String>> setProvider;

public List<String> get() {
/* if we wanted to, we could sort the list somehow */
return Collections.unmodifiableList(
new ArrayList<String>(setProvider.get());
}
});

Using this technique, you could also bind Map<K, V> if you've got a binding to Set<Map.Entry<K, V>>. We're thinking about adding built-in support for Maps, but this will work until we do.

Elite Guice 2: Binding de-duplication

In part one, I showed how to initialize a Guice extension using the @Inject tag on a method. In this post I'm going to demonstrate a Guice for deduplicating bindings.

What is binding duplication?


One of the features of the Multibindings Extension is that there's no central coordination. Each module contributes its own bindings, and they all get amalgamated into a single collection. Suppose you have these modules:
public class CandybarModule extends AbstractModule {
protected void configure() {
Multibinder<Snack> multibinder = Multibinder.newSetBinder(binder(), Snack.class);
multibinder.addBinding().toInstance(new Twix());
multibinder.addBinding().toProvider(SnickersProvider.class);
}
}
public class ChipsModule extends AbstractModule {
protected void configure() {
Multibinder<Snack> multibinder = Multibinder.newSetBinder(binder(), Snack.class);
multibinder.addBinding().to(Pringles.class);
multibinder.addBinding().toInstance(new Doritos());
}
}

Out of this API, our Multibinder implementation needs to bind Set<Snack> exactly once. This is tricky! For example, suppose our newSetBinder method was implemented like this:
  public static <T> Multibinder<T> newSetBinder(Binder binder, Type type) {
binder.bind(getSetKey(type)).toProvider(getSetProvider(type));
return new Multibinder(type);
}

This won't work. We call newSetProvider from both the CandybarModule and the ChipsModule, and Guice complains because we're binding Set<Snack> twice. This is binding duplication.

If Guice had an duplicate-binding API


Guice doesn't have this API, but what we kind of find ourselves wanting is a way to query the binder for its bindings thus-far:
  public static <T> Multibinder<T> newSetBinder(Binder binder, Type type) {
if (!binder.getBindings().containsKey(getSetKey(type))) {
binder.bind(getSetKey(type)).toProvider(getSetProvider(type));
}
return new Multibinder(type);
}

This would work, but in general it's a pretty terrible idea. It makes it easy to write fragile modules - modules that depend on the order they are installed in. And it also changes the module from being static configuration (good!) to a dynamic-runtime configuration (bad!). So we're glad this API doesn't exist.

But in this one case, we really wish we could prevent our binding from being performed twice.

Modules as value objects


The solution to this problem is a bit surprising, but I think it's quite elegant. Guice conveniently allows the same module to be installed twice. This is necessary so that both your PizzaServletsModule and your PizzaDatabaseModule can install your PizzaDomainModule.

Rather than binding the Set<Snack> directly on the binder, we create special Module class whose only job is to create that binding. And then we give that module a proper equals() and hashCode() methods, so that any two instances that bind the same type are equal.

Our final code looks like this:
  public static <T> Multibinder<T> newSetBinder(Binder binder, Type type) {
binder.install(new MultibindingModule(getSetType(), getProviderType()));
return new Multibinder(type);
}

The Module trick allows us to decentralize the binding. And that means less configuration code, and that means less code. Hooray for Guice.

Elite Guice 1: Initialize your extension

I recently wrote some fairly, um, extreme code for the Guice Mutibindings extension. That code makes use of several tricks that you might find useful in your own Guice extensions. In this series I'm going to show-and-tell the various clever code tricks from Multibinder.java.

Initialize an extension


Guice doesn't have a plug-in API and it probably never will. But if it did, it would probably provide a mechanism for you to initialize your plugin:
public interface GuicePlugin {
void initialize(Injector injector) throws ConfigurationException;
}

This interface doesn't exist. But that's fine, because Guice does something better - it injects members into every bound instance and provider instance at injector-creation time. And where there is injection, there is initialization. There's two steps to getting Guice to call your initialize method:
  1. Bind an instance, or a provider instance.
    Usually your extension is going to bind something anyway. Multibinder binds its Set, AssistedInject binds its Factory, ThrowingProviders binds its ThrowingProvider. If you have absolutely nothing to bind, create a class and bind an instance of that.

    You must bind either an instance, a provider instance, or an eager singleton. These are the only things that get injected at injector-creation time.

  2. Create a @Inject initialize() method on the bound instance.
    This method gets called at injector-creation time. This is that important stage after all modules have been executed but before the Injector has been returned to its creator. Your initialize method can take any injectable objects as parameters - usually the Injector is a useful choice, since it allows your extension to review its complete set of bindings.

    The method can also throw exceptions to indicate that it's improperly configured. Guice 1.0 has a bug where sometimes these exceptions don't halt injection. But recent snapshots have fixed this problem and you can now reliably use exceptions to fail if your extension is misconfigured. AssistedInject uses this feature to fail if your assisted constructor cannot be injected.


Example


In Multibinder.java, we bind a provider instance for the set:
    public void configure(Binder binder) {
...
binder.bind(setKey).toProvider(setProviderInstance);
}

That provider has our initialize() method. In this case, the initialize method loops through all of the injector's bindings, collecting providers for the elements of the collection:
    /**
* Invoked by Guice at Injector-creation time to prepare providers for each
* element in this set. At this time the set's size is known, but its
* contents are only evaluated when get() is invoked.
*/
@Inject void initialize(Injector injector) {
providers = new ArrayList<Provider<T>>();
for (Map.Entry<Key, Binding> entry : injector.getBindings().entrySet()) {
if (keyMatches(entry.getKey())) {
Binding<T> binding = (Binding<T>) entry.getValue();
providers.add(binding.getProvider());
}
}
}

Hooray, our extension is initialized. In future posts I intend to discuss duplicate binding, private bindings, and perhaps annotation nesting.

Guice Multibindings extension checked in!

As previously alluded to, I've started work on the Multibindings API. I've checked in the initial implementation, and I'm pretty excited about it. You can grab it from svn.

This feature is ideal for lightweight plugin-type architectures, where you've got multiple modules each contributing Servlets, Actions, Filters, Components or even just names.

The Multibinder Javadoc:

An API to bind multiple values separately, only to later inject them as a complete collection. Multibinder is intended for use in your application's module:
public class SnacksModule extends AbstractModule {
protected void configure() {
Multibinder<Snack> multibinder
= Multibinder.newSetBinder(binder(), Snack.class);
multibinder.addBinding().toInstance(new Twix());
multibinder.addBinding().toProvider(SnickersProvider.class);
multibinder.addBinding().to(Skittles.class);
}
}

With this binding, a Set<Snack> can now be injected:
class SnackMachine {
@Inject
public SnackMachine(Set<Snack> snacks) { ... }
}

Create multibindings from different modules is supported. For example, it is okay to have both CandyModule and ChipsModule to both create their own Multibinder<Snack>, and to each contribute bindings to the set of snacks. When that set is injected, it will contain elements from both modules.

Elements are resolved at set injection time. If an element is bound to a provider, that provider's get method will be called each time the set is injected (unless the binding is also scoped).

Annotations are be used to create different sets of the same element type. Each distinct annotation gets its own independent collection of elements.

Elements must be distinct. If multiple bound elements have the same value, set injection will fail.

Elements must be non-null. If any set element is null, set injection will fail.