big modular java with guice

58

Upload: best-tech-videos

Post on 15-Nov-2014

131 views

Category:

Documents


2 download

DESCRIPTION

Learn how Google uses the fast, lightweight Guice framework to power some of the largest and most complex applications in the world. Supporting scores of developers, and steep testing and scaling requirements for the web, Guice proves that there is still ample room for a simple, type-safe and dynamic programming model in Java. This session will serve as a simple introduction to Guice, its ecosystem and how we use it at Google.Watch a video at http://www.bestechvideos.com/2009/06/07/google-i-o-2009-big-modular-java-with-guice

TRANSCRIPT

Page 1: Big Modular Java with Guice
Page 2: Big Modular Java with Guice

2

Big Modular Java™ with GuiceJesse WilsonDhanji Prasanna

May 28, 2009

Post your questions for this talk on Google Moderator:code.google.com/events/io/questionsClick on the Tech Talks Q&A link.

Page 3: Big Modular Java with Guice

How does my code change with Guice?

> Objects come to you• Instead of ʻnewʼ and factories

> Reusable modules> First-class scopes> Easier tests

• and more confidence> Less boilerplate

3photo courtesy of http://flickr.com/photos/xero79/378837837

Page 4: Big Modular Java with Guice

Overview

> Example• Ugh, factories arenʼt fun

> Using Guice• @Inject is the new new

> Leveraging Guice• A tour of extensions and advanced features

4

Page 5: Big Modular Java with Guice

Exampletweet tweet

5

> Setting the stage> Constructors> Factories> Dependency Injection

• by hand• with Guice

photo courtesy ofhttp://flickr.com/photos/jessicafm/62271212

Page 6: Big Modular Java with Guice

Code you might writeA tweets client public void postButtonClicked() {

String text = textField.getText();

if (text.length() > 140) {

Shortener shortener = new TinyUrlShortener();

text = shortener.shorten(text);

}

if (text.length() <= 140) {

Tweeter tweeter = new SmsTweeter();

tweeter.send(text);

textField.clear();

}

}

6

Page 7: Big Modular Java with Guice

Calling Dependenciesʼ Constructors Directly

photo courtesy of http://flickr.com/photos/salford_ian/3134250986

Page 8: Big Modular Java with Guice

public void postButtonClicked() {

String text = textField.getText();

if (text.length() > 140) {

Shortener shortener = new TinyUrlShortener();

text = shortener.shorten(text);

}

if (text.length() <= 140) {

Tweeter tweeter = new SmsTweeter();

tweeter.send(text);

textField.clear();

}

}

Getting dependencies via their constructors...calling new directly doesnʼt afford testing

8

We post to tinyurl.com and send an SMS for each test! This is neither fast nor reliable.

Page 9: Big Modular Java with Guice

Getting Dependencies from Factories

photo courtesy of http://flickr.com/photos/abulic_monkey/130899453

Page 10: Big Modular Java with Guice

public void postButtonClicked() {

String text = textField.getText();

if (text.length() > 140) {

Shortener shortener = ShortenerFactory.get();

text = shortener.shorten(text);

}

if (text.length() <= 140) {

Tweeter tweeter = TweeterFactory.get();

tweeter.send(text);

textField.clear();

}

}

Getting dependencies from factories

10

Page 11: Big Modular Java with Guice

public class TweeterFactory {

private static Tweeter testValue;

public static Tweeter get() {

if (testValue != null) {

return testValue;

}

return new SmsTweeter();

}

public static void setForTesting(Tweeter tweeter) {

testValue = tweeter;

}

}

Implementing the factoryall of this boilerplate slows you down. Ugh!

11

We still have to write a factory for the URL shortener.

Page 12: Big Modular Java with Guice

Factory dependency graphthe static dependency causes monolithic compiles

12

TweetClient

TweeterFactory

SmsTweeter

depends

depends

Page 13: Big Modular Java with Guice

public void testSendTweet() {

MockTweeter tweeter = new MockTweeter();

TweeterFactory.setForTesting(tweeter);

try {

TweetClient tweetClient = new TweetClient();

tweetClient.getEditor().setText("Hello!");

tweetClient.postButtonClicked();

assertEquals("Hello!", tweeter.getSent());

} finally {

TweeterFactory.setForTesting(null);

}

}

Testing with a factorydonʼt forget to clean up afterwards!

13

Page 14: Big Modular Java with Guice

Dependency Injection (DI) by hand

photo courtesy of http://flickr.com/photos/dan4th/1657850829

Page 15: Big Modular Java with Guice

public class TweetClient {

private final Shortener shortener;

private final Tweeter tweeter;

public TweetClient(Shortener shortener, Tweeter tweeter) {

this.shortener = shortener;

this.tweeter = tweeter;

}

public void postButtonClicked() {

...

if (text.length() <= 140) {

tweeter.send(text);

textField.clear();

}

Dependency injection by handobjects come to you

15

Dependency Injection:rather than looking it up, get it passed in.

Page 16: Big Modular Java with Guice

public void testSendTweet() {

MockShortener shortener = new MockShortener();

MockTweeter tweeter = new MockTweeter();

TweetClient tweetClient

= new TweetClient(shortener, tweeter);

tweetClient.getEditor().setText("Hello!");

tweetClient.postButtonClicked();

assertEquals("Hello!", tweeter.getSent());

}

Testing with dependency injectionno cleanup required

16

Page 17: Big Modular Java with Guice

public class TweetClientFactory {

private static TweetClient testValue;

public static TweetClient get() {

if (testValue != null) {

return testValue;

}

Shortener shortener = ShortenerFactory.get();

Tweeter tweeter = TweeterFactory.get();

return new TweetClient(shortener, tweeter);

}

Where does the dependency go?ugh, you still have to write boilerplate code to build stuff

17

DI motto:Push dependencies from the core to the edges

Page 18: Big Modular Java with Guice

Where does the dependency go?your application code sheds its heavyweight dependencies

18

TweetClient

SmsTweeterTinyUrlShortener

depends

creates

TweeterFactoryShortenerFactory

dependsTweetClientFactory

Page 19: Big Modular Java with Guice

Dependency Injection with Guice

photo courtesy of http://flickr.com/photos/randysonofrobert/347327376

Page 20: Big Modular Java with Guice

Dependency injection with Guice

20

TweetClient

SmsTweeterTinyUrlShortener

depends

createsInjector

uses

TweetModule

Page 21: Big Modular Java with Guice

import com.google.inject.AbstractModule;

public class TweetModule extends AbstractModule {

protected void configure() {

bind(Tweeter.class).to(SmsTweeter.class);

bind(Shortener.class).to(TinyUrlShortener.class);

}

}

Configuring the injector using modules

21

Page 22: Big Modular Java with Guice

import com.google.inject.Inject;

public class TweetClient {

private final Shortener shortener;

private final Tweeter tweeter;

@Inject

public TweetClient(Shortener shortener, Tweeter tweeter) {

this.shortener = shortener;

this.tweeter = tweeter;

}

Telling Guice to use your constructorannotate a constructor with @Inject

22

Page 23: Big Modular Java with Guice

public static void main(String[] args) {

Injector injector = Guice.createInjector(new TweetModule());

TweetClient tweetClient = injector.getInstance(TweetClient.class);

tweetClient.show();

}

Bootstrapping Guice

23

Page 24: Big Modular Java with Guice

Using Guice

> Why?> Bindings

• Instances• Constructors• Linked Bindings• Provider Methods

> Scopes> Injections

24photo courtesy of http://flickr.com/photos/theogeo/2211326536

Page 25: Big Modular Java with Guice

Why use a framework?

> Writing boilerplate slows you down> More up front type checking> It makes it easier to write better code

> Plus...• Scopes• AOP• Tight integration with web, data access APIs, etc.

25

Page 26: Big Modular Java with Guice

Guice in a nutshell

> Types have dependencies• these are passed in automatically• identified with annotations

> Modules define how dependencies are resolved

26

Page 27: Big Modular Java with Guice

Bindings

photo courtesy of http://flickr.com/photos/uwehermann/3417729678

Page 28: Big Modular Java with Guice

Bindingsmap types to their implementations

28

public class TweetModule extends AbstractModule {

protected void configure() {

bind(TweetClient.class);

bind(Tweeter.class) .to(SmsTweeter.class);

bind(String.class).annotatedWith(Username.class) .toInstance("jesse");

}

@Provides Shortener provideShortener() {

return new TinyUrlShortener();

}

}

Page 29: Big Modular Java with Guice

Binding Annotationsuniquely identify a binding

29

protected void configure() {

bind(String.class).annotatedWith(Username.class) .toInstance("jesse");

...

}

“jesse”@Username String

@Inject

public SmsTweeter(@Username String username) {

this.username = username;

}

Page 30: Big Modular Java with Guice

Defining your own binding annotations

30

@BindingAnnotation

@Retention(RUNTIME)

@Target({FIELD, PARAMETER, METHOD})

public @interface Username {}

> This boilerplate defines a binding annotation> Everything is compile-time checked• IDE autocomplete, import, find usages• Avoids clumsy string matching

Page 31: Big Modular Java with Guice

Instance Bindingsalways use the same value

31

protected void configure() {

bind(Integer.class).annotatedWith(Port.class) .toInstance(8080);

...

}

8080@Port Integer

> Best suited for value objects such as a database name, or webserver port

Page 32: Big Modular Java with Guice

Constructor Bindingsto resolve a type, call its constructor

32

public class TweetModule extends AbstractModule {

protected void configure() {

bind(TweetClient.class);

...

}

}

new TweetClient(...)TweetClient

> Requires @Inject on the constructor• Dependencies are passed in as parameters

Page 33: Big Modular Java with Guice

Linked Bindingsto resolve a type, use another binding

33

public class TweetModule extends AbstractModule {

protected void configure() {

bind(Tweeter.class).to(SmsTweeter.class);

...

}

}

> Requires a binding for the target type• If none exists, one will be created automatically

SmsTweeterTweeter

Page 34: Big Modular Java with Guice

Linked Bindingsto resolve a type, use another binding

34

public class TweetModule extends AbstractModule {

protected void configure() {

bind(Tweeter.class).to(SmsTweeter.class);

...

}

}

new SmsTweeter(...)Tweeter

> Requires a binding for the target type• If none exists, one may be created automatically...

SmsTweeter

Page 35: Big Modular Java with Guice

Provider methodsto resolve a type, call this method

35

public class TweetModule extends AbstractModule {

protected void configure() {...}

@Provides Shortener provideShortener() {

return new TinyUrlShortener();

}

}

provideShortener(...)Shortener

> Annotate a module method with @Provides• The return type is bound• Dependencies are passed in as parameters

Page 36: Big Modular Java with Guice

Using Scopes

photo courtesy of http://flickr.com/photos/houseofsims/3139640931

Page 37: Big Modular Java with Guice

Scopesmanage how many

> Scopes manage how instances are reused• because theyʼre stateful• or expensive to construct or lookup• or expensive to maintain

37

Page 38: Big Modular Java with Guice

Common scopes

> Unscoped: one per use• create it, use it, and toss it!• often the best choice

> @Singleton: one per application• for heavyweight resources• and application state

> @RequestScoped: one per web or RPC request> @SessionScoped: one per HTTP session

38

Everything is unscoped by default in Guice.

Page 39: Big Modular Java with Guice

Applying scopesthe best way is to annotate a class with its scope

39

@Singleton

public class TweetClient {

...

@Inject

public TweetClient(Shortener shortener, Tweeter tweeter) {

this.shortener = shortener;

this.tweeter = tweeter;

}

Page 40: Big Modular Java with Guice

Applying scopesyou can specify scopes in a module

40

public class TweetModule extends AbstractModule {

protected void configure() {

bind(Tweeter.class) .to(SmsTweeter.class) .in(Singleton.class);

}

@Provides @Singleton Shortener provideShortener() {

return new TinyUrlShortener();

}

}

Page 41: Big Modular Java with Guice

Defining Injections

photo courtesy of http://flickr.com/photos/gaetanlee/631004864

Page 42: Big Modular Java with Guice

Constructor injectionto supply dependencies when creating an object

42

public class TweetClient {

private final Shortener shortener;

private final Tweeter tweeter;

@Inject

public TweetClient(Shortener shortener, Tweeter tweeter) {

this.shortener = shortener;

this.tweeter = tweeter;

}

Immutable

Page 43: Big Modular Java with Guice

Method injectionsets dependencies into a new or existing instance

43

public class TweetClient {

private Shortener shortener;

private Tweeter tweeter;

@Inject void setShortener(Shortener shortener) {

this.shortener = shortener;

}

@Inject void setTweeter(Tweeter tweeter) {

this.tweeter = tweeter;

}

> Plays nice with inheritance

Page 44: Big Modular Java with Guice

Field injectionsets dependencies into a new or existing instance

44

public class TweetClient {

@Inject Shortener shortener;

@Inject Tweeter tweeter;

public TweetClient() {}

> Concise, but difficult to test

Page 45: Big Modular Java with Guice

Injecting Providers

photo courtesy of http://flickr.com/photos/toasty/535851893

Page 46: Big Modular Java with Guice

The Provider interface

46

public interface Provider<T> {

T get();

}

Page 47: Big Modular Java with Guice

Injecting a Provider

47

public class TweetClient {

@Inject Provider<Shortener> shortenerProvider;

@Inject Tweeter tweeter;

public void postButtonClicked() {

String text = textField.getText();

if (text.length() > 140) {

Shortener shortener = shortenerProvider.get();

text = shortener.shorten(text);

}

...

}

Page 48: Big Modular Java with Guice

Why inject Providers?

> to get multiple instances• for example, if you need multiple

DatabaseConnections

> to load lazily

> to mix scopes• for example, to access request-scoped objects from

a singleton-scoped object

48

Page 49: Big Modular Java with Guice

Leveraging Guice

> AJAX via GWT> Servlets and App Engine> AOP> Type Literals> Introspection SPI

49photo courtesy of http://flickr.com/photos/niff/87501285

Page 50: Big Modular Java with Guice

AJAX via GWTand GIN

> Zero runtime cost: GIN generates JavaScript from modules

> API compatibility with Guice• Great for GWT-RPC• Test without a browser

50

public class MyWidgetClientModule extends AbstractGinModule {

protected void configure() {

bind(MyWidgetMainPanel.class).in(Singleton.class);

bind(MyRemoteService.class) .toProvider(MyRemoteServiceProvider.class);

}

}

Page 51: Big Modular Java with Guice

Servlets and App Engine

> Configure your servlets programatically

> Use @RequestScoped and @SessionScoped to manage application state safely and easily

51

public class TweetSearchServletModule extends ServletModule {

protected void configureServlets() {

serve("/search").with(TweetSearchServlet.class);

}

}

Page 52: Big Modular Java with Guice

AOPaspect oriented programming

> You can apply method interceptors to injected objects• This is fantastic for cross-cutting concerns like

transactions, security, and performance

52

public class DatabaseTweetStorage implements TweetStorage {

@Transactional

public void saveTweet(String message) {

...

}

}

Page 53: Big Modular Java with Guice

Type Literals

> Like the language itʼs built on, Guice loves types• Set<User> is distinct from Set<Tweet>

> Guice can defeat erasure!

53

@Inject

public SocialView(

Set<User> followers,

Set<Tweet> tweets) {

...

}

Page 54: Big Modular Java with Guice

Introspection SPIservice provider interface

54

TweetClient

<init>

Tweeter Shortener

SmsTweeter

<init>

@Username

String

TweetModule.java:34

"jesse"

TweetModule.java:38

#provideShortener()

> Module and injector internals are available via a mirror SPI• Inspect, analyze and rewrite

bindings

> Guice uses it internally for...• createInjector()• module overrides• graphing

Page 55: Big Modular Java with Guice

Wrapping up...

> Dependency injection leads to testable and reusable code

> Guice makes dependency injection easy• plus it enables scopes• and it integrates neatly with the other APIs you use

> It works on both Java™ SE and Java™ EE• Plus Android, App Engine and GWT (via GIN)

55

Page 56: Big Modular Java with Guice

For more information...

> The Guice website documents usage, extensions, and best practices• http://code.google.com/p/google-guice/

> Plus, Dhanji and Robbieʼs books:

56

Page 57: Big Modular Java with Guice

Q & A

photo courtesy of http://flickr.com/photos/toasty

Post your questions for this talk on Google Moderator:code.google.com/events/io/questionsClick on the Tech Talks Q&A link.

Page 58: Big Modular Java with Guice