Google Guice
  Kirill Afanasjev
 Software Architect




       jug.lv
    Riga, Latvia
Overview

   Dependency Injection
   Why Guice
   Getting Guice
   Using Guice
   Advanced Guice
Code without DI

 public void sendButtonClicked() {
     String text = messageArea.getText();
     Validator validator = new MailValidator();
     validator.validate(text);
     MailSender sender = new MailSender();
     sender.send(text);
 }
Using factories

 public void sendButtonClicked() {
      String text = messageArea.getText();
      Validator validator = ValidatorFactory.get();
      validator.validate(text);
      MailSender sender = SenderFactory.get();
      sender.send(text);
  }
Testable now
 public void testSendButton() {
      MockSender mockSender = new MockSender();
      SenderFactory.setInstance(mockSender);
      MailForm form = new MailForm();
      form.getMessageArea().setText("Some text");
      form.sendButtonClicked();
      assertEquals("Some text", mockSender.getSentText());
      SenderFactory.clearInstance();
 }
Well, not really
 public void testSendButton() {
       MockSender mockSender = new MockSender();
       SenderFactory.setInstance(mockSender);
       try {
           MailForm form = new MailForm();
           form.getMessageArea().setText("Some text");
           form.sendButtonClicked();
           assertEquals("Some text", mockSender.getSentText());
       } finally {
           SenderFactory.clearInstance();
       }
   }
Dependency injection

 private Validator validator;
 private MailSender mailSender;


 public MailForm(Validator validator, MailSender mailSender) {
       this.validator = validator;
       this.mailSender = mailSender;
 }


 public void sendButtonClicked() {
 …..
Testing now

 public void testSendButton() {
      MockSender mockSender = new MockSender();
      Validator validator = new Validator();
      MailForm form = new MailForm(validator, mockSender);
      form.getMessageArea().setText("Some text");
      form.sendButtonClicked();
      assertEquals("Some text", mockSender.getSentText());
 }
Why DI frameworks

   Avoid boilerplate code
   AOP
   Integrate your DI with http session/request,
    data access APIs, e.t.c
   Separate dependencies configuration from
    code
   Makes life easier
What is Guice

   Open source dependency injection framework
   License : Apache License 2.0
   Developer : Google
Why Guice

   Java API for configuration
   Easier to use
   Line numbers in error messages
   Less overhead
   Less features, too
   DI in GWT client-side code (using GIN)
Getting Guice

   http://code.google.com/p/google-guice/
   http://mvnrepository.com/
   Small – 865 KB
   Version without AOP, suitable for Android –
    470KB
   Lacks fast reflection and line numbers in errors
Dependency injection with Guice

 private Validator validator;
 private MailSender mailSender;


 @Inject
 public MailForm(Validator validator, MailSender mailSender) {
      this.validator = validator;
      this.mailSender = mailSender;
 }
Creating instance of MailForm

 Injector injector =
     Guice.createInjector(new YourAppModule());
 MailForm mailForm = injector.getInstance(MailForm.class);
Bindings

 public class YourAppModule extends AbstractModule {
     protected void configure() {
                bind(MailService.class).to(MailServiceImpl.class);
                bind(Validator.class).to(ValidatorImpl.class);
     }
 }
Providers
 public class YourAppModule extends AbstractModule {
      protected void configure() {
                 bind(Validator.class).to(ValidatorImpl.class);
      }


      @Provides
      MailService getMailService() {
                 MailService service = new MailService();
                 return service;

      }
 ….
Injecting fields

 @Inject
 private Validator validator;
 @Inject
 private MailSender mailSender;


 public MailForm() {
 }
Injecting with setter methods

   private Validator validator;


   public MailForm() {
   }


   @Inject
   public void setValidator(Validator validator) {
               this.validator = validator;
   }
Optional injection

   Inject(optional=true)
   Ignores values for which no bindings are
    avalaible
   Possible with setter methods only
Bind instance

    protected void configure() {
         bind(Integer.class).annotatedWith(ThreadCount.cla
         ss).toInstance(4);
    }
    ..
    @ThreadCount
    int threadCount;

   IDE autocomplete, find usages e.t.c
Two implementations
  protected void configure() {
             bind(Validator.class).to(ValidatorImpl.class);
             bind(Validator.class).to(StrictValidatorImpl.class);
  }
Two implementations

Exception in thread "main" com.google.inject.CreationException:
Guice configuration errors:
1) Error at lv.jug.MailService.configure(YourAppModule.java:12):
A binding to lv.jug.MailService was already configured at
lv.jug.YourAppModule.configure(YourAppModule.java:11)
Two implementations
  protected void configure() {
                bind(Validator.class).to(ValidatorImpl.class);
                bind(Validator.class)
                   .annotatedWith(Strict.class)
                   .to(StrictValidatorImpl.class);
  }
  ….
  @Inject
  public MailForm(@Strict Validator validator) {
      this.validator = validator;
  }
Binding annotation

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@BindingAnnotation
public @interface Strict {}
Implicit binding

      @Inject
      public MailForm(
         @ImplementedBy(StrictValidator.class) Validator
         Validator validator,
         MailSender mailSender) {
       this.validator = validator;
       this.mailSender = mailSender;
  }
Static injection

   protected void configure() {
               bind(Validator.class).to(ValidatorImpl.class);
               requestStaticInjection(OurClass.class);
   }
   …
   …
  @Inject static Validator validator;
Scoping

  protected void configure() {
             bind(Validator.class).to(ValidatorImpl.class)
                   .in(Scopes.SINGLETON);
             bind(MailService.class).to(MailServiceImpl.class)
                   .asEagerSingleton();
  }
Multibindings

  Multibinder<Plugin> pluginBinder =
  Multibinder.newSetBinder(binder(), Plugin.class);
  pluginBinder.addBinding().to(SomePluginImpl.class);
  pluginBinder.addBinding().to(AnotherPluginImpl.class);
  ….

  @Inject Set<Plugin> plugins
Grapher

   Describe the object graph in detail
   Show bindings and dependencies from several
    classes in a complex application in a unified
    diagram
   Generates .dot file
Advanced Guice
   AOP
   Warp
   Google Gin
   Spring integration
   Using guice with Servlets
Why AOP

   Transaction handling
   Logging
   Security
   Exception handling
   e.t.c
AOP
   void bindInterceptor(
    Match <? super Class<?>> classMatcher,
    Matcher<? super Method> methodMatcher,
    MethodInterceptor... interceptors)


    public interface MethodInterceptor extends
    Interceptor {
        Object invoke (MethodInvocation invocation) throws
        Throwable
    }
AOP

   You can not match on private and final methods
    due to technical limitations in Java
   Only works for objects Guice creates
Warp

   http://www.wideplay.com/
   Eco-system for Google Guice
   Thin lightweight modules for Guice applications
   Persistence
   Transactions
   Servlets
Warp-persist

   Supports : Hibernate/JPA/Db4Objects
   Inject DAOs & Repositories
   Flexible units-of-work
   Declarative transaction management
    ( @Transactional )
   Your own AOP for transactions management
   @Finder(query="from Person")
Google Gin

   Automatic dependency injection for GWT client-
    side code
   Code generation
   Little-to-no runtime overhead, compared to
    manual DI
   Uses Guice binding language
   http://code.google.com/p/google-gin/
Spring integration

   http://code.google.com/p/guice-spring/
   @Named(”mySpringBean”)
JSR-330

   javax.inject
   @Inject
   @Named
   @Qualifier
   @Scope
   @Singleton
   e.t.c
   Supported by Guice, Spring, EJB
Using Guice with Servlets

   @RequestScoped
   @SessionScoped
   ServletModule
   serve(”/admin”).with(AdminPanelServlet.class)
   serve("*.html", "/my/*").with(MyServlet.class)
   filter(”/*”).through(MyFilter.class)
   @Inject @RequestParameters Map<String,
    String[]> params;
Thank you

   Questions ?

Jug Guice Presentation

  • 1.
    Google Guice Kirill Afanasjev Software Architect jug.lv Riga, Latvia
  • 2.
    Overview  Dependency Injection  Why Guice  Getting Guice  Using Guice  Advanced Guice
  • 3.
    Code without DI public void sendButtonClicked() { String text = messageArea.getText(); Validator validator = new MailValidator(); validator.validate(text); MailSender sender = new MailSender(); sender.send(text); }
  • 4.
    Using factories publicvoid sendButtonClicked() { String text = messageArea.getText(); Validator validator = ValidatorFactory.get(); validator.validate(text); MailSender sender = SenderFactory.get(); sender.send(text); }
  • 5.
    Testable now publicvoid testSendButton() { MockSender mockSender = new MockSender(); SenderFactory.setInstance(mockSender); MailForm form = new MailForm(); form.getMessageArea().setText("Some text"); form.sendButtonClicked(); assertEquals("Some text", mockSender.getSentText()); SenderFactory.clearInstance(); }
  • 6.
    Well, not really public void testSendButton() { MockSender mockSender = new MockSender(); SenderFactory.setInstance(mockSender); try { MailForm form = new MailForm(); form.getMessageArea().setText("Some text"); form.sendButtonClicked(); assertEquals("Some text", mockSender.getSentText()); } finally { SenderFactory.clearInstance(); } }
  • 7.
    Dependency injection privateValidator validator; private MailSender mailSender; public MailForm(Validator validator, MailSender mailSender) { this.validator = validator; this.mailSender = mailSender; } public void sendButtonClicked() { …..
  • 8.
    Testing now publicvoid testSendButton() { MockSender mockSender = new MockSender(); Validator validator = new Validator(); MailForm form = new MailForm(validator, mockSender); form.getMessageArea().setText("Some text"); form.sendButtonClicked(); assertEquals("Some text", mockSender.getSentText()); }
  • 9.
    Why DI frameworks  Avoid boilerplate code  AOP  Integrate your DI with http session/request, data access APIs, e.t.c  Separate dependencies configuration from code  Makes life easier
  • 10.
    What is Guice  Open source dependency injection framework  License : Apache License 2.0  Developer : Google
  • 11.
    Why Guice  Java API for configuration  Easier to use  Line numbers in error messages  Less overhead  Less features, too  DI in GWT client-side code (using GIN)
  • 12.
    Getting Guice  http://code.google.com/p/google-guice/  http://mvnrepository.com/  Small – 865 KB  Version without AOP, suitable for Android – 470KB  Lacks fast reflection and line numbers in errors
  • 13.
    Dependency injection withGuice private Validator validator; private MailSender mailSender; @Inject public MailForm(Validator validator, MailSender mailSender) { this.validator = validator; this.mailSender = mailSender; }
  • 14.
    Creating instance ofMailForm Injector injector = Guice.createInjector(new YourAppModule()); MailForm mailForm = injector.getInstance(MailForm.class);
  • 15.
    Bindings public classYourAppModule extends AbstractModule { protected void configure() { bind(MailService.class).to(MailServiceImpl.class); bind(Validator.class).to(ValidatorImpl.class); } }
  • 16.
    Providers public classYourAppModule extends AbstractModule { protected void configure() { bind(Validator.class).to(ValidatorImpl.class); } @Provides MailService getMailService() { MailService service = new MailService(); return service; } ….
  • 17.
    Injecting fields @Inject private Validator validator; @Inject private MailSender mailSender; public MailForm() { }
  • 18.
    Injecting with settermethods private Validator validator; public MailForm() { } @Inject public void setValidator(Validator validator) { this.validator = validator; }
  • 19.
    Optional injection  Inject(optional=true)  Ignores values for which no bindings are avalaible  Possible with setter methods only
  • 20.
    Bind instance protected void configure() { bind(Integer.class).annotatedWith(ThreadCount.cla ss).toInstance(4); } .. @ThreadCount int threadCount;  IDE autocomplete, find usages e.t.c
  • 21.
    Two implementations protected void configure() { bind(Validator.class).to(ValidatorImpl.class); bind(Validator.class).to(StrictValidatorImpl.class); }
  • 22.
    Two implementations Exception inthread "main" com.google.inject.CreationException: Guice configuration errors: 1) Error at lv.jug.MailService.configure(YourAppModule.java:12): A binding to lv.jug.MailService was already configured at lv.jug.YourAppModule.configure(YourAppModule.java:11)
  • 23.
    Two implementations protected void configure() { bind(Validator.class).to(ValidatorImpl.class); bind(Validator.class) .annotatedWith(Strict.class) .to(StrictValidatorImpl.class); } …. @Inject public MailForm(@Strict Validator validator) { this.validator = validator; }
  • 24.
  • 25.
    Implicit binding @Inject public MailForm( @ImplementedBy(StrictValidator.class) Validator Validator validator, MailSender mailSender) { this.validator = validator; this.mailSender = mailSender; }
  • 26.
    Static injection protected void configure() { bind(Validator.class).to(ValidatorImpl.class); requestStaticInjection(OurClass.class); } … … @Inject static Validator validator;
  • 27.
    Scoping protectedvoid configure() { bind(Validator.class).to(ValidatorImpl.class) .in(Scopes.SINGLETON); bind(MailService.class).to(MailServiceImpl.class) .asEagerSingleton(); }
  • 28.
    Multibindings Multibinder<Plugin>pluginBinder = Multibinder.newSetBinder(binder(), Plugin.class); pluginBinder.addBinding().to(SomePluginImpl.class); pluginBinder.addBinding().to(AnotherPluginImpl.class); …. @Inject Set<Plugin> plugins
  • 29.
    Grapher  Describe the object graph in detail  Show bindings and dependencies from several classes in a complex application in a unified diagram  Generates .dot file
  • 30.
    Advanced Guice  AOP  Warp  Google Gin  Spring integration  Using guice with Servlets
  • 31.
    Why AOP  Transaction handling  Logging  Security  Exception handling  e.t.c
  • 32.
    AOP  void bindInterceptor( Match <? super Class<?>> classMatcher, Matcher<? super Method> methodMatcher, MethodInterceptor... interceptors) public interface MethodInterceptor extends Interceptor { Object invoke (MethodInvocation invocation) throws Throwable }
  • 33.
    AOP  You can not match on private and final methods due to technical limitations in Java  Only works for objects Guice creates
  • 34.
    Warp  http://www.wideplay.com/  Eco-system for Google Guice  Thin lightweight modules for Guice applications  Persistence  Transactions  Servlets
  • 35.
    Warp-persist  Supports : Hibernate/JPA/Db4Objects  Inject DAOs & Repositories  Flexible units-of-work  Declarative transaction management ( @Transactional )  Your own AOP for transactions management  @Finder(query="from Person")
  • 36.
    Google Gin  Automatic dependency injection for GWT client- side code  Code generation  Little-to-no runtime overhead, compared to manual DI  Uses Guice binding language  http://code.google.com/p/google-gin/
  • 37.
    Spring integration  http://code.google.com/p/guice-spring/  @Named(”mySpringBean”)
  • 38.
    JSR-330  javax.inject  @Inject  @Named  @Qualifier  @Scope  @Singleton  e.t.c  Supported by Guice, Spring, EJB
  • 39.
    Using Guice withServlets  @RequestScoped  @SessionScoped  ServletModule  serve(”/admin”).with(AdminPanelServlet.class)  serve("*.html", "/my/*").with(MyServlet.class)  filter(”/*”).through(MyFilter.class)  @Inject @RequestParameters Map<String, String[]> params;
  • 40.
    Thank you  Questions ?