We are in JavaGroupBrewery, which contains JavaBeerFaucet , which can be connected to a BeerKeg,
and any Customer can come and order some Beer.
Well, lets have a closer look...
in JAVA of course!
Can be found: https://github.com/xbaran/guice-presentation
traditionally low level modules define how higher level modules interface with them
Can be found: https://github.com/xbaran/guice-presentation
public class JavaGroupBrewery {
private JavaBeerFaucet javaBeerFaucet;
private Boolean openStatus = Boolean.FALSE;
public JavaGroupBrewery() {
buildBrewery();
this.javaBeerFaucet = new JavaBeerFaucet();
}
public void openBrewery() { ... }
public void closeBrewery() { ... }
public Boolean isOpen() { ... }
public JavaBeer orderBeer() {
try {
return this.javaBeerFaucet.pourBeer();
} catch (JavaBeerKeg.EmptyKegException e) {
this.javaBeerFaucet.replaceEmptyKeg(new JavaBeerKeg());
return orderBeer();
}
}
public JavaBeer orderSmallBeer() { ... }
private void cleanUp(JavaBeerFaucet javaBeerFaucet) { ... }
private void buildBrewery() { ... }
}
public class JavaBeerFaucet { private JavaBeerKeg beerKeg;
public JavaBeerFaucet() { this.beerKeg = new JavaBeerKeg(); } public void replaceEmptyKeg(JavaBeerKeg javaBeerKeg) { this.beerKeg = javaBeerKeg; } public JavaBeer pourBeer() throws JavaBeerKeg.EmptyKegException { return beerKeg.pull(0.5F); }
public class JavaBeerKeg {
private float capacity;
public JavaBeerKeg() {
this.capacity = 50.0F;
}
public JavaBeer pull(float amount) throws EmptyKegException {
if((capacity - amount) < 0) throw new EmptyKegException();
this.capacity = this.capacity - amount;
return new JavaBeer();
}
public World() { JavaCustomer Milan = new JavaCustomer("Milan"); JavaCustomer Peter = new JavaCustomer("Peter"); JavaCustomer Jaro = new JavaCustomer("Jaro"); JavaGroupBrewery brewery = new JavaGroupBrewery();
brewery.openBrewery(); Milan.goGetSomeBeer(brewery); Peter.goGetSomeBeer(brewery); Jaro.goGetSomeBeer(brewery); Peter.goGetSomeBeer(brewery); brewery.closeBrewery(); Peter.goGetSomeBeer(brewery); Peter.goGetSomeBeer(brewery); }
with IoC high level modules define interfaces that lower level modules should implement
public interface Brewery {
void openBrewery();
void closeBrewery();
Boolean isOpen();
Beer orderBeer();
Beer orderSmallBeer();
}
public interface BeerFaucet {
public void replaceEmptyKeg(BeerKeg beerKeg);
public Beer pourBeer() throws BeerKeg.EmptyKegException;
}
public interface BeerKeg {
Beer pull(float amount) throws EmptyKegException;
public class EmptyKegException extends Throwable {};
}
public interface Beer {
Boolean isStrong();
String getBrand();
}
public class SimpleBrewery implements Brewery { protected BeerFaucet beerFaucet; protected BeerKegFactory beerKegFactory; protected Boolean openStatus = Boolean.FALSE; public SimpleBrewery(BeerFaucet beerFaucet, BeerKegFactory beerKegFactory) { buildCoffeeShop(); this.beerFaucet = beerFaucet; this.beerKegFactory = beerKegFactory; }
public Beer orderBeer() { try { return beerFaucet.pourBeer(); } catch (BeerKeg.EmptyKegException e) { beerFaucet.replaceEmptyKeg(beerKegFactory.orderBeerKeg()); return orderBeer(); } } public void openBrewery() {...} public void closeBrewery() {...} public Boolean isOpen() {...} private void cleanUp(BeerFaucet beerFaucet) {...} private void buildCoffeeShop() {...}
public class SimpleBeerFaucet implements BeerFaucet {
private BeerKeg beerKeg;
public SimpleBeerFaucet(BeerKeg beerKeg) {
this.beerKeg = beerKeg;
}
public abstract class SimpleBeerKeg implements BeerKeg {
public SimpleBeerKeg(float capacity) { this.capacity = capacity; } @Override public Beer pull(float amount) throws EmptyKegException { if((capacity - amount) < 0) throw new BeerKeg.EmptyKegException(); this.capacity = this.capacity - amount; return createBeer(); } protected abstract Beer createBeer(); }
public class GenericBeerKeg extends SimpleBeerKeg {
private BeerFactory beerFactory;
public GenericBeerKeg(float capacity, BeerFactory beerFactory) {
this.beerFactory = beerFactory;
}
protected Beer createBeer() {
return beerFactory.get();
};
}
new BeerFactory(JavaBeer.class)
public Beer get() {
try {
return beerClass.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
public World() { BeerKegFactory javaBeerKegFactory = new SimpleBeerKegFactory(50, JavaBeer.class);
Brewery javaPivarna = new SimpleBrewery( new SimpleBeerFaucet(javaBeerKegFactory.orderBeerKeg()), javaBeerKegFactory); Customer Milan = new CommonCustomer("Milan"); Customer Peter = new CommonCustomer("Peter", new NeverGoHomeStrategy()); Customer Jaro = new CommonCustomer("Jaro", new PesimisticDrinkingStrategy(), new TimeToGoHomeStrategy()); javaPivarna.openBrewery(); Milan.goGetSomeBeer(zamockyBrewery); Milan.goGetSomeBeer(javaPivarna); Peter.goGetSomeBeer(zamockyBrewery); Jaro.goGetSomeBeer(zamockyBrewery); zamockyBrewery.closeBrewery(); javaPivarna.closeBrewery(); }
public class GuicedBrewery extends SimpleBrewery {
@Inject public GuicedBrewery(BeerFaucet beerFaucet, BeerKegFactory beerKegFactory) { super(beerFaucet, beerKegFactory); }}
public class SimpleBrewery implements Brewery {
protected final BeerFaucet beerFaucet; protected final BeerKegFactory beerKegFactory;
}
Method injection
sets dependencies into a new or existing instance
public class GuicedBrewery extends SimpleBrewery {
@Inject public void setBeerFaucet(BeerFaucet beerFaucet) {
this.beerFaucet = beerFaucet;
}
public class GuicedBrewery extends SimpleBrewery {
@Inject protected BeerFaucet beerFaucet; @Inject protected BeerKegFactory beerKegFactory;
public GuicedBrewery() { super(beerFaucet, beerKegFactory); //Cannot reference before supertype }}
public class SimpleWorldModule extends AbstractModule {
@Override
protected void configure() {
bind(Brewery.class).to(GuicedBrewery.class);
bind(BeerFaucet.class).to(GuicedBeerFaucet.class);
bind(BeerKeg.class).to(GuicedBeerKeg.class);
bindConstant().annotatedWith(Names.named("keg.capacity")).to(50F);
bind(Beer.class).to(JavaBeer.class);
}
public World() {
BeerKegFactory javaBeerKegFactory =
new SimpleBeerKegFactory(50, JavaBeer.class);
Brewery javaPivarna = new SimpleBrewery(
new impleBeerFaucet(javaBeerKegFactory.orderBeerKeg()),
javaBeerKegFactory);
com.google.inject.CreationException: Guice creation errors:
1) No implementation for me.baran.brewery.BeerKegFactory was bound.
while locating me.baran.brewery.BeerKegFactory
for parameter 1 at me.baran.brewery.GuicedBrewery.<init>(GuicedBrewery.java:15)
at me.baran.guice.SimpleWorldModule.configure(SimpleWorldModule.java:23)
public interface Provider<T> {
T get();
}
bind(Beer.class).to(JavaBeer.class);
bind(Beer.class).toProvider(JBeerProvider.class);//impl. Provider<Beer>
bind(Beer.class).toProvider(new Provider<Beer>() {
@Override
public Beer get() {
return new JavaBeer();
}
});
public class SimpleWorldModule extends AbstractModule {
@Override protected void configure() {...}
@Provides public BeerKegFactory providesBeerKegFactory(final Provider<BeerKeg> beerKeg) {
return new BeerKegFactory() { @Override public BeerKeg orderBeerKeg() { return beerKeg.get(); } }; }
Injector inj = Guice.createInjector(new SimpleWorldModule());
Brewery javaPub = inj.getInstance(Brewery.class);
BeerKegFactory javaBeerKegFactory = new SimpleBeerKegFactory(50, JavaBeer.class);
Brewery javaPivarna = new SimpleBrewery( new SimpleBeerFaucet(javaBeerKegFactory.orderBeerKeg()), javaBeerKegFactory);
[PilsnerBeer, KozelBeer, JavaBeer, CorgonBeer, SvijanyBeer]
protected void configure() { bind(Brewery.class).to(GuicedBrewery.class); bind(BeerFaucet.class).to(GuicedBeerFaucet.class); bind(BeerKeg.class).to(GuicedBeerKeg.class); bindConstant().annotatedWith(Names.named("keg.capacity")).to(50F); bind(Beer.class).to(JavaBeer.class);
bind(Brewery.class).to(GuicedBrewery.class); bind(Beer.class).to(PilsnerBeer.class);
}
1) A binding to me.baran.brewery.blueprint.Beer was already configured at me.baran.guice.SimpleWorldModule.configure(SimpleWorldModule.java:30).
at me.baran.guice.SimpleWorldModule.configure(SimpleWorldModule.java:33)
@BindingAnnotation
@Target({ FIELD, PARAMETER, METHOD })
@Retention(RUNTIME)
public @interface BreweryPub {
String value();
}
bind(Brewery.class) .annotatedWith(new BreweryPubImpl("Java")).to(GuicedBrewery.class);
bind(Beer.class) .annotatedWith(new BreweryPubImpl("Java")).to(JavaBeer.class); bind(Brewery.class) .annotatedWith(new BreweryPubImpl("Pilsner")).to(GuicedBrewery.class); bind(Beer.class) .annotatedWith(new BreweryPubImpl("Pilsner")).to(PilsnerBeer.class);
@Inject
public GuicedBeerKeg(
@Named("keg.capacity") float capacity,
@BreweryPub("Java") Provider<Beer> beerProvider) {
super(capacity);
this.beerProvider = beerProvider;
}
class PrivateBreweryModule extends PrivateModule {
private final Annotation pubAnnotation;
private final Class<? extends Beer> beerClass;
PrivateBreweryModule(Class<? extends Beer> beerClass) {
this.pubAnnotation = new BreweryPubImpl(beerClass.getSimpleName());
this.beerClass = beerClass;
}
@Override
protected void configure() {
bind(Brewery.class).annotatedWith(pubAnnotation).to(GuicedBrewery.class);
bind(BeerFaucet.class).to(GuicedBeerFaucet.class);
bind(BeerKeg.class).to(GuicedBeerKeg.class);
bindConstant().annotatedWith(Names.named("keg.capacity")).to(50F);
bind(Beer.class).to(beerClass);
expose(Brewery.class).annotatedWith(pubAnnotation);
}
@Provides
public BeerKegFactory providesBeerKegFactory(final Provider<BeerKeg> beerKegProvider) {
return new BeerKegFactory() {
@Override
public BeerKeg orderBeerKeg() {
return beerKegProvider.get();
}
};
}
}
1) Unable to create binding for me.baran.brewery.blueprint.Brewery annotated with BreweryPub(value=JavaBeer). It was already configured on one or more child injectors or private modules (PrivateBreweryModule.java:35)
If it was in a PrivateModule, did you forget to expose the binding?
ComplexWorldModuleTest.getJavaPub(ComplexWorldModuleTest.java:31)
public class ComplexWorldModule extends AbstractModule {
@Override
protected void configure() {
install(new PrivateBreweryModule(PilsnerBeer.class));
install(new PrivateBreweryModule(KozelBeer.class));
install(new PrivateBreweryModule(JavaBeer.class));
install(new PrivateBreweryModule(ZamockyBeer.class));
}
@Inject public GuicedWorld( @BreweryPub("PilsnerBeer") Brewery pilsnerPub, @BreweryPub("KozelBeer") Brewery kozelPub, @BreweryPub("JavaBeer") Brewery javaPub, @BreweryPub("ZamockyBeer") Brewery zamockyPub ) { pilsnerPub.openBrewery(); kozelPub.openBrewery(); javaPub.openBrewery(); zamockyPub.openBrewery();
... and get the party started!!!
}
GuicedWorld world = Guice.createInjector(
new ComplexWorldModule())
.getInstance(GuicedWorld.class);
public class ComplexWorldModuleTest { @Test public void testComplexWorldInjection() throws Exception { Injector inj = Guice.createInjector(new ComplexWorldModule()); inj.injectMembers(this); Brewery pilsnerPub = inj.getInstance( Key.get(Brewery.class, new BreweryPubImpl("PilsnerBeer")));
Brewery javaPub = getJavaPub(); Assert.assertNotNull(javaPub); Assert.assertNotSame(javaPub,pilsnerPub); Assert.assertEquals("Java",javaPub.orderBeer().getBrand());
} @Inject public void getJavaPub(@BreweryPub("JavaBeer") Brewery javaPub) { this.javaPub = javaPub; } public Brewery getJavaPub() { return this.javaPub; };