Friday, April 13, 2018

Google Guice



When you annotate a method with @Provides the type of the object you want to inject is the same as the method return type. On the other hand when you use @CheckedProvides you can inject the provider not the object that the provider provides



https://github.com/google/guice/wiki/FrequentlyAskedQuestions
You can use a TypeLiteral to create the binding. TypeLiteral is a special class that allows you to specify a full parameterized type.
  @Override public void configure() {
    bind(new TypeLiteral<List<String>>() {}).toInstance(new ArrayList<String>());
  }
Alternately, you can use an @Provides method.
 @Provides List<String> providesListOfString() {
   return new ArrayList<String>();
 }

https://github.com/google/guice/wiki/JustInTimeBindings
https://softwareengineering.stackexchange.com/questions/284111/what-is-the-motivation-behind-the-implementedby-annotation-in-guice?rq=1
having your interfaces depend on your implementation can be a code smell;

Use @ImplementedBy carefully; it adds a compile-time dependency from the interface to its implementation.
Such dependency may not be a problem in many cases but I personally see it as a code smell.
What use cases make the @ImplementedBy annotation worth using?
One possible way seems to be to employ it in the code of a library or framework. As described in the docs, the annotation can provide a default binding easily overriden by an explicit one.
If a type is in both a bind() statement (as the first argument) and has the @ImplementedByannotation, the bind() statement is used. The annotation suggests a default implementation that can be overridden with a binding.

https://github.com/google/guice/wiki/InjectingProviders
Use providers when you need multiple instances of the same type. Suppose your application saves a summary entry and a details when a pizza charge fails. With providers, you can get a new entry whenever you need one.
public class LogFileTransactionLog implements TransactionLog {

  private final Provider<LogFileEntry> logFileProvider;

  @Inject
  public LogFileTransactionLog(Provider<LogFileEntry> logFileProvider) {
    this.logFileProvider = logFileProvider;
  }

  public void logChargeResult(ChargeResult result) {
    LogFileEntry summaryEntry = logFileProvider.get();
    summaryEntry.setText("Charge " + (result.wasSuccessful() ? "success" : "failure"));
    summaryEntry.save();

    if (!result.wasSuccessful()) {
      LogFileEntry detailEntry = logFileProvider.get();
      detailEntry.setText("Failure result: " + result);
      detailEntry.save();
    }
  }

Providers for lazy loading

Providers for Mixing Scopes

It is an error to depend on an object in a narrower scope. Suppose you have a singleton transaction log that needs on the request-scoped current user. Should you inject the user directly, things break because the user changes from request to request. Since providers can produce values on-demand, they enable you to mix scopes safely:
@Singleton
public class ConsoleTransactionLog implements TransactionLog {
  
  private final AtomicInteger failureCount = new AtomicInteger();
  private final Provider<User> userProvider;

  @Inject
  public ConsoleTransactionLog(Provider<User> userProvider) {
    this.userProvider = userProvider;
  }

  public void logConnectException(UnreachableException e) {
    failureCount.incrementAndGet();
    User user = userProvider.get();
    System.out.println("Connection failed for " + user + ": " + e.getMessage());
    System.out.println("Failure count: " + failureCount.incrementAndGet());
  }
http://gotolongjump.blogspot.com/2012/05/use-guice-simplest-way.html
With Foo as the root application-level binding, Guice already has full knowledge of Bar, Baz and Doh dependencies through reflection. It will report errors the same way as if you wrote explicit bindings for Bar and Baz. There is no need to manually "tell" Guice about them.

Main supposed benefits I've heard about preferring explicit bindings:
  1. "They give up-front error reporting." Again, this is simply irrelevant because implicit bindings do the same.
https://www.tutorialspoint.com/guice/guice_just_in_time_bindings
As bindings are defined in Binding Module, Guice uses them whenever it needs to inject dependencies. In case bindings are not present, it can attempt to create just-in-time bindings. Bindings present in binding module are called explicit bindings and are of higher precedence whereas just-in-time bindings are called implicit bindings. If both type of bindings are present, explicit bindings are considered for mapping.

Sr.No.Binding Type & Description
1Injectable Constructors
Non-private, No-argument constructors are eligible for just-in-time bindings. Another way is to annotate a constructor with @Inject annotation.
2@ImplementatedBy annotation
@ImplementatedBy annotation tells the guice about the implementation class. No binding is required in Binding Module in such a case.
3@ProvidedBy annotation
@ProvidedBy annotation tells the guice about the provider of implementation class. No binding is required in Binding Module in such a case
https://github.com/google/guice/wiki/JustInTimeBindings
https://www.hackingnote.com/en/versus/dagger-vs-guice

The key difference is that Guice is dependency injection at runtime, while Dagger is at compile time. This leads to the following comparisons:
  • Guice is base on reflection, while Dagger is generating extra code during compile-time; reflection is much slower than the pre-generated code.
  • Dagger is often used in Android development(reflection is even slower in Android)
  • Dagger has simpler APIs, and the stacktrace is easier to understand
https://github.com/google/guice/wiki/MinimizeMutability

Minimize mutability

Wherever possible, use constructor injection to create immutable objects. Immutable objects are simple, shareable, and can be composed
Method injection is most useful when you need to initialize an instance that is not constructed by Guice. Extensions like AssistedInject and Multibinder use method injection to initialize bound objects.
Field injection has the most compact syntax, so it shows up frequently on slides and in examples. It is neither encapsulated nor testable. Never inject final fields; the JVM doesn't guarantee that the injected value will be visible to all threads.
https://github.com/google/guice/wiki/InjectOnlyDirectDependencies
Inject only direct dependencies

Yes. You should always be using packages anyway. Use of the default package is discouraged for all but toy-sized programs.
I would typically expect to have a org.whatever.foo.some.feature package with a module class called FeatureModule (i.e. the name of the package + Module, not specifically FeatureModule).
Second, you can see unit testing the class through means of direct instantiation. This means we should do unit testing a class using direct instantiation, not Guice's Module? I think Guice is also useful for a testing, especially unit testing as they said.
It's just easier to see exactly what you're testing with if you directly inject the things you want to test with.
Sure, you can use guice, but there's a certain amount of "magic happens here" with the bindings, which can hide unexpected behaviour in the test.
This applies to unit testing; if you're doing integration testing, you likely do want to be using something close to how your production code does it, which may involve guice.

Keep constructors on Guice-instantiated classes as hidden as possible.
As a correction, simply limit the visibility of both your implementation classes, and their constructors. Typically package private is preferred for both, as this facilitates:
  • binding the class within a Module in the same package
  • unit testing the class through means of direct instantiation
Conditional logic in itself isn't too bad. But problems arise when configurations are untested. In this example, theInMemoryFooService is used for development and RemoteFooService is used in production. But without testing this specific case, it's impossible to be sure that RemoteFooServiceworks in the integrated application.
To overcome this, minimize the number of distinct configurations in your applications. If you split production and development into distinct modules, it is easier to be sure that the entire production codepath is tested. In this case, we split FooModule into RemoteFooModule and InMemoryFooModule. This also prevents production classes from having a compile-time dependency on test code.

The preferred solution is to not inject closable resources, but instead, objects that can expose short-lived closable resources that are used as necessary

Guice forbids null by default. It will refuse to inject null, failing with a ProvisionExceptioninstead. If null is permissible by your class, you can annotate the field or parameter with @Nullable. Guice recognizes any @Nullable annotation, like edu.umd.cs.findbugs.annotations.Nullable or javax.annotation.Nullable.

  • Modules start up, but they don't shut down. Should you open a database connection in your module, you won't have any hook to close it.
  • Modules should be tested. If a module opens a database as a course of execution, it becomes difficult to write unit tests for it.
  • Modules can be overridden. Guice modules support overrides, allowing a production service to be substituted with a lightweight or test one. When the production service is created as a part of module execution, such overrides are ineffective.
Rather than doing work in the module itself, define an interface that can do the work at the proper level of abstraction. 
After creating the Injector, we finish bootstrapping our application by starting its services. We also add shutdown hooks to cleanly release resources when the application is stopped.
  public static void main(String[] args) throws Exception {
    Injector injector = Guice.createInjector(
        new DatabaseModule(),
        new WebserverModule(),
        ...
    );

    Service databaseConnectionPool = injector.getInstance(
        Key.get(Service.class, DatabaseService.class));
    databaseConnectionPool.start();
    addShutdownHook(databaseConnectionPool);

    Service webserver = injector.getInstance(
        Key.get(Service.class, WebserverService.class));
    webserver.start();
    addShutdownHook(webserver);
  }

https://www.tutorialspoint.com/guice/guice_provides_annotation
Guice provides a way to create bindings with complex objects using @provides method
@Provides methods can have parameters that are injected by Guice
https://stackoverflow.com/questions/28202882/guice-provides-methods-vs-provider-classes
The main advantage of @Provides is compactness, especially in comparison to anonymous inner Provider implementations. Note, however, that there might be a few cases where you'd want to favor Provider classes:
  • You can create your own long-lived Provider instances, possibly with constructor parameters, and bind keys to those instances instead of to class literals.
    bind(Foo.class).toProvider(new FooProvisioner("bar", "baz"));
  • If you're using a framework compatible with JSR 330 (javax.inject), you can easily bind to javax.inject.Provider classes or instances. com.google.inject.Provider extends that interface.
    bind(Foo.class).toProvider(SomeProviderThatDoesntKnowAboutGuice.class);
  • Your Provider may be complex enough to factor into its own class. Depending on how you've structured your tests, it may be easier to test your Provider this way.
  • Providers can extend abstract classes. It may not be easy or intuitive to do this with @Provides methods.
  • You can bind several keys to the same Provider directly. Each @Provides method produces exactly one binding, though you could bind other keys to the key (@Quux Foo here) and let Guice do a second lookup.
  • Providers are easy to decorate or wrap, if you wanted to (for instance) cache or memoize instances without using Guice scopes or bindings.
    bind(Foo.class).toProvider(new Cache(new FooProvisioner("bar", "baz")));

IMPORTANT: Though this is a good strategy for classes that Guice can't create, bear in mind that Guice can automatically create and inject a Provider<T> for any T that you bind in any way, including to a class name, key, or instance. No need to create an explicit provider unless there's actual logic of your own involved.


https://github.com/google/guice/wiki/ProvidesMethods

@Provides Methods

When you need code to create an object, use an @Provides method. The method must be defined within a module, and it must have an @Provides annotation. The method's return type is the bound type. Whenever the injector needs an instance of that type, it will invoke the method.
public class BillingModule extends AbstractModule {
  @Override
  protected void configure() {
    ...
  }

  @Provides
  TransactionLog provideTransactionLog() {
    DatabaseTransactionLog transactionLog = new DatabaseTransactionLog();
    transactionLog.setJdbcUrl("jdbc:mysql://localhost/pizza");
    transactionLog.setThreadPoolSize(30);
    return transactionLog;
  }
}
If the @Provides method has a binding annotation like @PayPal or @Named("Checkout"), Guice binds the annotated type. Dependencies can be passed in as parameters to the method. The injector will exercise the bindings for each of these before invoking the method.


  @Provides @PayPal
  CreditCardProcessor providePayPalCreditCardProcessor(
      @Named("PayPal API key") String apiKey) {
    PayPalCreditCardProcessor processor = new PayPalCreditCardProcessor();
    processor.setApiKey(apiKey);
    return processor;
  }

https://www.baeldung.com/guice
The Module is the basic unit of definition of bindings (or wiring, as it’s known in Spring).
Guice has adopted a code-first approach for dependency injection and management so you won’t be dealing with a lot of XML out-of-the-box.
Another incarnation of this mechanism is the named binding. Consider the following variable declaration:
1
2
@Inject @Named("DefaultCommunicator")
Communicator communicator;
For this, we will have the following binding definition:
1
2
3
4
5
6
@Override
protected void configure() {
    bind(Communicator.class)
      .annotatedWith(Names.named("DefaultCommunicator"))
      .to(Communicator.class);
}
This binding will provide an instance of Communicator to a variable annotated with the @Named(“DefaultCommunicator”) annotation.
You’ll notice the @Inject and @Named annotations appear to be loan annotations from JavaEE’s CDI, and they are. They are in the com.google.inject.* package

You can also inject a dependency that doesn’t have a default no-arg constructor using constructor binding:
1
2
3
4
5
6
7
8
public class BasicModule extends AbstractModule {
  
    @Override
    protected void configure() {
        bind(Boolean.class).toInstance(true);
        bind(Communication.class).toConstructor(
          Communication.class.getConstructor(Boolean.TYPE));
}
The snippet above will inject an instance of Communication using the constructor that takes a boolean argument. We supply the true argument to the constructor by defining an untargeted binding of the Boolean class.
This untargeted binding will be eagerly supplied to any constructor in the binding that accepts a boolean parameter. With this approach, all dependencies of Communication are injected.
Another approach to constructor-specific binding is the instance binding, where we provide an instance directly in the binding:
1
2
3
4
5
6
7
8
public class BasicModule extends AbstractModule {
  
    @Override
    protected void configure() {
        bind(Communication.class)
          .toInstance(new Communication(true));
    }   
}
This binding will provide an instance of the Communication class wherever a Communicationvariable is declared.

Implicit Injections

Guice will implicitly inject some general purpose components like the Injector and an instance of java.util.Logger, among others.
The asEagerSingleton() call defines the singleton as eagerly instantiated.
In addition to these two scopes, Guice supports custom scopes as well as the web-only @RequestScoped and @SessionScoped annotations, supplied by JavaEE (there are no Guice-supplied versions of those annotations).


Anti-Pattern: Field Injection

https://liviutudor.com/2017/03/17/java-dependency-injection-and-a-useless-annotation/#sthash.4A7bMjA1.dpbs
Look closely here — there is no @PostConstruct or @PreDestroy kicking in! Wait, what???

As it turns out, Google Guice on its own does not provide any lifecycle management support — I found this post from ages ago mentioning it: https://groups.google.com/forum/#!topic/google-guice/0M3molmK4IU ; as a suggestion to the Guice peeps, it would be good if their (otherwise excellent) docco states this clearly too. Since they are referencing the java.annotation package, one is lead to believe they support this too — I definitely was.

OK, so note to all Guice users: unless you add other libraries in your app you do not get any lifecycle support such as @PostCreate and @PreDestroy in your app!
https://discursive.com/2011/01/26/creating-a-simple-google-guice-application/
we need to provide some hints to Guice to tell it what class to instantiate when it is asked for a particular interface.


    private static class AModule extends AbstractModule {
        @Override
        protected void configure() {
            bind(ObjectMapper.class).toInstance(new ObjectMapper()
                                                        .configure(SerializationFeature.INDENT_OUTPUT, true)
                                                        .configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false)
       ....
        }
    }

Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts