Guice / injection

2,453 views
Skip to first unread message

jon.mithe

unread,
Apr 1, 2014, 11:30:31 AM4/1/14
to project...@googlegroups.com
Hi,

Love lombok but having difficulties with Guice / injection.  I've looked around the site + forums and I see a few things but I'm not seeing anything I can use so wandering if there are any plans for anything else or I had a couple idea's I was looking to implement.

Either something simple like an @InjectRequiredArgsConstructor where it does required args but just adds @Inject would probably solve 90% of cases with anything more fancy requiring a hand rolled constuctor.  Its not perfect, but would remove alot of boilerplate from my apps.

The other idea I was playing with / may try is to generate a constructor based off of annotations in the field declaration, but I dont know exactly what is possible in the ast.

for example something like this:

@InjectRequredConstructorArgs
class A {
    @Assisted private final MyClass a;
    @Named("bill")  private final OtherDependency b;
}

is rewritten:

class A {
  private final MyClass a;
  private final OtherDependency B;
    @Inject 
    A(@Assisted Myclass a, @Named("bill") OtherDependency b)  {
      this.a = a;
      this.b = b
    }
}
 

Essentially the idea being the constructor is generated from required args and any annotations on the field are added to the declaration in the constructor and stripped from the final output on  the fields.  If annotations are needed for the fields, I think ordering is preserved so you could do something like (but with sensible names):

@NonNull @MyAnnotionan @FollowingAnnotationsStrippedToConstructor @Assisted MyClass a

creates the field:

@NonNull @MyAnnotionan  MyClass a

I'm not exactly sure how much is possibly with the AST / rewriting.  I could see annotations with arguments, e.g. @Named("server"),  being problematic, but then again, they are quite brittle / horrible anyway and a custom annotation would be safer, i.e. do @MyCustomAnnotation MyClass instead, so just supporting no arg annotations you could get 100% boiler plate removal with good design.

I see alot of the thought on posts has been about gentrifying annotations, so finding ways of expressing annotations with annotations and overloading, basically making required args constructor to almost polymorphic / multifunctional.  Similar to Getter with lazy boolean but on steroids.

I think some specific custom annotations for it is reasonable / would be cleaner and more understandable than overloading existing annotations.  Behind the scenes they can share common code.  Especially as its got to the point now where injection  is going to be standard.

Cheers,
Jon


Martin Grajcar

unread,
Apr 1, 2014, 12:11:20 PM4/1/14
to project...@googlegroups.com
On Tue, Apr 1, 2014 at 5:30 PM, jon.mithe <jon....@gmail.com> wrote:
Either something simple like an @InjectRequiredArgsConstructor where it does required args but just adds @Inject would probably solve 90% of cases with anything more fancy requiring a hand rolled constuctor.  Its not perfect, but would remove alot of boilerplate from my apps.

It already exists and I love it:
@RequiredArgsConstructor(onConstructor=@__(@Inject))

The two underscores are there in order to avoid a JDK9 warning, IIRC one would do as well.

jon.mithe

unread,
Apr 1, 2014, 12:40:18 PM4/1/14
to project...@googlegroups.com
Thanks, unfortunately that was one I was trying to avoid as from what I understand it's an experimental feature / essentially a hack that may disappear in later versions.  Also hoping for something maybe a little cleaner, it may have to do.

Thanks.

Martin Grajcar

unread,
Apr 1, 2014, 1:04:17 PM4/1/14
to project...@googlegroups.com
I'm pretty sure there's no non-experimental thing that could help. The problem with onConstructor is that it's a hack and the reason for this hack is that nothing else works (while annotations can accept other annotations as arguments, they can't accept an arbitrary annotation). I guess it works for JDK9 (at least nobody complained yet) and IMHO it won't go away until it either gets broken by JDK10 or something really better gets invented.

There's no chance of making user-defined annotation,
so even when Oracle decided to support everything Lombok users ever dreamt about, the best thing you could get is

@RequiredArgsConstructor(onConstructor=@Inject)

instead of

@RequiredArgsConstructor(onConstructor=@__(@Inject))


--
You received this message because you are subscribed to the Google Groups "Project Lombok" group.
To unsubscribe from this group and stop receiving emails from it, send an email to project-lombo...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

jon.mithe

unread,
Apr 1, 2014, 1:35:38 PM4/1/14
to project...@googlegroups.com
Interesting.  Parameters and annotations in annotations makes me shiver a little, especially when you get to addressing things like assisted or annotated injections.

So as far as I understand the second thing I was talking about, annotating field variables with annotations and rewriting the annotations in the constructor declarations should be possible? -- i.e. annotations arn't being passed into annotations here.

The configuration stuff looks cool but seems like assisted/named/custom annotations would still be problematic, it';d be cool if annotations on the field variables in some way could be transferred as that would do the trick.

I realise there is a concern here about bloat so I doubt more specific annotations will ever happen, especially with permutation issues when you get into the more meta-annotations like @Data.

Thanks,
Jon

Fabrizio Giudici

unread,
Apr 1, 2014, 2:07:18 PM4/1/14
to project...@googlegroups.com, jon.mithe
On Tue, 01 Apr 2014 19:35:38 +0200, jon.mithe <jon....@gmail.com> wrote:

> Interesting. Parameters and annotations in annotations makes me shiver a
> little, especially when you get to addressing things like assisted or
> annotated injections.

Just for completeness, let me recall that annotations in annotations are
used by many standard frameworks, such as JEE - sure, not for generating
code. Just to say it's not an uncommon practice from a formal point of
view.

--
Fabrizio Giudici - Java Architect @ Tidalwave s.a.s.
"We make Java work. Everywhere."
http://tidalwave.it/fabrizio/blog - fabrizio...@tidalwave.it

Martin Grajcar

unread,
Apr 1, 2014, 2:27:58 PM4/1/14
to project...@googlegroups.com
On Tue, Apr 1, 2014 at 7:35 PM, jon.mithe <jon....@gmail.com> wrote:
Interesting.  Parameters and annotations in annotations makes me shiver a little, especially when you get to addressing things like assisted or annotated injections.

I see no problem there except for some confusion due to nesting. As Lombok comes before Guice, which only sees the transformed result, it must work.
 
So as far as I understand the second thing I was talking about, annotating field variables with annotations and rewriting the annotations in the constructor declarations should be possible? -- i.e. annotations arn't being passed into annotations here.

I guess it should be possible, actually I proposed such an annotation migration some long time ago. But the current approach using @__ was chosen and I agree that it's better.

What also works is

Setter(onParam=@__(@Named("bill")))

so I believe that

OnConstructorParam=@__(@Named("bill"))

should be easy to implement. Google told me I've already proposed it
and I told myself it should be tracked somewhere:
 
The configuration stuff looks cool but seems like assisted/named/custom annotations would still be problematic, it';d be cool if annotations on the field variables in some way could be transferred as that would do the trick.

Yes, but this can get complicated... there are 4 possible targets (getter, setter, setter argument, constructor argument) and each combination makes sense. In addition you may want to leave the annotation where it is, so 31 combinations make sense to me.

I realise there is a concern here about bloat so I doubt more specific annotations will ever happen, especially with permutation issues when you get into the more meta-annotations like @Data.

Sure, it is already pretty complicated.

Krzysztof Makowski

unread,
May 30, 2014, 6:35:06 AM5/30/14
to project...@googlegroups.com
"Either something simple like an @InjectRequiredArgsConstructor where it does required args but just adds @Inject would probably solve 90% of cases with anything more fancy requiring a hand rolled constuctor.  Its not perfect, but would remove alot of boilerplate from my apps."

+1 

I would love to have this annotation in lombok.

Reinier Zwitserloot

unread,
Jul 1, 2014, 9:09:38 PM7/1/14
to project...@googlegroups.com
Sigh, another day, another issue with @__. There's a bug introduced somewhere in the late stages of the final days of JDK1.8.0's release which shows up in extremely rare cases.... and, _always_, when using the onMethod/onConstructor/onParam @__ syntax, if you're trying to add annotations that have named arguments in them. There's absolutely nothing we can do about it, except report it to oracle, pray they understand it's a bug on their end, and that they fix it within a reasonable time frame and in such a way that our 'trick' still works.

With that in mind, given the popularity of @Inject, and the fact that @Inject takes no arguments (It's always just @Inject, never @Inject(foo=bar), right?), I'm starting to warm up to the idea of just giving up on an 'elegant' solution and introducing some sort of lombok.extern.AddInject annotation.

Roel has used guice before and has cooled to the concept. It's been on my 'I gotta try it sometime' list with just a small niggle of worry, but Roel's experience pretty much nailed exactly what I was worried about (a bit off-topic to go into here). At any rate, the upshot is: We don't use guice nor any other framework that uses @Inject anymore, so we need some community help. What would you like to write, and what should lombok desugar it to?

Martin Grajcar

unread,
Jul 2, 2014, 4:58:38 AM7/2/14
to project...@googlegroups.com
On Wed, Jul 2, 2014 at 3:09 AM, Reinier Zwitserloot <rein...@gmail.com> wrote:
Sigh, another day, another issue with @__. There's a bug introduced somewhere in the late stages of the final days of JDK1.8.0's release which shows up in extremely rare cases.... and, _always_, when using the onMethod/onConstructor/onParam @__ syntax, if you're trying to add annotations that have named arguments in them. There's absolutely nothing we can do about it, except report it to oracle, pray they understand it's a bug on their end, and that they fix it within a reasonable time frame and in such a way that our 'trick' still works.

With that in mind, given the popularity of @Inject, and the fact that @Inject takes no arguments (It's always just @Inject, never @Inject(foo=bar), right?),

Right. There are Guice Inject and javax Inject, the former accepts a boolean, but I have used it maybe once or twice.
 
I'm starting to warm up to the idea of just giving up on an 'elegant' solution and introducing some sort of lombok.extern.AddInject annotation.

I wouldn't be opposed. I'm working on a small project and nearly half of my classes gets
@RequiredArgsConstructor(onConstructor=@__(@Inject))
on them, so something more compact would be nice. Actually, it should be always access PROTECTED, or PRIVATE but I tend to always forget it. FWIW, nearly all other classes get lone @RequiredArgsConstructor, and there's no single other XArgsConstructor.
 
Roel has used guice before and has cooled to the concept. It's been on my 'I gotta try it sometime' list with just a small niggle of worry, but Roel's experience pretty much nailed exactly what I was worried about (a bit off-topic to go into here). At any rate, the upshot is: We don't use guice nor any other framework that uses @Inject anymore, so we need some community help. What would you like to write, and what should lombok desugar it to?

I'm currently quite happy with what exists. I'm just occasionally avoiding the need to use annotations on constructor arguments by creating trivial subclasses or whatever. As this could get cumbersome in a bigger project, I started to write OnConstructor(onParam=...).

The most commonly used annotations are @Named and @Assisted, both having a String argument. Some avoid @Named because of its stringly typed argument and use own (usually paramerless) annotations instead.

I guess, whenever AddInject gets used, @Named on a field can be simply copied (or maybe moved) to the constructor argument. People actually using it can surely say more.
Reply all
Reply to author
Forward
0 new messages