Dagger Unsmartness(1): Map and Set of Map.Entry

Dagger treats Map and Set<Map.Entry> as two different types when you define both of them in its module files. This seems obvious but can cause problem when you have multiple developers working on multiple modules based large project, and especially when someone in the team naively thinks Dagger would automatically merge them.  Here below is the example,


import java.util.Map;

import javax.inject.Singleton;

import com.google.common.collect.ImmutableMap;

import dagger.Module;
import dagger.Provides;

@Module(library = true)
public class MapModule
{
 @Provides
 @Singleton
 Map<String, String> provideNamesMap()
 {
 return ImmutableMap.<String, String> of("First2", "Last2");
 }
}


import java.util.Map;
import java.util.Set;

import javax.inject.Singleton;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;

import dagger.Module;
import dagger.Provides;

@Module(library = true)
public class SetModule
{
 @Provides(type = Provides.Type.SET_VALUES)
 @Singleton
 Set<Map.Entry<String, String>> provideNamesSet()
 {
 return ImmutableSet.<Map.Entry<String, String>> of(Maps.<String, String> immutableEntry("First1", "Last1"));
 }
}


import dagger.Module;

@Module(injects = HelloWorld.class, includes = { SetModule.class, MapModule.class
})
public class HelloModule
{

}


import java.util.Map;
import java.util.Set;

import javax.inject.Inject;

import dagger.ObjectGraph;

public class HelloWorld
{
 @Inject
 Set<Map.Entry<String, String>> names1;

@Inject
 Map<String, String> names2;

public void run()
 {
 for (Map.Entry<String, String> entry : names1)
 {
 System.out.println("names1 has " + entry.getKey() + " " + entry.getValue());
 }

for (Map.Entry<String, String> entry : names2.entrySet())
 {
 System.out.println("names2 has " + entry.getKey() + " " + entry.getValue());
 }
 }

public static void main(String[] args)
 {
 ObjectGraph objectGraph = ObjectGraph.create(new HelloModule());
 HelloWorld app = objectGraph.get(HelloWorld.class);
 app.run();
 }
}

The output of the above main is

names1 has First1 Last1
names2 has First2 Last2

This result is more understandable if you take a look at the Dagger compiled classes. In the generated source HelloWorld$$InjectAdapter, you will see

public void attach(Linker linker) {
 names1 = (Binding<Set<java.util.Map.Entry<String, String>>>) linker.requestBinding("java.util.Set<java.util.Map$Entry<java.lang.String, java.lang.String>>", HelloWorld.class, getClass().getClassLoader());
 names2 = (Binding<java.util.Map<String, String>>) linker.requestBinding("java.util.Map<java.lang.String, java.lang.String>", HelloWorld.class, getClass().getClassLoader());
 }

This clearly tells that Dagger is not dealing with the merging between Map and Set<Map.Entry> so this is a work you, as a developer, have to do in your wish.

Advertisements
This entry was posted in Java, Programming and tagged , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s