Guice MapBinder with list values… here is a solution to the problem.
Guice MapBinder with list values
I have a service that needs to inject mulitmap – Map<String, List<Enricher>>
public class EnrichService {
private Map<String, List<Enricher>> typeEnrichers;
@Inject
public EnrichService(Map<String, List<Enricher>> typeEnrichers) {
this.typeEnrichers = typeEnrichers;
}
public void enrich(Entity entity) {
List<Enricher> enrichers = typeEnrichers.get(entity.type);
//.. enriching entity with enrichers
}
}
class Entity {
String id;
String type = "shapedColorful";
String color;
String shape;
}
interface Enricher {
void enrich(Entity entity);
}
class ColorEnricher implements Enricher {
@Inject
private ColorService colorService;
public void enrich(Entity entity) {
entity.color = colorService.getColor(entity.id);
}
}
class ShapeEnricher implements Enricher {
@Inject
private ShapeService shapeService;
public void enrich(Entity entity) {
entity.shape = shapeService.getShape(entity.id);
}
}
I need help configuring typeEnrichers Binder in juice
This is what I was trying but stuck
bind(ColorService).to(ColorServiceImpl.class);
bind(ShapeService).to(ShapeServiceImpl.class);
MapBinder<RelationType, List<Enricher>> mapBinder = MapBinder.newMapBinder(
binder(),
new TypeLiteral<String>() {},
new TypeLiteral<List<Enricher>>() {});
mapBinder.addBinding("shapedColorful", to(/*how to bind list of Enrichers here?? */))
Any help, how do I bind (bind) such a multi-graph?
Solution
You are trying to mix MapBinder
with Multibinder
.
I recommend that you create a provider
for each MapBinder relationship. In fact, Multibinder itself is a List Provider
, specifically, its RealMultibinder
implementation is unfortunately private and forbidden. If it’s not package private, maybe we can use it this way. Most likely it won’t work anyway … IMHO, it would be fine.
bind(ColorService).to(ColorServiceImpl.class);
bind(ShapeService).to(ShapeServiceImpl.class);
MapBinder<RelationType, List<Enricher>> mapBinder = MapBinder.newMapBinder(
binder(),
new TypeLiteral<String>() {},
new TypeLiteral<List<Enricher>>() {});
mapBinder.addBinding("shapedColorful", toProvider(Multibinder.newSetBinder(this.binder(), Enricher.class).addBinding().to(ColorService.class).addBinding().to( ShapeService.class).asEagerSingleton()))
You can still create and use providers:
public class ShapeColorfulProvider implements Provider<List<Enricher>> {
@Inject private ColorService colorService;
@Inject private ShapeService shapeService;
public List<Enricher> get() {
return Lists.newArrayList(colorService,shapeService);
}
}
And then
mapBinder.addBinding("shapedColorful", toProvider(ShapeColorfulProvider.class))