Google I/O 2009 - Big Modular Java with Guice

Uploaded by GoogleDevelopers on 03.06.2009

Lee: All right, thanks, everyone, for coming.
Um, first off, my name's Bob Lee.
And I'll be introducing you to your speakers today.
Before we get started, I just want to remind you
at the end of the session
if you'd share your thoughts and give us some feedback,
we'd really appreciate it.
Um, so I created Guice about three years ago.
And we open sourced it two years ago.
And it went on to win the Jolt Award.
And just last week, we introduced Guice 2.
And nowadays at Google,
pretty much just about every Java application
also happens to be a Guice application.
And there are-- we found that they're
a lot smaller and a lot more maintainable for it.
So our first speaker is Dhanji.
And Dhanji has been working on Guice
since before he even came to Google.
And he's responsible for kind of our
more Enterprise layer.
You know, it integrates Guice with servlets
and whatnot.
And Dhanji's also written a book
on dependency injection,
which is heavily focused on Guice,
and I sure hope he'll plug it in the talk.
And Dhanji also works on Google Wave,
which you guys learned about this morning,
and, uh...
which also happens to be a Guice user.
Next, we have Jesse Wilson.
Uh, Jesse Wilson's kind of the Guice star.
He is responsible for-- "player."
[laughing] He's responsible for most of the development
on Guice 2, and he did an incredible job.
Thanks. Jesse: Cool.
All right, uh...
you've already got our names.
Um, so I guess we should get started.
Uh, so we'll start out by just saying
what are you expecting to get
by sitting with us for the next hour?
Um, Guice is all about dependency injection,
and that is the Hollywood principle.
You know, don't call us, we'll call you.
So if you take that principle
and apply it to your Java classes,
Guice is sort of what comes out of it.
It's dependency injection invented by Martin Fowler,
and we'll just talk about how Guice works
and what you will--
by applying Guice to your application,
you'll get more reusable code, more modular code,
more testable code,
and you'll actually write less code to do this.
uh, do you want to do...
Dhanji: Okay, so our talk is split up
into three parts.
The Motivation, Using Guice,
and Leveraging Guice.
So most of it's gonna be introductory.
We're gonna talk about why we think
you need dependency injection
or what the drawbacks are
of not using dependency injection.
Uh, most applications, sadly, even today
don't make use of dependency injection,
and by that, I mean the design pattern,
not necessarily Guice
or any of the other frameworks that are out there.
So it's important to understand
where we're coming from when we say
Guice makes your lives easier
by first looking at how your lives
are currently difficult.
[Jesse laughs]
Uh, so, and then we're gonna talk about
the API itself,
what @Inject means.
How @Inject replaces your factory code.
And, uh, and then finally we'll take a look
at the ecosystem
and we'll spend some time looking at
all the extensions that people have built
around Guice that make your lives really easy.
Jesse: Okay, so we're gonna write a Twitter client.
Um, Twitter is taking the world by storm,
including Google.
And so just to demo the code that you might write,
we'll use Twitter as our example.
We'll start by writing some code
using the factory pattern,
and we'll show all the drawbacks.
And then we'll move to Guice and show what happens
and how your code changes.
So hopefully, the code that you're looking at
will be familiar, and you can see, you know,
"Oh, that's code I would have written," or something.
And then we'll show how your code would change
if you were to use dependency injection,
and then if you were to use dependency injection and Guice.
So here's some code you might write.
This is the ClickHandler for a--
the post button on a Twitter client.
And so the idea is is that
when somebody clicks "post,"
we pull the text out of the text field,
see if it's too long.
If it's too long, we try to shorten it
using TinyURL shortener.
And then we tweet it off,
and we're using SMS as our transport
to send our tweet to Twitter servers.
So you may have noticed that the code
in this example
actually builds its dependencies immediately.
So we say new TinyUrl.Shortener
and new SmsTweeter.
And this is-- this is really convenient
and it's really terse
but there's a lot of problems with it.
Most notably, this code doesn't lend itself to testing.
Um, we can't run this code and say,
"I'm gonna write a test
to make sure everything's working,"
because every time you run that test
you're actually gonna end up doing an SMS.
So that means that you have to have a device
that has an SMS to run the code on,
and you have to pay the SMS bill at the end of the month
if you do that.
And also, you're also sort of at the mercy
of whether or not Tiny URL is working today.
Dhanji: And it doesn't really help
with testing automation.
Jesse: Yeah.
So tell us what factories are, Dhanji.
Dhanji: Okay, so the traditional solution
to that problem has been factories.
So a factory is a third-party object
it's just--it's another class that we've written--
that separates the post button clicked method
and the class that it contains
from the actual services that it requires.
So here, we don't have a direct dependency.
We have an indirect dependency.
So the shortener is now not necessarily
a tiny URL shortener.
It's just something we get from the shortener factory.
And similarly, for the tweeter factory.
All right?
Now, the factory itself
is directly dependent on the SMS tweeter,
for instance.
Uh, so in this case, what we've done
is we've taken that hard dependency
that we had between the post button handler
and the actual services that we want,
and we've inserted one layer of abstraction
in between.
It helps us, but not quite.
Let's see why not.
Jesse: So immediately, one problem is
you have to actually write this factory class.
And so, if you have a whole bunch of classes,
that means you have to write a whole bunch of factories.
And this is code that slows you down.
It's not very interesting.
Uh, it's another thing that you have to version control
and code review, and it's just more code
that doesn't actually get you anywhere
in writing tweet-- Twitter clients.
So, uh, as Dhanji alluded to,
the factory adds an interaction layer
between the Tweet client and the SMS twit--tweeter
that is actually going to be doing the implementation for us.
But, unfortunately, the dependency is still there,
And so what happens is when we write applications
in this style,
anything that you depend on
you need to compile at the same time.
So you've got this compilation time dependency,
and what ends up happening
is you have to build your entire application
any time you want to build any part of your application.
Your application isn't very modular.
And so if we take this to the logical extreme,
what happens is your application blows up
in a firestorm of pain and dependencies
because now everything depends on everything.
So the other problem with the factory
is it's awkward to test.
So I was writing a test for our tweeter client,
and I wrote this.
And so I set up, uh, a mock tweeter,
which lets me intercept the text that gets tweeted.
Instead of sending it to SMS,
I can actually just take an in-memory object
and get the tweet from there.
So I wrote this test.
Dhanji: Well, that's a good start that you have there.
So you're using a special mock tweeter
in your factory.
So now, when you call "get,"
it's gonna get the mock instance.
But I'm not quite satisfied with this.
Can you tell me what's wrong?
Jesse: So the problem is that
when I'm using this mock tweeter,
my test is gonna run,
we're gonna click the post button,
we're gonna get the text out of the tweet--
out of the mock tweeter at the very end
on this last line.
But the problem is is that, now,
I've left my mock tweeter behind.
I forgot to clean up after myself.
Fortunately, there's an easy fix,
and that is that you have to actually add code
to tear down the mock tweeter at the end.
So whenever you write this factory pattern,
you don't even need to worry
about just setting up your mocks
and getting your tests-- your application testable,
you have to also worry
about tearing everything down afterwards.
Dhanji: This is a lot better, but it's still not perfect.
Jesse: Oh, okay. turns out
that this still isn't sufficient
to test with factories
because you still need to worry about
the case where, if my test fails,
it'll throw in the assert method
and it won't actually get to tear down my fac--
tear down my mock tweeter.
So you actually need to put it
try finally clause.
This is really ugly code.
You don't want to see it in your application.
It adds another layer of control flow
that you don't really have to think about.
And we haven't even gotten to the point
of setting up the TinyURL mock yet, so...
Dhanji: So you guys see it's not just your factories
that get polluted with all this extra code
in order to enable testing.
But even your tests are polluted
with all this extra code in order to enable testing.
Jesse: Yeah, yeah.
Uh...the problem is is that
when testing becomes this complicated,
you just don't want to write any tests.
And if you don't write tests,
you don't have confidence in your application,
and you don't get to ship Wave on time.
So, uh, Dependency Injection by hand.
And Dependency Injection is sort of
a technology or design pattern
that addresses this problem very delicately.
So the principle is instead of saying,
"Hey, shortener factory, give me a shortener;
hey, tweeter factory, give me a tweeter,"
we pass those in.
So here's the constructive for TweetClient.
And it actually takes a shortener and a tweeter.
And now it's the caller's responsibility to decide
which implementations to use.
This is this Hollywood principle again.
We'll call you with your dependencies.
Don't ask for them. They'll just be passed in.
And what's absolutely brilliant about this
is that now we don't need to worry about
passing in real dependencies in our, uh,
we don't have to worry about
setting up teardown in our test.
And since we're passing them into the constructer
of TweetClient here--
so I say new TweetClient,
and I pass in the dependencies I want to use--
not only do I have to not worry about tearing it down,
but I also don't have to worry about forgetting something.
So you may have written applications where,
you know, you get your test, you get everything compiled,
and you run your test,
and then at runtime it fails immediately
because you forgot to prepare some factory.
You know, you forgot to initialize something
or get something started up.
And so now your application gets this sort of gross,
bootstrap system where
in order to actually write a test,
you need to, you know, start the service,
connect to the database, do this, the other thing,
test that the SMS radio is turned on,
and now we can test.
Well, with dependency injection,
your dependencies are obvious
and they're part of your API.
But this is where dependency injection breaks down.
Okay, so what we have here is a client factory,
and it does all of the work of providing
the dependencies to our object.
But we've just moved it one step further.
We had the tweeter factory
and we had the shortener factory.
Uh, but now we've, like, pushed it one step further
in order to make our tweet client
dependency injectable.
So, I mean, we've saved a little,
but we've still got our factory code
to write and maintain,
and it still looks ugly,
and there's still the same problem.
It's just one step removed.
So the idea of all this dependency injection
is we've broken this hard dependency
from tweet client onto its TinyURL shortener
and SMS tweeter,
and by moving it, we only depend on the interfaces,
which is just fantastic.
It means we can compile and test and do all these things.
But we've really just shifted the dependency
over to our tweet clients in our factories,
and we just had to write a lot of factories
to get this done, right?
There's--there's three factors here.
That's a lot of code that you have to write.
And so we have to have something else.
There's got to be something better.
And that something is Guice.
So with Guice, you take your factories
and you replace them
with a combination of injectors and modules.
And so instead of writing all about
imperative code to figure out
how to build an SMS tweeter, and, uh,
an URL shortener,
instead, you create a module,
and this maps the implementations,
the interfaces to their implementations.
And injector is a Guice-applied class
that basically acts as your factory,
and it's one-stop-does- everything factory
for your application,
and it does it in a dependency injection idiom.
Dhanji: And, more importantly,
it's a factory that you don't have to write
and you never have to maintain.
Jesse: Yeah, yeah.
All right, so now can configure our dependencies
using a module.
And so, instead of writing that 12 lines of factory
for tweeter and 12 lines of factory for shortener
and 12 lines of factory for everything else,
instead, we have one statement
which is bind interface to implementation.
And this is how you configure Guice,
and that creates an injector that works the way you'd like.
So the change to the client code
is you add the inject annotation,
and that just is a signal to Guice to say
whenever somebody wants to factory construct
a tweet client,
call this constructor, so...
Dhanji: So it's--we've taken that entire factory
with all of that boilerplate code
and that testing code that accompanied it,
and shortened it to the one little @Inject annotation
that you see there.
And that's all Guice needs
in order to be able to provide this class
with its dependencies.
Now, that's a great saving.
Jesse: [whispering] Yeah, yeah!
Especially since it's such a savings encode,
you'll actually tend to do it.
And we believe that when you use dependency injection,
you'll write better codes.
You'll write better code, more testable code,
more modular code.
Um, here are the four lines of code that you need
to bootstrap Guice.
Uh, you need to create an injector
with your module or your list of modules.
Then you can use that injector
to get an instance of something.
So this is just like your factory used to do.
Now you can say, "Hey, injector, give me a tweet client,"
and it's parameterized on what you want it to construct.
And it's fully type-safe.
So if you've ever used
Spring dependency injection tools,
then you'll notice that it's not type-safe,
and you'll to do a lot of casting
and you need to do a little finger crossing
to make sure that what you ask the injector for
is what you get.
With Guice, it's fully type-safe.
The type that you pass in is the type it will return.
And if it's not there, it'll blow up spectacularly
and tell you all of the details of what went wrong.
So that's the motivation for Guice.
And now we're gonna just dive into
all of the minutiae of the Guice API
and explain how you use it,
what the day-to-day life of Guice development is like.
So why?
Dhanji: Okay, so we've already said that boilerplate code
is messy and it's difficult to test and maintain.
And it's just nothing that, uh, we--
as a developer, you want to spend your time doing.
But there are also other reasons to use Guice.
Like Jesse said, there's a lot of type safety
that you gain from Guice.
And this is because when you tell Guice,
when you give it that bind statement,
that's actually a signal to Guice
to go out there and look at that class
and make sure that all the dependencies
for that class are also available,
and that's valid in a way in which
it can construct it at runtime for you.
And that's-- that's really useful.
More often than not, you'll find
that fixing one small error by hand in a factory
and then recompiling--
you go a bit further down the line,
you find another error,
but Guice does all of this type checking
upfront for you
and gives you a long error list
the first time you deploy it.
Jesse: It gives you JavaC-style errors
that you can even click on
and navigate right in your code
to the bind statement that didn't work.
Um, in addition, when you use Guice--
this is really the real value of Guice,
and this is growing as our community matures.
You get scopes, which is an absolutely humungous,
cool feature.
You get aspect-oriented programming,
which is something that you may like.
It turns out to be very, very convenient
in your larger,
Enterprisey-style applications,
as well as any application where you have
cross-cutting concerns.
And there's tight integration
with a whole bunch of different APIs
that you already are using,
such as servlets and databases
and RPC systems, et cetera.
Oh! And, uh--
Dhanji: Google Wave.
Jesse: If all these technical reasons weren't enough,
well, Wave uses Guice,
so why aren't you, right?
All right, so in a nutshell,
classes have dependencies.
And modules define
how these dependencies are resolved.
This is the--this is the whole concept, right?
You have code, it has dependencies.
Today, you use factories,
And with Guice, it's the same thing.
You have dependencies.
And then you configure it with Guice.
You configure your dependencies
and the resolution using modules.
So let's investigate that, uh, module resolution.
And that's called a binding.
Dhanji: Okay, so--
Jesse: I'll go. Dhanji: You want to do it?
Jesse: All right, so we've got a module
with four bindings here.
Uh, there are the three statements in the code,
the bind tweak line-- the bind tweeter,
bind string, those lines.
And then method that has @Provides annotation.
And so these are four bindings
and we'll go into detail
and explain how each of them works.
All right, so...
Dhanji: [laughs]
Okay, so this is a simple bind statement.
All this says is it tells Guice
to look in that class and use it any time
it appears as a dependency in any other code
that you have.
So what you need to do in the tweet client
is place an @Inject annotation,
like we saw just earlier,
on the constructor that you want to use,
and all the dependencies of that constructor
will be filled in for you by Guice.
Jesse: So, uh...
Whoops, this one.
All right, so the next type of binding
is called a provider method,
and this is really, really handy,
and its new in Guice version 2,
which we released last week.
So a provider method is
whenever somebody asks me for this type,
run this little bit of code
in order to calculate it or to compute it
or to fetch it or to construct it.
So this sort of is your traditional factory method
type of operation where you can create something,
configure it, and then return it.
And the way you do a provider method binding
is somewhere in your module class
you have a method with the @Provides annotation
and the return type that you'd like to bind.
So in this case, we say,
@Provides Shortener,
which says this method is a binding for Shortener,
and then whenever Guice needs to inject
a shortener or to find a shortener
for somebody else's dependency,
it will run this code.
And what's really handy about provider methods
is that they can have dependencies of their own.
So if you want to provide a shortener
and it has a dependency on some HTP factory
or something like that,
you can pass that dependency in
via the parameter of the method.
So not only can your classes have methods,
but your providers--your provider methods themselves
can have dependencies,
because your application is effectively
a big graph of this depends on that.
You know, my user interface
depends on the components inside of it.
Et cetera.
All right.
Dhanji: Okay, so this is a slightly longer form
of the bind statement.
And what we're saying here is bind this interface
to this implementation.
So tweeter is the interface that we have.
We don't know how the tweets actually go out.
Um, but SmsTweeter does now.
SmsTweeter sends them over the short message service.
So all this is saying is every place
that you see tweeter as a dependency,
make sure that SmsTweeter is provided.
And the great saving here is, of course,
none of the client code
knows that there is an SmsTweeter
being used underneath.
It just uses it when it's available at runtime.
Jesse: Yeah, so, you know, six months down the road,
if we decide that the SmsTweeter isn't optimal,
or if we want to use a JSONTweeter
or some other protocol,
all we have to do is change this one statement
and say, "Okay, now I'm gonna bind my tweeter
"to my JSONTweeter of my AJAXTweeter
or my XML," or something like that,
any transport that would be used.
Uh, so what's actually happening behind the scenes here
is there's two bindings.
There's the binding for tweeter to SmsTweeter.
And then there's a second binding,
which is SmsTweeter to its own constructor.
So when Guice sees this,
it's actually going to create a binding for tweeter,
and then it'll look at the SmsTweeter's binding.
And in this case, it'll just use that class as constructor.
All right.
Uh, Binding Annotations.
So, so far, we've always been talking about
the unit of a dependency is a type.
So you can say, "Okay, I depend on a tweeter
or a shortener."
But oftentimes, the type doesn't uniquely identify
what you really want in your dependency.
So if you say, "Okay, I want my database address,"
or, "I want the port I'm supposed to bind on,"
it's not really sufficient to say,
"Just inject a string,"
because there may be multiple strings
and you need to really identify,
"Okay, I want the string that is the database addressed,
"or the string that is--
the integer that is the port number."
And so Guice uses a type-safe way
to identify bindings
in addition to the bindings type itself.
And these are called binding annotations.
And so you can annotate a parameter
with an annotation that you define
that identifies which instance of that type you want.
So in this case, I'm binding the string "jesse"
annotated with Username.
And this is, again, indirect.
So we can say, "Okay, I want a...
uh, an annotation called port number
or an annotation called database address."
So you can use Guice to configure not only
your class dependencies,
but also, all of your configuration dependencies.
So you can--you don't have to worry about
having these separate mechanisms
for how you connect to your database,
how you connect to remote services,
you can use Guice to configure everything.
And this is the standard boilerplate you need
to define user annotation.
I'm not gonna go too much into detail on it,
but this is just--every time you want to define
a custom name for something,
use this boilerplate.
You're saying about his and hers?
Dhanji: Oh, yeah, so the great thing about this
is it does look like a little bit of boilerplate,
but the awesome saving is it's purely
a bit of metadata, right?
You can reuse it across your application
for several purposes.
You might bind "jesse" to the user name,
where you use it in a login-style scenario.
But you might bind something else
to a user name somewhere else for a different type.
So it's completely flexible,
and it doesn't force you to bind directly
to the actual implementation that's underneath.
So in the tweeter case,
you might bind it to a current transporter,
paid transport,
and, really, that paid transport is an SMS transport.
But you can reuse the paid annotation
to bind, say, a credit card transport--
or a credit card service, sorry--
or any number of other dependencies.
Jesse: And one really nice thing about the way
Guice does dependency injection is that
this annotation is compiled into your code.
So this is just standard Java code,
and if you spell user name wrong,
the compiler will tell you, or, more likely,
if you're using an IDE like IntelliJ or Eclipse,
it'll highlight it in red,
and make sure you spell everything properly.
All right, so the last type of binding
we're gonna talk about is an instance binding.
And we already sort of saw this with the "jesse" example,
where you can give an actual value
that you want to bind to.
So, in this case, instead of hard coating 8080
as a public data constant in 10,000 classes,
you can configure it once in your module,
and then everywhere that you need that constant,
you just inject it.
And this really overcomes this problem
where, you know,
if you decide you want to run your FTP server
on Port 22 instead of 21,
you have to go in and change 10,000 pieces of code
where that's wired.
And the, uh, the main problem is that
when you do that type of approach,
you either have the 10,000 different definitions of that
or you have some file called "constants"
that everything else has to depend on.
So this is a nice balance.
All right, you talk about scopes.
Dhanji: Okay, so scopes are very interesting.
They're really hard for me to define
in one, simple way.
So I'll use the simplest explanation
that I could think of.
For me, scopes are about duration, right?
You can talk about scopes as a context,
for instance, an HTP request
is a scope in Guice.
Or an HTTP session, which is a series of requests
that come in a sequence.
Or you can talk about singletons,
objects that live throughout the life of an application.
That is a Scope in itself.
So these are short or longer durations
during which any dependency injection that's performed
will always receive the same instance
of the dependency.
Jesse: So, uh, when you do your factory pattern,
you'll often have, you know, a private static constant
that is, you know, the tweeter.
And when you say, "Give me the tweeter,"
you might lazily instantiate it.
And then, for the rest of your application,
you always get the same instance.
With scopes, you can get that sort of
application-wide constant
without having to actually write the statics
and without having to compromise
your application's testability.
In our cute diagram here,
we have this sort of long, blue line,
which is the duration of the application.
Um, this is a very abstract example, without a legend,
so I'll describe what I'm thinking
when I'm drawing this.
Um, the red bars are HTTP sessions,
and the blue bars are HTTP requests.
And so you can see that the scopes
nest inside of each other.
So you can have, like, your application lives
for several hours or several days
or several months,
depending on how your uptime is.
And then every session gets its own context,
and then every request
gets its own context.
And this is the HTTP example,
but you can come up with scopes
for any number of different contexts
that exist in your application.
Uh, so we've already sort of talked about this.
These are the common scopes.
So the most natural one is Unscoped,
and that means that any time you want a value,
it will be created, you use it,
and then you throw it away.
Uh, the opposite is Singleton,
where any time you need a value
it's created exactly once,
and you always, always use the same one.
This is great if your application is stateful,
and you want to do something like
track the number of hits on your sever
since it was started.
Because you can just say, "Use a singleton,"
and every time somebody does something,
you call increment.
Uh, RequestScope is fantastic.
And it says, "For the duration of my HTTP request,
remember this value."
This is particularly handy
if you're doing a several-tier application
where you want to say,
"I don't really want to go back to the database
"every single time I want to remember
who the current user is."
You can just put that in a RequestScoped object
and it remembers.
And SessionScoped is the same process
for the HTTP session.
So if you have, uh, if you have any session data,
like a cache, this works very nicely for that.
So that's how you apply scopes to your objects in Guice.
Uh, you just annotate them with the name of the Scope.
We're very annotation happy in Guice.
And this is both functional, because it says,
"Okay, there will only be one tweet client
for the duration of the application."
But it's also documentation.
So when you're seeing this class tweet client,
and you're maintaining it,
the singleton annotation is a really good hint
that you may have to think about concurrency
when you're maintaining this.
Because singletons are naturally--
uh, need to be multithreaded in multithreaded applications.
All right, um, if you want to apply a scope
in a binding instead,
you can also do that.
So here we're saying,
"Bind my ConnectionPool to the ExecutorServicePool
as a Singleton,"
which is .in(Singleton.class).
Or in your provide method you just annotate the method.
And that'll mean that Guice
will only call that method one time,
and then it'll just remember the value.
And any time anybody wants a shortener,
it just uses that same instance.
Dhanji:, okay.
So there are different kinds of injections
that Guice supports,
and constructor injection is the most obvious one.
This is the one that we've been talking about.
This is where you pass in all your dependencies
via constructor,
and you place an @Inject annotation
on the constructor
to tell Guice to use it.
Now, the advantage to constructor injection
is--is really great,
because you can declare your dependencies as final,
which makes them immutable.
Now, this is great for any concurrent class
where you have multiple threads
accessing the code in the same class.
Then you have no danger of state leaking
between these threads,
because there is no state, right?
You don't change the values.
It's also great for publication,
which is--which means that once the value is set,
it's seen by all threads,
and you never have any danger
of a NullPointerException.
You also have method injection,
which is traditionally called setter injection.
And this is almost exactly like constructor injection,
but it's called after the constructors have run.
And what this is is just a simple setter method,
so you pass in your dependency via a setter.
And the method doesn't have to be called
Set Shortener or Set whatever.
It can be called anything you like,
so long as it has an @Inject annotation
and it doesn't only have to take
the one parameter.
It can take as many arguments as you like,
just like a constructor.
Jesse: All right, and lastly.
Dhanji: Lastly, we have this horrible form of injection
that we don't want you to use,
but we're gonna talk about anyway.
And this is field injection.
The thing about field injection
is that it's really concise, right?
It's an @Inject annotation directly on the member
that you're, uh, that you depend on.
You don't need to set anything.
Guice will set it for you by reflection.
The problem with this,
and the reason we discourage it,
is that it makes testing very, very difficult.
Now, you have to expose your fields.
In this case, we've exposed them as PackageLocal
in order to access them from a test class
in the same package.
Now, not only is that ugly,
it's, um, it's also difficult for other tests
that don't sit in the same package
to get access to it.
So we discourage this, but in a pinch
or in tutorial code, it looks nice and it works.
Jesse: It's very, very concise.
So a lot of the intro in the talk
was about removing boilerplate.
And if you get-- if that's why you're here,
I invite you to use field injection.
Although you're losing out on a lot of other benefits
of dependency injection.
All right, uh, let's talk about injecting providers.
So thus far, we've always been talking about
I have a dependency.
You get a single instance of that dependency
and you use it.
Um, the provider interface permits something new.
And the interface is very, very simple.
It's parameterized on "T."
So you can have a provider of string
and then "get" will return string,
or you can have a provider of shortener,
and "get" will return shortener.
So the provider's type,
it's a factory for a given value.
So when you inject a provider into your code--
and I'm using field injection here,
shame on me--
um, you can see that
we don't have to actually get our shortener
until we need it.
So if we have somebody who's very terse
and doesn't ever write tweets that are shorter than--
that are longer than 140 characters,
we can avoid the cost of constructing our shortener
until we actually need it.
So in this case, we say, you know,
if text length is greater than 140,
then go ahead and ask the shortener provider
for a value.
We'll use it, and then we'll let it go out of scope.
So there's a bunch of reasons why you would use providers.
Um, first is to load lazily,
which is what we just saw.
So we don't actually have to worry
about constructing the shortener
until it's actually needed.
It's also useful if you want to get
multiple instances of a value.
So if you need multiple database connections,
instead of injecting a database connection
in your constructor, you can inject a provider
of the database connection,
and then you can call "get" once for each thread
that you want to use to connect,
or once for each, uh, each query
that you need to run.
Finally, providers let you mix scopes.
And so this is where you have, uh,
a singleton object
that's sort of the overseer of everything.
But it kind of wants to know who's asking
who the current user is
or what their session contains.
And so you can inject a provider of user
or a provider of session,
and then use that to look inside.
All right, so thus far,
we've talked about a lot of the mechanics
of using Guice.
Now it's time to get into the real exciting stuff,
which is how do we really start to take advantage of Guice,
and how does this really change our applications?
We've removed the boilerplate.
We've become testable.
But now let's really start
to figure out how you can build
absolutely fantastic applications with Guice.
All right, so this is a fairly abstract diagram
of a fairly abstract, uh--
This is--imagine that this is Google AdWords, okay?
So these are all of the classes
in Google AdWords.
And we are in sort of dependency, uh,
dependency nightmare mode here,
where we can't compile a single module
without having to build the whole world.
Everything depends on everything.
And it's really hard to figure out, you know,
how do I--how do I isolate this one component
so that I can reuse it in AdSense
or so that I can reuse it in some other system?
So you want to avoid creating
this really complex spaghetti dependency, uh,
So with Guice,
the idea is that you
are encouraged to divide your application
up into modules.
So, in this case, we have five modules,
and they all communicate with each other
via the public API.
And, uh, this is possible with factories
and it's possible with really good
software engineering discipline.
But when you're using dependency injection,
and Guice in particular,
it becomes very easy
to have this type of discipline
where you're saying,
"Okay, only my API is exposed."
And the reason that this is possible
is because Guice lets you
hide your implementation details.
So you only-- only your module knows
about your implementation classes.
And then your interfaces and your domain classes
and all that can be in your public API.
All right, so did you see that cool transition?
All right, so here's-- here's where we're at.
We--we've written this application,
and we want to swap out this entire component
in the top right with a new component,
and when you use dependency injection,
it's about writing modular code.
And modular code really means
that I can swap out this blue one
for a yellow one.
And that can be a completely different implementation
written by a completely different team.
This is extremely powerful, you know.
You're writing these really, really big applications,
things get slow, things get complicated,
and you know you want to say, "Rewrite!"
Well, Guice helps you avoid the rewrite
and all of the costs with it
because you don't have to rewrite the whole thing.
You can just rewrite this module,
the particularly painful one.
Um, so that's really handy, but the other thing is
is that not only can you take an entire module,
airlift it, and put in a different implementation.
You can also take that module and reuse it
in a completely different application.
So we can take our, you know,
our yellow module from AdWords,
and then go and use it exactly the same
in AdSense.
And this is extremely powerful.
And this is the type of reuse
that was sort of promised to us
with object-oriented programming,
but hasn't really been within reach.
You know, you write the customer class
in every, single application
because you don't have a customer module.
And this sort of permits
sort of your service-oriented application
where you can actually have a module that says,
you know, these are all the APIs
talking to my service.
Dhanji: Okay, so Wave is famously
a GWT application.
GWT is Google Web Toolkit.
And, uh, for Wave,
we don't use this in particular,
but, um, GWT does support Guice-like behavior
using a library called GIN.
GIN was written by one of our Googlers
and it provides very similar functionality
to Guice.
When GWT is running in Java mode,
or hosted mode, as they like to call it,
it will defer to Guice
to do all of the dependency injection.
And when it's compiled into JavaScript
GIN will provide
the intermediary JavaScript Code
to do the dependency injection
just like it would work in Java.
Now, it does everything
without any runtime cost whatsoever
because the source code that's generated by GIN
is exactly the same source code
you would write in JavaScript
to wire up all those objects with one another.
So that's fantastic.
The other great thing is it's the same API you use
for Guice.
So if you have a module that you use
in a server environment,
and you'd like to port it to the GWT environment,
something that would have been unheard of
before GWT and before Guice,
you can do this today.
It is a reality.
Things like GWT-RPC,
where you share code
between the client and the server
really becomes possible
now that you have GIN sitting in this dual use mode.
Okay, so the other cool thing about Guice is--
and particularly, Guice 2,
is the Guice servlet extension.
Now, the Guice servlet extension
is available in trunk.
You can check it out,
and there's a separate jar that you need to download it
and use it.
Jesse: It's a separate jar, but it comes with Guice.
Dhanji: Comes with Guice. Jesse: Yep.
Dhanji: And it gives you the request
and session HTTP scopes that we saw just earlier,
just as an annotation,
just like @Singleton was.
that you get out of the box of Guice.
Now, these are really cool,
but the servlet module has a lot, lot more to it.
As you see here, you extend servlet module
rather than abstract module
when you're creating your Guice module.
And what this gives you is the whole extension
to the binding language
to configure servlets and filters.
Now, if you guys have ever used web.xml
in a HTTP sever, like Tomcat or JEDI,
you find yourself writing a lot of declarative XML rules
to tell you how to route requests
based on their URLs.
Now, you can do all of that with idiomatic Java.
Just like you're used to with, you know,
with bindings and how JEDI would work under the covers
without all this XML in the middle.
Now, that's great because we're Java programmers,
and we like to write Java.
But it's also great because it's type-safe.
I can't serve a particular URL
with something that's not a servlet.
So you have all these minor little enforcements
that come into play that add--
give you this extra level of confidence, yeah.
Now, the other great thing about the servlet module
is that it has a lot more extensions
than just this.
It allows you to match URIs
based on regular expressions.
It allows you to bind keys
so you can have multiple servlets
that are matched in a dispatch order.
All the power of web.xml and a lot, lot more,
and none of the pain.
Jesse: Yeah, the part that Dhanji was talking about--
me about earlier
is that when you move your servlet configuration
out of the XML file and into modules,
you get a modular design for your servlets.
And so what that lets you do
is you can actually create a prepackaged module
for some aspect of your application,
like authentication or your admin servlet,
and you can say, okay, we've written the, you know,
the single sign-on servlet package,
and we use that module
in a whole bunch of different applications,
and you don't have to worry about
configuring web.xml for each.
So if you're the single sign-on team
or the security team
and you have your own servlet filters
and your own servlets,
you can give this to your entire development staff
at your company and say,
"Okay, use this module in your servlet application,
"and you'll automatically get our filters
"and our servlets applied,
and there's no other integration work."
Whereas the alternative is
is you have to actually go in
and edit the web.xml for each.
And that means that you're sort of discouraged
from changing your filters over time
as your business needs change.
Dhanji: The other great thing is we do this
in Google Wave, by the way.
So we use this modular design,
so we have particular servers that sit on the front end,
and the single sign-on is the same code
that's used all over Google,
and we bring that into Google Wave this way.
And--and this morning's demo,
when you saw Lars doing all those fancy, cool things
with the collaborative editing stuff,
every single character that he typed
went through a Guice servlet dispatch rule.
Yeah, so is it fast?
Jesse: [laughs] It's way fast.
Okay, all right, so one of the features
I hinted at earlier is aspect-oriented programming.
And this is a very, very powerful,
very, very complex domain.
And Guice gives you sort of the sweet spot
of what you want,
which is method interceptors.
Um, so suppose you're writing a database thing,
and you--you're writing this boilerplate
where you need to set up and tear down a transaction
for every method called.
So, traditionally, what you'll do
is you'll say database,
try, then do your actual work.
And then you'll have, you know, a catch clause
and a finally clause
and some teardowns and rollbacks
to handle the cases where your business logic
either failed or there was an optimistic problem
with your, um, your commit.
So with aspect-oriented programming,
instead of doing all that stuff all over the place,
you separate the cross-cutting concerns
into interceptors,
and they run around your method.
So in this case, we've annotated
database tweet storage with @Transactional.
And what this will do is it'll make sure
that before and after saveTweet is called,
we set up a transaction and then we make sure
to commit or roll back,
depending on how that, uh, method completed.
Jesse: Uh, do you want to talk more about this?
Dhanji: Well, this is another extension to Guice
that's not available in the Guice code project,
but you can find it in our documentation.
It's a very, very convenient thing
for people who use Hibernate or Java Persistence API,
which is the foundation of Google App Engine's
persistence framework.
So this is a bit of boilerplate code,
very much like the factories,
but something that sits in every method
that does any work with the database session.
And it can all be abstracted away
with this one, single annotation.
And Guice enables us to do this, yeah.
Jesse: The other thing is is that this AOP,
it really fits hand-in-glove for transactions.
And there's a handful of other cases
where it also fits very nicely.
So on my former project in billing,
we used AOP and Guice to do security.
And so you'd have a method that says, you know,
"Make payment,"
and you would have an annotation on that method
that said @Secure.
And that would require
that whoever was calling that method
had a prior login.
And you can annotate your methods
and configure all this stuff
just exactly as you need it to fit your application.
So you can define your own annotations,
and you can define how those annotations behave.
Uh, it's fully pluggable,
and in its core, Guice knows nothing about transactions,
it knows nothing about servlets,
it knows nothing about security.
But it supports all these things to be added on
with its own modular architecture.
All right, so the last part
is that Guice is fairly open
to extension and manipulation.
So we've talked about binding so far,
and we've talked about injections.
All of this information, all this metadata
about your application is exposed
through Guice's Introspection Service Provider interface.
And so, when you define your module
and you set everything up,
Guice will actually give you all of the metadata
that is has internally
so that you can take that and analyze your application.
Uh, the most interesting one so far
has been that we've been graphing our applications.
You find really interesting things
when you can take your entire 10,000 class application
and spit it out into a graph and say,
"You know what?
"That dependency there, that one's broken.
We need to fix that."
And you can't do that type of thing
by just inspecting the code,
reading line by line,
because the modules are, you know, modular.
One's over here, one's over here.
The introspection API lets you see it all
at the same time.
Uh, it's also used internally by Guice
to do some of the more, uh, testy,
easy, configuration-type things.
So when Guice--when you have a module
and you know, you say,
"Okay, I want 90% of this module,
"but instead of that binding to the production database,
I'd rather bind to the QA environment database."
Or you know, the, uh, the canary database.
So you can take that module,
override it with just the stuff that you want,
and you can create a new module.
And this all uses the introspection SPI.
It's sort of built on top of Guice's own, uh...
All right, so wrapping up.
Dependency injection leads to testable,
reusable, modular, maintainable code.
And we love dependency injection,
but you really want a framework.
And Guice makes dependency injection easy.
It's a, you know, it's very concise.
You add that annotation.
Very little boilerplate that you have write.
And once you've got Guice independency injection in play,
then there's a whole new avenue of components
and modules that you can use as well.
So this is, you know, your scopes, your AOP,
your warp-persist, your app engine integration,
your Google App Toolkit integration.
And Guice is also really lightweight.
So we're serious about this,
and we don't think that it makes sense
to include a sort of large kernel in applications.
So although Guice drives, you know,
some of the bigger applications at Google,
it also works on Android.
It's a fairly lightweight, simple library.
And then it's a got a sort of pluggable thing
so you can put the servlets for App Engine
or the UI stuff for Android,
and it all just sort of works seamlessly.
All right, and the book plug.
Dhanji: Yep, so I've got a book coming out
called Dependency Injection.
It's mostly a design patterns book,
but it has a lot of focus on Guice
and another framer of Spring,
and if you use that discount code
and go to that URL,
I believe you get a 40% discount for one week.
Jesse: Yep, Google I/O only.
So, uh, you can get the book
in Manning Early Access right away.
Dhanji: Yep, and then once it's ready,
it'll be shipped out to you.
Jesse: Yeah, the book really goes into full detail
about all of the stuff that we've just breezed through
in the last hour.
And I guess now we should open the poll up
for questions.
Um, we're using Google moderator.
So if you guys have your laptops handy
and the Wi-Fi is working well,
you can post questions there.
Otherwise, please use the microphones here.
Um, thank you.
All right.
man: How do I compose modules?
Jesse: How do you compose modules?
man: Take several small modules and build a big one.
Jesse: Yeah, so, um,
the, uh, the-- the module API
actually has a method
where one module can install another module.
So you can say,
"Okay, here's my entire front end module."
And then you may have multiple teams, you know.
You've got your team in New York
working on the billing system,
and your team in L.A.
working on the user authentication system,
and a team in Mountain View working on the features.
Your front end module can just install each of those.
And what's really nice about that approach
is that those modules
are independently reusable.
So those teams can work independently of one another
as well as, you know, when you actually need
to go out in production
and you need the whole team's code
all in one binary.
You just compose it all into one system.
Um, now, if you have multiple bindings
for the same type--
So if Dhanji binds his tweeter to SmsTweeter,
and I bind it to JSONTweeter,
Guice will detect that at start-up time,
when you call that guice.createinjector method,
and it'll say, you know,
these are the old falling bindings
that we had problems with.
And, you know, this one happened on line 45
of SMS module,
and this one happened on line 32 of JSON module.
And it'll help you to resolve that.
Dhanji: There's also a really simple way
to compose modules.
And that is when you're bootstrapping Guice,
you just give it a list of modules,
and it's just a simple Java tool list.
Give it as many modules you like,
it'll be installed in order.
Jesse: Yep.
Uh, so we got a question from a moderator
that Jesse in Mountain View wrote.
Uh, what apps use Google Guice?
So the ones at Google that use it are, uh,
you know, we started out with Adwords.
We had this really big application
fairly hard to maintain.
You know, we had a lot of, um, factories
and a lot of static state
and a lot of, you know, database connections
that were required for tests
that had nothing to do with the database.
And so Guice really rescued Adwords front end
and gave it a couple more years of life
by making it so that, all of a sudden,
you could use certain components of Adwords independently,
and that's breathed new life into it.
Um, there's also Gmail,
um, Orkut, Docs, YouTube,
Wave, um... the...
Dhanji: Pretty much every new Google application
these days.
Jesse: All right, "Is Guice Servlet module
now a superset of warp-core?"
So, uh...
Good question.
[both laugh]
Uh, so...
Dhanji: The answer to that is no.
It's--it has very similar functionality.
But warp-core is now defunct.
So Guice Servlet takes precedence.
It supersedes it.
Jesse: Yep, warp is still useful