Multibind map object (and possible bug?)

30 views
Skip to first unread message

Donald Blodgett

unread,
Apr 14, 2013, 3:38:10 PM4/14/13
to sil...@googlegroups.com
Is there a way to multibind a java.util.Map?

Also not sure if I understand multibind completely or if this is a bug. I have the following code. The expected Integers are [1, 3], but for the testMultibindList and testMultibindSet ints equals [1, 2, 3] where in TestMultibindArray ints equals [1, 3] as expected.


public class DiTest {
   @Test
   public void testMultibindList() {
      Injector injector = Bootstrap.injector(TestBundle.class);
      Dependency<List> dependency = Dependency.dependency(Type.raw(List.class).parametized(Integer.class));
      List ints = injector.resolve(dependency.named("list_1"));
      
      Integer[] a = (Integer[]) ints.toArray(new Integer[ints.size()]);
      Arrays.sort(a);
      ints = Arrays.asList(a);
      
      List exp = new ArrayList();
      exp.add(1);
      exp.add(3);
      
      Assert.assertEquals(exp, ints);
   }
   
   @Test
   public void testMultibindSet() {
      Injector injector = Bootstrap.injector(TestBundle.class);
      Dependency<Set> dependency = Dependency.dependency(Type.raw(Set.class).parametized(Integer.class));
      Set ints = injector.resolve(dependency.named("list_1"));
      
      Set exp = new HashSet();
      exp.add(1);
      exp.add(3);
      
      Assert.assertEquals(exp, ints);
   }
   
   @Test
   public void testMultibindArray() {
      Injector injector = Bootstrap.injector(TestBundle.class);
      Dependency<Integer[]> dependency = Dependency.dependency(Type.raw(Integer[].class));
      Integer[] ints = injector.resolve(dependency.named("list_1"));
      
      Arrays.sort(ints);
      
      Integer[] exp = new Integer[] {1, 3};
      
      Assert.assertArrayEquals(exp, ints);
   }
}

public class TestBundle extends BootstrapperBundle {
   @Override
   protected void bootstrap() {
      install(TestModule.class);
      install(TestModule2.class);
      install(BuildinBundle.LIST);
      install(BuildinBundle.SET);
   }
}

public class TestModule extends BinderModule {
   @Override
   protected void declare() {
      multibind(Name.named("list_1"), Integer.class).to(1);
      multibind(Name.named("list_2"), Integer.class).to(2);
   }
}

public class TestModule2 extends BinderModule {
   @Override
   protected void declare() {
      multibind(Name.named("list_1"), Integer.class).to(3);
   }
}

jan

unread,
Apr 15, 2013, 2:58:00 AM4/15/13
to sil...@googlegroups.com
Hi,


On Sunday, 14 April 2013 21:38:10 UTC+2, Donald Blodgett wrote:
Is there a way to multibind a java.util.Map?
I assume you mean Map as result that is injected.
It is possible by adding a bridge like you have done for Set or List. Since I don't see a what value would be used as key there is no such bridge build in. You could do something like this.

class ArrayToMapBridgeSupplier extends ArrayBridgeSupplier<Map<?>> {

@Override
<E> Map<E> bridge( E[] elements ) {
Map<E> res = new HashMap<E>();
// fill map from elements
return res;
}
}

per( DEPENDENCY_TYPE ).starbind( Map.class ).to( new ArrayToMapBridgeSupplier() );
 
 
Also not sure if I understand multibind completely or if this is a bug. I have the following code. The expected Integers are [1, 3], but for the testMultibindList and testMultibindSet ints equals [1, 2, 3] where in TestMultibindArray ints equals [1, 3] as expected.

You used same instance name twice. That is not how it was meant to be used. I haven't thought about that possibility to use multibinds that way. E.g. to have different List instances. Right now it works on type level. Still all binds are kept and added to later lists or sets since those just filter. But it either should result in the list you expected or throw an exception since same instance has been bound twice.

Do you have a concrete use case or was it just a test ?

Jan

P.S. I noticed that there is no tool to add code blocks here. I assume this needs to be configured. 

jan

unread,
Apr 15, 2013, 3:01:57 AM4/15/13
to sil...@googlegroups.com

P.S. I noticed that there is no tool to add code blocks here. I assume this needs to be configured. 
// Has been enabled now

 

jan

unread,
Apr 15, 2013, 1:51:53 PM4/15/13
to sil...@googlegroups.com


On Sunday, 14 April 2013 21:38:10 UTC+2, Donald Blodgett wrote:
Also not sure if I understand multibind completely or if this is a bug. I have the following code. The expected Integers are [1, 3], but for the testMultibindList and testMultibindSet ints equals [1, 2, 3] where in TestMultibindArray ints equals [1, 3] as expected.
I created a test for this. 

I misunderstood the case. I assume that the multibind works as you expect. E.g. binding to 2 different named instances will work like adding elements. This works as long as working with the arrays directly. 

But what currently does not work is asking for named Lists or Sets. I am not 100% sure that it should work like that but I think it should be transparently work equally to the array. 
The name is lost during the link from List to array. I have to make sure that forwarding this does not cause problems in other cases, apart from that it is easy to change.



jan

unread,
Apr 16, 2013, 3:22:49 AM4/16/13
to sil...@googlegroups.com
Looks like we can call this a bug (in the List/Set bridge). I fixed it so now this test https://github.com/jbee/silk/blob/master/src/test/se/jbee/inject/bind/TestMultibindBinds.java works. 
You can take a look at the 3 commits https://github.com/jbee/silk/commits/ made on 15. April. to see the changes. It would work to apply them to 0.5 youself by just installing/binding a fixed version of the List/Set bridges. 
Reply all
Reply to author
Forward
0 new messages