Sapphire Gimlets


Published on

Gin and Guince

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

Sapphire Gimlets

  1. 1. Sapphire Gimlets* <br />Robert Cooper<br /><br />*no onions<br />
  2. 2. Guice<br />Dependency Injection<br />Java Source configuration<br />Convention over configuration<br />Fast<br />
  3. 3. Gin<br />Guice for GWT apps<br />100% Client Side<br />Based on Deferred Binding, so some limitations<br />Fast<br />
  4. 4. Guicevs Spring<br />Spring Config Hell<br />Promise of simplicity<br />Ever expanding config files<br />Lots of subprojects<br />Becomes more brittle, in that it becomes harder to extract code for reuse.<br />
  5. 5. Guicevs Spring<br />Guice<br />Java Source “configuration”<br />Convention over configuration.<br />Annotation based<br />Opposite of Spring in defaults<br />Prefer constructor injection<br />Prefer new instances (“Prototype”) over Singletons<br />Provider<T> interface encourages mixing scopes<br />Type Safe – you got static typing, use it!<br />
  6. 6. Guice 101<br />Basic Annotations<br />@Inject<br />@ImplementedBy/@ProvidedBy<br />@[Scope]<br />@Named<br />
  7. 7. Guice 101<br />public class MyClass{<br /> private final MyService service;<br /> @Injectpublic MyClass(finalMyService service){this.service = service;}<br /> public String sayHelloToUser(){ return this.service.hello();}<br />}<br /> @ImplementedBy(MyServiceImpl.class)public interface MyService{ public String hello();}<br />
  8. 8. Guice 101<br />@Singleton<br />public class MyServiceImpl implements MyService {<br /> private final Provider<MySessionObject> sessionProvider;<br /> public MyServiceImpl(final Provider<MySessionObject> sessionProvider){<br />this.sessionProvider = sessionProvider;<br /> }<br /> @Override<br /> public String hello() {<br /> return "Hello, "+sessionProvider.get().getName() +"!";<br /> }<br />}<br />
  9. 9. Guice 101<br />import;<br />@SessionScoped<br />public class MySessionObject {<br /> private String name;<br /> public String getName(){<br /> return;<br /> }<br /> public void setName(String name){<br /> = name;<br /> }<br />}<br />
  10. 10. Guice 101<br />What have we done?<br />MyClass gets a MyService injected.<br />MyService is implemented by MyServiceImpl as a Singleton<br />MyServiceImpl gets a Provider<MySessionObject><br />The hello() method fetches the Session scoped MySession object, and says Hello!<br />
  11. 11. Guice 101<br />@ImplementedBy provides defaults for any interface (You don’t need to config these if the default is OK)<br />Injection is type safe on constructors (Unit tests have obvious requirements)<br />Scope annotations (@SessionScoped, @Singleton) provide defaults.<br />Provider<T> hides the scope shift from the Singleton service in a single thread method.<br />
  12. 12. Guice 101<br />Making it work on the web…<br />
  13. 13. Guice 101<br />public class GuiceContextListener extends GuiceServletContextListener {<br /> @Override<br /> protected Injector getInjector() {<br /> return Guice.createInjector(<br /> new Module() {<br /> public void configure(Binder binder) {<br /> // Oh Wait, we don’t need anything here!<br /> }<br /> }<br /> }, new ServletModule() {<br /> @Override<br /> protected void configureServlets() {<br />this.serve(“/myPath/*”).with(MyServlet.class);<br /> }<br /> }<br /> }<br />}<br />
  14. 14. Guice 101<br />Warning! Overly complicated coming up!<br />
  15. 15. Guice 101<br />@Singleton<br />public class MyServlet extends HttpServlet{<br /> private final Provider<MySessionObject> sessionProvider;<br /> private final MyClassmyClass;<br /> @Inject<br /> public MyServlet(final Provider<MySessionObject> sessionProvider, MyClassmyClass){<br />this.sessionProvider = sessionProvider;<br />this.myClass = myClass;<br /> }<br /> @Override<br /> public void doGet(HttpServletRequestreq, HttpServletResponse res) throws IOException {<br />this.sessionProvider.get().setName(req.getParameter("name"));<br />res.getWriter().println(myClass.hello());<br /> }<br />}<br />
  16. 16. Guice 101<br />So this is interesting. What happened there?<br />The SessionScoped object was created, and set on the session.<br />MyClass was created one off for injection into the servlet. Since it wasn’t a Provider<MyClass> it was implicitly @Singleton with the servlet<br />But since the MyClass implementation used a provider, it ended up performing a singleton-session scoped op.<br />
  17. 17. Guice 101<br />What else?<br />Servlets, Filters, etc must always be @Singleton of course, this just makes sense.<br />They can *still* get anything injected into them.<br />You need to add your boostrapGuiceContextListener to your web.xml<br />For Servlet < 3.0 you need to add a to /*<br />
  18. 18. Guice 201<br />Why does this rock? (Hint GWT stuff…) <br />Can you say RemoteServiceServlet?<br />No more calls to getThreadLocalX() for servlet context stuff. Just use Provider<T><br />
  19. 19. Guice 201: Warp<br />The Warp-* projects provide a lot of utility ops for Guice:<br />@Transactional scope<br />Transaction per Request<br />Some stuff not dissimilar to Spring WebFlow or Stripes.<br />
  20. 20. Guice 201: More Config<br />@Named lets you provide named values in your configuration. (You can also create custom annotations)<br />You can also use @Provides for factory methods in your modules for simple providers<br />@Provides <br />public Connection getConnection(@Named(“jdbc-url”) String jdbcUrl) {<br />DriverManager.forName(whatever);<br />DriverManager.getConnection(jdbcUrl);<br />}<br />
  21. 21. Guice 201: More Config<br />binder.bind(String.class).annotatedWith(Names.named(“jdbc-url”)).toInstance(“jdbc:mysql://localhost/mydb”);<br />Note: @Provides methods could do JNDI lookups, or get other stuff. (This is a stupid example!)<br />
  22. 22. Of Junipers and Bathtubs<br />Gin is Google Guice for GWT client side apps.<br />Based on DeferrredBinding.<br />Certain features lost:<br />Binding .toInstance() on any module<br />Anonymous Provider<T> can’t be done (@Provides is *kinda* OK)<br />Scoping needs to be by hard class reference.<br />
  23. 23. Of Junipers and Bathtubs<br />That is.. in(Singleton.class) not .asEagerSingleton() or with @Singleton<br />Gin seems both stupid and too smart.<br />Binding a RemoteServiceAsync class works out of the box…<br />Unless you want to do @Provides<br />Gin created classes are new Class() not GWT.create(Class.class); -- except for RemoteServiceAsync, which is a special scope.<br />
  24. 24. Gin 101<br />@GinModules(MyGinModule.class)<br />public interface Injector extends Ginjector {<br /> public static final Injector INSTANCE = GWT.create(Injector.class);<br /> public MyStartupClassstartupClass();<br />}<br />public class Module extends AbstractGinModule {<br /> @Override<br /> protected void configure() {<br />this.bind(Resources.class)<br /> .toProvider(ResourcesProvider.class)<br /> .in(Singleton.class)<br /> }<br />}<br />public static class ResourcesProvider implements Provider<Resources> {<br />@Override<br /> public Resources get() {<br /> return GWT.create(Resources.class);<br /> }<br />}<br />
  25. 25. Gin 101<br />Does this step on the toes of DeBi? <br />OK, maybe a little bit. Sure you could do a singleton Resources.INSTANCE but injection makes Unit testing without dropping into GWTTestCase more frequent. (Read: much, much faster)<br />This reserves DeBi for what it is best for: local environment specific code.<br />
  26. 26. Gin 201<br />What can’t you do with Gin?<br />Remember your Injector.INSTANCE is compile-time:<br />No “toInstance()” bindings… ever.<br />No “toProvider(AnonymousProvider(){})” providers need to be public scoped static classes at the least.<br />Gin treats RemoteServiceAsync specially. You can do a provider, but if you try @Provides methods in your GinModule classes, you will get a duplicate declaration error.<br />
  27. 27. Gin 201<br />All this aside, stacked with DeBi, Gin can rock rough and stuff with its Afro Puffs.<br />Replace your Startup call with a Sync method.<br />Replace your Async classes with thing that talk to local storage.<br />Automagically retry onFailure() methods on network errors while your uses if offline.<br />
  28. 28. Way way more<br />Warp-* is some great stuff:<br /><br /><br />Guice with JAX-WS<br />(Strangely harder than JAX-RS)<br />