Alexis Moussine-Pouchkine: Hi, everyone.
We're here at Devoxx 2014, and I'm here
with people that know a thing or two about Java.
And I think you guys have read "Effective Java," right?
EAMONN MCMANUS: Yes.
CHRISTIAN GRUBER: Yes.
MALE SPEAKER: So this is Eamonn, this is Christian.
And we're going to talk about annotation processing, code
generation, and two specific projects.
So why don't we start with annotation processing?
So for those that haven't been exposed to it,
you want to explain what that is?
EAMONN MCMANUS: Sure.
So it's something that was introduced
as a standard with Java 6.
So there was a JSR that defined that,
and there's a set of APIs that define it.
And it's basically a way of extending the Java processor,
plugging your own code into the processor that
will run while compilation is running.
And it's quite powerful.
You can follow these standard APIs
which will work with both Java SE and ECJ
because it is a standard.
And you can arrange that when the compilation happens
your code gets executed, and that code
can see what other code is being compiled.
And it can also generate new code
that will be compiled alongside the original code.
So doing that means that you can-- first
of all, you can do additional checks,
because you can emit error messages,
and they will show up in the right place.
If you were using an IDE, they would show up as red lines,
there is a problem here.
And secondly, then you can augment the code, the input
code of your program, with this new generated code.
MALE SPEAKER: So the fact that it's at the compiler level
obviously means that you still get the benefit of using,
you mentioned an IDE, and all the tool chain.
And that is very critical.
How about performance?
Is that something that people need to worry about?
EAMONN MCMANUS: It's not something
that we've noticed as a problem, so I
think it's probably all right.
MALE SPEAKER: So the reason you were here
talking about annotation processing,
and that we're talking about it now,
is that this enables for some interesting features.
And one of the projects you've been working on
is AutoValue, is the proper name?
EAMONN MCMANUS: Yes.
MALE SPEAKER: And that's a project on its own?
Can we say it's built by the Guava team?
Some relation to it?
CHRISTIAN GRUBER: It's part of a larger effort of projects
that all do annotation processing
for various purposes.
AutoValue does value type.
Really easy, low boilerplate value types.
I
MALE SPEAKER: So, yeah.
I mean, AutoValue, I mentioned "Effective Java." if you
haven't read it, guys watching this and gals,
you should read it.
It talks about how you have to implement
equals hashcode-- what was the third one?
EAMONN MCMANUS: Two string.
MALE SPEAKER: Two string.
Thank you.
EAMONN MCMANUS: And that's a major pain, right?
MALE SPEAKER: And that is painful, yes.
But remind us, why do you need to do that?
And how are you solving this?
EAMONN MCMANUS: So you don't absolutely
have to implement two string, but you really
would want to implement equals and hashcode so that you
can use your values as keys in like hash map or hash set.
If you have equals, that means you can use it in tests.
So you can compare your object against an expected object,
and so on.
So you pretty much always want to define these methods
when you're creating a value type.
So an immutable type, you really want to define these methods.
And it's a huge pain, because you're doing it
exactly the same way every time.
So the idea of AutoValue is, instead
of-- so you define basic abstract methods that
are the properties of your objects.
So your classes and address, you say abstract class address.
And you say abstract string, street address,
abstract post code and so on.
And you put the AutoValue annotation on that class.
And so the idea with the AutoValue annotation processor
is that it sees this notation, and that
causes it to generate basically new code,
which is the implementation of this class.
So you have this abstract class, which is the interface
that the client code sees.
And then you can have a private implementation
of that class, a subclass that basically
writes those methods for you.
So it writes the implementations of those two abstract methods
that you defined, and it also writes the implementation
of the equals and hashcode and two string methods.
So it's a simple idea, but it's just a huge benefit
in terms of avoiding having to rewrite
the same sorts of things over and over again.
MALE SPEAKER: So if I want to use it, it's like [INAUDIBLE],
I add-- how does it--
EAMONN MCMANUS: The easiest way to do it is with Maven.
I mean, you just express a dependency on it with Maven,
and everything just works.
MALE SPEAKER: This has no impact on any jar that you generate,
right?
This is all tooling.
EAMONN MCMANUS: Yes, that's right.
CHRISTIAN GRUBER: This is tooling.
Although the generated code goes in your jar.
We actually made a choice to generate source code,
not bite code, precisely so you could go look at it.
MALE SPEAKER: But you're not carrying along a library, or--
CHRISTIAN GRUBER: No, no, no.
MALE SPEAKER: this huge dependency.
EAMONN MCMANUS: AutoValue in particular
is defined to be completely standalone.
It doesn't depend on anything else
in terms of what's generated.
MALE SPEAKER: Yeah, Java 6 and above.
CHRISTIAN GRUBER: And you're configuring the compiler
with the jar, you're not configuring your runtime
with the jar.
MALE SPEAKER: Right, exactly.
It's really the compile time.
CHRISTIAN GRUBER: Yeah, for sure.
MALE SPEAKER: So there's more to it than just [INAUDIBLE] this.
I know there's some nice additional features
that people might want to use that is part of this.
So when it comes to declaring things as being nullable,
for example?
EAMONN MCMANUS: Right, so it does do a certain amount of--
MALE SPEAKER: Optionally?
EAMONN MCMANUS: Optionally, yes.
If you don't specify a parameter as nullable,
then the generated constructor would actually
verify that it's not null.
So there's a few things like that.
We have GWT serialization, G-W-T serialization, for example.
So a few extra bells and whistles like that, yeah.
MALE SPEAKER: OK.
So if you haven't checked it out--
and what is the status of that project?
CHRISTIAN GRUBER: It's in a release candidate.
And we had a discussion yesterday
where we couldn't think of a good reason not to release 1.0.
So I suspect we'll release 1.0 really soon now.
MALE SPEAKER: You heard it here first.
Really soon now.
CHRISTIAN GRUBER: There's a little bit
of touching up in terms of the other features and maybe
some documentation improvements.
But we've been using it in production code at Google
for quite awhile now, at head.
And it hasn't changed much in the last couple of months.
MALE SPEAKER: And it is an open sourced project developed
[INAUDIBLE].
CHRISTIAN GRUBER: It's on GitHub.
It's GitHub, in the Google project space, called Auto,
A-U-T-O.
MALE SPEAKER: OK, great.
So let's switch gears a little bit and talk
about something, Christian, you've
been spending some time on, which is Dagger.
Which is, really when you look at it,
another use of annotation processing, where a lot of work
is done at the compile time so that, in terms of performance
start up time and many other things,
you don't have to do it at run time.
So tell us what is Dagger real quickly, and how it uses ABT.
CHRISTIAN GRUBER: Yeah, so Dagger
is, in essence, a JSR 330 compliant
dependency injection framework.
MALE SPEAKER: At inject.
CHRISTIAN GRUBER: At inject.
You, just like every other dependency injection framework
these days you have classes that you control the constructor
for, and you can mark at inject on the constructor.
And then they declare their dependencies
as constructor parameters.
Or you have a configuration for things
that can't have constructors, like interfaces
that need to be bound.
And we have some annotations at module
for the module configuration classes,
and at provides to declare the methods that
will provide these types that you don't have constructors
for.
And what it does is it looks at these annotation signals
and says, hey, what are the dependencies
that were declared?
And can we satisfy these with all of the things that we know?
And then it just does that work for you.
So traditionally, things like Spring and Juice,
et cetera, would use reflection at run time
to analyze these signals and yank them all together.
And what we wanted was, first of all,
to have some improved performance on Android.
And reflection is pretty slow on dalvik,
and so that was one of the inceptions of Dagger,
one of the motivations for it.
Secondly, we wanted to move errors from runtime,
late in the game, to compile times.
It's always good to move your errors forward.
And with annotation processors, we
found a way that we could generate
code that could do what the reflection did.
Because we did the reflective analysis at compile time.
And we could also omit the errors and warnings,
as Eamonn mentioned, so we could actually turn these wiring
errors that you would normally have
to do some kind of an internal logging
system, or an internal observation,
to figure out what is my wiring, you
can now see it at compile time.
You know when you got it wrong.
And it'll catch cycles and all of these sorts of things.
MALE SPEAKER: So you mentioned that mobile and Android
in particular was the prime motivation.
CHRISTIAN GRUBER: That was the original, yeah.
MALE SPEAKER: The original one.
So has this evolved?
Because it sounds like--
CHRISTIAN GRUBER: It has involved.
MALE SPEAKER: Yes.
There are a number of things you cannot do,
because you're doing stuff at compile time.
So you cannot be as dynamic, and--
CHRISTIAN GRUBER: Yeah.
And to be clear, we've never had it
as a goal to be as fully dynamic as the runtime based
dependency injection systems.
Like Juice will always have more capabilities,
because it can dynamically slurp things up
at the last minute, which we will never
be able to do quite the same.
Although we found that a lot of places where we were using
reflection, like graph analysis for example,
that we're doing at compile time,
there are other kinds of, sort of the assembling of new things
that is often done at reflection, that we found
we can also do at compile time.
So we have some people that had implemented plug-in systems
on top of Juice, and they were trying to use Dagger.
And they were like, well how do we do that?
Because we can't dynamically build the shell
around this thing, because it's static.
And they just turned their plug-in
into a Dagger-like annotation processor system
so they would generate dagger modules which
then our processor would generate the resulting DI
code for.
And it just works amazingly well for that sort of thing.
So we just kept pushing the reflection problem further out
and got a lot of the benefits and even layers
on top of dagger.
It was kind of fascinating.
MALE SPEAKER: So same question is for AutoValue.
What is Dagger 2?
We're talking mostly about Dagger 2 here by the way.
CHRISTIAN GRUBER: I should mention,
so Dagger 1 did the exact same thing that we're talking about.
But Dagger 2, we went fully compile time.
There was still some loading that
was going on in reflection, and we've
eliminated all of that with Dagger 2.
MALE SPEAKER: And then where are we now?
Can I use Dagger 2?
What has Google been doing in terms of contributing and using
Dagger 2?
CHRISTIAN GRUBER: So Dagger 1 was a joint project
with Google and Square.
Dagger 2 is still a joint project
in that Square has been consulting with us and helping,
and we've been workshopping all of the ideas with the Square
guys.
But primarily, the implementation
has been written inside Google.
We are using it in production on a couple of servers
and quite a few Android applications, Dagger 2.
So at head, it works.
It's missing a lot of important things,
like the validations aren't fully built out.
So if you get errors, sometimes in your graph
you'll sometimes get a stack trace
where you should get a nice error.
And that's just stuff we have to improve and work on.
It's in a pre-alpha state.
We haven't released a formal alpha,
but we are pushing snapshots to Sonatype snapshot repositories.
So if you use Maven, you can use Dagger 2 as 2.0 dash snapshot
version, and you'll just get the latest from head.
Every time we push to GitHub, we get a new version pushed out
to Sonatype automatically.
MALE SPEAKER: For those people that
have an issue with snapshots, how long would it be before--?
CHRISTIAN GRUBER: We're hoping to put together
some sort of developer's preview in the next couple of weeks.
MALE SPEAKER: A couple of weeks.
CHRISTIAN GRUBER: We've just updated
the documentation on the website.
So it is actually-- there is some documentation now for 2.0.
So you can get a sense of how to use it.
Now that we've done a couple of talks,
and Jake Wharton's doing a talk later today
here at the conference.
So we think people will be in good shape
to receive a developer preview in the next couple of weeks.
MALE SPEAKER: Great.
CHRISTIAN GRUBER: Yeah.
MALE SPEAKER: So I guess that's all
the time we have for questions.
Eamonn, thank you very much.
AutoValue, Dagger, all powered by annotation processing.
And with super low overhead, no runtime dependency whatsoever.
So thanks for answering my questions.
EAMONN MCMANUS: Yeah, pleasure.
MALE SPEAKER: And do check out those projects.
Thank you very much.
EAMONN MCMANUS: Thank you.
CHRISTIAN GRUBER: Thanks.