Jhug nov11-google guice


Published on

My presentation at Java Hellenic Users Groups (JHUG) about Google Guice (November 2011)

Published in: Technology
  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Jhug nov11-google guice

  1. 1. Google Guice JHUG November 2011 Anastasopoulos Spyros winwasher@gmail.com
  2. 2. What is Google Guice @Simply A library that helps manipulate the object graph and write maintainable code @BuzzwordCompliant A dependency injector for modular java @Like The spring application context or J2EE CDI
  3. 3. The Object Graph A java program creates, wires and uses objects. // grep <pattern> public static void main(String[] args) throws Exception { BufferedReader bin = new BufferedReader(newInputStreamReader(System.in)); PrintWriter bout = new PrintWriter(new BufferedOutputStream(System.out)); Pattern p = Pattern.compile(args[0]); String line = null; while ((line = bin.readLine()) != null) { Matcher m = p.matcher(line); if (m.find()) bout.println(line); } }
  4. 4. The Object Graph Objects need the assistance of other objects to do their job. A program must ensure that an object is given references to the other objects it needs (its dependencies) before that object has to do anything. This leads to the object graph. Validator Service Storage Enhancer Logger Adapter
  5. 5. The Object Graph Out of the box the language supports only a single object - new, equals(), hash(), =, finalize() There is no support for the object graph with callbacks like - onCreation(), onReference(), onUse() The work to handle the object graph is left on the programmer. To make things more difficult, not all objects are the same. Some are expensive (DBConnection), some are for a lifetime(ApplicationMonitor), some can be reused (HttpConnection), some are immutable(Long), some are in flux (ConcurrentHashMap), some are scoped(HttpRequest), some are OS dependent(Socket) and so on... This leads to ...
  6. 6. Static References public void processAndStore(InputData data) { DataValidator dv = new NASDataValidator(); if (dv.areDataValid(data)) { AmazonS3Storage ds = new AmazonS3Storage(S3URL); ds.store(data); } else { FileStorage ds = new FileStorage("./data.txt", data); LogDataTransformer dt = Context.getDataTransformer(); logger.info("Invalid NAS Data: " + dt.transform(data)); } } ● tight coupling on implementation ● code not polymorphic ● cannot be reused in another context, all or nothing testing ● viral, easy to spread though code base ● dependencies are implicit, hidden in the code ● hard to maintain and refactor
  7. 7. Design Patterns to the rescue? ● Abstract Factory, Factory Method ● Object Pools, Object Caches, Lazy Loading ● Builder ● Prototype ● Service Locator ● Singleton Most design patterns are informal: described in prose; refer to by name, but must be implemented from scratch for each use (Peter Norvig) Remember static references are viral while design patterns are just convention (Hint: maintainability)
  8. 8. Design Patterns to the rescue? Not me ● Factory ○ how to get it? global, use locator, use metafactory etc ○ code now depends on implementation of factory ○ boilerplate code. We will need many factories ○ reuse in a different context is difficult (testing) ○ dependencies are still hidden in the implementation ● Service Locator ○ how to configure it? ○ how to ensure availability? ○ hard to tell what services an object will need (no tools) ○ looses some type safety
  9. 9. Dependency Injection (DI) A style of programming that promises ● less boilerplate code ● easy reuse and maintainance ● easy unit testing The leap of faith is that an object doesn't do anything to resolve its dependencies but assumes they will be resolved by someone else and passed to the object by the time it will have to do some work. The resolution is done either by user code or by a framework (Guice, Spring, CDI etc) The main benefits of DI are ● separation between behavior and dependency resolution ● dependencies are now exposed in the API
  10. 10. DI example Assuming that we have class Client { private Service service; public Client(Service service) { this.service = service;} public int doWork(int volume) { // uses service } } A user of Client Client cli = new Client(new ProductionService()); cli.doWork(); A unit test of Client Client cli = new Client(new MockService()); assertEquals(cli.doWork(10), 50);
  11. 11. DI with Spring Write an XML configuration file <beans> <bean id="service" class="com.services.ProductionService"/> <bean id="client" class="com.clients.DefaultClient"> <constructor-arg><ref bean="service"/></constructor-arg> </bean> </beans> Use it to create the injector, then get objects public static void main(String[] args) { ApplicationContext ctxt = new ClassPathXmlApplicationContext("applicationContext.xml"); Client cli = ctxt.getBean("client"); client.work(10); }
  12. 12. Google Guice ● Created and used by Google ● Releases 1.0 Mar 2007 - 2.0 May 2009 - 3.0 Mar 2011 ● At time of first release Spring did not meet their needs ○ no support for Java 5 features, generics and annotations ○ verbose XML configuration and inadequate tool support ○ XML is code ○ Spring vision was a comprehensive alternative to J2EE ● Guice went back to the basics ○ focus on dependency injection ○ support type safety, generics, annotations ○ ease of use, good error messages ○ maximum power-to-weight ratio of API
  13. 13. Why Guice? It is a matter of taste Spring is an excellent piece of software but like everything in the java world it has made configuration first priority. You can configure it in many ways to do many things implicit or explicit ● It does not enforce or suggest a one true way to use it. J2EE is the standard with all the pros and cons. ● Why do we need to standardize everything? Guice is just a tool that can help you build applications. It does not try to recreate the world and it does not try to dominate your application. ● Designed to support and favor a particular good code style
  14. 14. Applied Guice: the application interface Greeter { void greet(); } public class WelcomeGreeter implements Greeter { public void greet() { System.out.println("Welcomen"); } public class Main { private Greeter gt; void setGreeter(Greeter gt) { this.gt = gt; } public void doIt() { gt.greet(); } }
  15. 15. Applied Guice: the application Guicified interface Greeter { void greet(); } public class WelcomeGreeter implements Greeter { public void greet() { System.out.println("Welcomen"); } public class Main { private Greeter gt; @Inject void setGreeter(Greeter gt) { this.gt = gt; } public void doIt() { gt.greet(); } }
  16. 16. Applied Guice: the machinery public class AppModule extends AbstractModule { protected void configure() { bind(Greeter.class).to(WelcomeGreeter.class); } } public class Bootstrap { public static void main(String[] args) { Injector in = Guice.createInjector(new AppModule()); Main app = in.getInstance(Main.class); app.doIt(); } }
  17. 17. Applied Guice: first notes ● @Inject is the new new ● configuration involves creating bindings that is mappings between types and their implementations ● dependencies resolutions are based on types. ○ types are the natural currency of java (Bob Lee) ○ type safety -> usage, documentation, IDEs, refactoring ○ compare with spring which uses string identifiers ● dependencies bindings are grouped in modules ○ enhances java rudimentary module system ○ provides a unit of reuse. Programmer decides granularity ○ modules and applications are M:N ○ good practice: export interface of modules
  18. 18. Applied Guice: first facts ● configuration is in plain java only. No XML ○ XML is verbose, not type safe, not easily handled by tools, eventually becomes a configuration language (XBean, namespaces <Server> <Queue> <Listener> etc) and programmer looses insight of (a probably bad) API ○ java is a type safe language supported by good IDEs ○ A good design supports tools well does not need them ● Guice provides an injector not a container. It just gives you objects. There is not sleight of hand like life cycle callbacks, implicit calls start(), implicit wirings, object scanning etc
  19. 19. Applied Guice: first problem public class FarewellGreeter implements Greeter { public void greet() { System.out.println("Good byen"); } } // what does this public class Main private Greeter private Greeter print? { welcome; farewell; @Inject public void setWelcomeGreeter(Greeter gt) {this.welcome = gt;} @Inject public void setFarewellGreeter(Greeter gt) {this.farewell = gt;} public void doIt() { welcome.greet(); farewell.greet(); } }
  20. 20. Applied Guice: the club The previous snippet prints welcome 2 times. Guice does not know anything about FarewellGreeter, it is not a member of the club in Guice argo. So we add it to the module public class AppModule extends AbstractModule { protected void configure() { bind(Greeter.class).to(WelcomeGreeter.class); bind(Greeter.class).to(FarewellGreeter.class); } } we rerun the program and we get....
  21. 21. Applied Guice: Binding Annotations Exception in thread "main" com.google.inject.CreationException: Guice creation errors: 1) A binding to java.lang.Greeter was already configured at AppModule.configure(AppModule.java:6). at AppModule.configure(AppModule.java:7) Guice supports a single binding for a type in a single module. The solution is to use annotations which are type safe metadata embedded in a program.
  22. 22. Applied Guice: Binding Annotations First we create the annotations. Boilerplate code but IDE helps. @Retention(RetentionPolicy.RUNTIME) // by JDK @Target({ElementType.PARAMETER}) // by JDK @BindingAnnotation // by Guice public @interface Welcome {} @Retention(RetentionPolicy.RUNTIME) // by JDK @Target({ElementType.PARAMETER}) // by JDK @BindingAnnotation // by Guice public @interface Farewell {} Then we use them in conjuction with @Inject @Inject setWelcomeGreeter(@Welcome Greeter gt) { this.welcome = gt; } @Inject setFarewellGreeter(@Farewell Greeter gt) { this.farewell = gt; }
  23. 23. Applied Guice: Binding Annotations We update the module and run the program bind(Greeter.class).annotatedWith(Welcome.class).to(WelcomeGreeter.class); bind(Greeter.class).annotatedWith(Farewell.class).to(FarewellGreeter.class); And this time it runs and prints the correct messages. Binding Annotations ● A type safe alternative to convention with all the advantages ● Because they are specificed in compile time they describe flavors of implementation therefore they can be reused. ● Example @Cache @Blue @Eager @Mock @Transactional
  24. 24. Applied Guice: Providers "which dependency do you want?" "it depends!" Providers are used to provide objects manually. interface Provider<T> { T get(); } class TimeGreeterProvider implements Provider<Greeter> { Greeter get() { return new SmartGreeter(new Date()); } } bind(Greeter.class).toProvider(TimeGreeterProvider.class);
  25. 25. Applied Guice: Providers When to use a provider ● no access to source code so we cannot put @Inject ● need for multiple instances ● optional creation of objects, lazy loading ● context dependent instantiation Providers are full members of the club ● They can have @Inject if they have dependencies ● Providers are DI friendly ○ implement one when you have something to provide ○ have injected it to you when you must be provided with something
  26. 26. Applied Guice: Scopes Every time Guice must satisfy a dependency it creates a new instance of the object. Frequently we must reuse objects because they are either expensive to create or stateful. A scope is a policy for reusing injected instances. Out of the box Guice provides: ● @Singleton an instance for the application lifetime ● @SessionScoped an instance for the session lifetime ● @RequestScoped an instance for the request lifetime Usage is straightforward bind(Cart.class).to(ShoppingCart.class).in(SessionScoped.class); bind(Biller.class).toInstance(MyBiller.class).in(Singleton.class);
  27. 27. Google Guice: The big picture Type<T> Key<T> * N Injector Binding<T> * Scope Provider<T> ● A binding maps a type to an implementation ● A provider creates instances. ● A key uniquely identifies a binding ● A scope defines the lifecycle of a binding ● An annotation defines the flavor of a type Annotation
  28. 28. Google Guice: philosophy examples ● Extreme type safety ● AOP ● Environment
  29. 29. Extreme Type Safety Consider the following: // program public class Report { List<String> names; List<Long> ids; @Inject public Report(List<String> names, List<Long> ids) { this.names = names; this.ids = ids; } } // module bind(List.class).to(ArrayList.class);
  30. 30. Extreme Type Safety Guice fully understands generics 1) No implementation for java.util.List<java.lang.Long> was bound. while locating java.util.List<java.lang.Long> for parameter 1 at Report.<init>(Report.java:11) while locating Report 2) No implementation for java.util.List<java.lang.String> was bound. while locating java.util.List<java.lang.String> for parameter 0 at Report.<init>(Report.java:11) while locating Report
  31. 31. Extreme Type Safety Guice can handle erasure // module bind(new TypeLiteral<List<String>>(){}) .to(new TypeLiteral<ArrayList<String>>(){}); bind(new TypeLiteral<List<Long>>(){}) .to(new TypeLiteral<LinkedList<Long>>(){}); TypeLiteral<T> is provided by Guice. It is based on the work of Neal Gafter http://gafter.blogspot.com/2006/12/type-literals.html In a nutshell this is was Java 5 should have provided instead of Class<T>
  32. 32. AOP Guice implements a restricted (if we consider AspectJ) but simpler and practical AOP model, based on method interceptors. The configuration is in the same spirit as DI. bindInterceptor( Matcher<? super Class<?>> classMatcher, // class predicate Matcher<? super Method> methodMatcher, // method predicate MethodInterceptor... interceptor); MethodInteceptor is an interface from org.aopalliance as in Spring The injector enhances only objects with bindings. For a concrete class you must provide an untargetted binding bind(ServiceImpl.class);
  33. 33. AOP A real example from Guice Persistence Extension. Works by annotating methods or classes with @Transactional // class-level @Transacational bindInterceptor(annotatedWith(Transactional.class), any(), getTransactionInterceptor()); // method-level @Transacational bindInterceptor(any(), annotatedWith(Transactional.class), getTransactionInterceptor()); The transaction interceptor setups JPA entity manager, binds the current transaction to the thread, delegates to the method and finally commits on successful return and rolls back on exception
  34. 34. AOP Compare with Spring @Aspect public class BeforeExample { @Before("execution(* com.xyz.myapp.dao.*.*(..))") public void doAccessCheck() { // work } } Guice is simpler to configure but supports simple cases Spring has fully supports AOP but configuration is a major issue Guice AOP hasn't changed from the initial release
  35. 35. Environment Some examples from the Guice Javadocs. DI is viral with Guice. It stays simple and goes for maximum power-to-weight API SpringIntegration: public static Provider<T> fromSpring(Class<T> type, String name) Creates a provider which looks up objects from Spring using the given name. Expects a binding to org.springframework.beans.factory.BeanFactory JndiIntegration static <T> Provider<T> fromJndi<Class<T>, String name) Creates a provider which looks up objects in JNDI using the given name.Requires a binding to javax.naming.Context.
  36. 36. Google Guice: resources Web site with downloads, wiki, documentation, videos, blogs http://code.google.com/p/google-guice/ Talks I highly recommend the one by Bob Lee, the creator of Guice http://www.youtube.com/watch?v=l81T1AQWX84 Books Dependency Injection by Dhanji Prasanna (+1) Open Source Projects http://sitebricks.org a set of libraries for web development. Hint: Have a look to the web client. Guice style API
  37. 37. @JHUG @Inject List<Question> @Speaker Provider<Answers>