30

I have been working with and actively using Lombok for 2 months. With Java I'm a little more familiar. But, for the first time, I was faced with the following syntax structure in the language:

@RequiredArgsController(onController = @__(@Autowired))
                                       ^^^

What does that mean, and how does it get compiled?

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
  • 1
    Some digging turned this: https://projectlombok.org/features/experimental/onX.html: *the `@__` type is an annotation reference to the annotation type `__` (double underscore) which doesn't actually exist*. I know nothing about Lombok though. ([also this mail](https://groups.google.com/forum/#!topic/project-lombok/PA8V-RNdAcU)) – Tunaki Jun 27 '16 at 16:32

3 Answers3

31

This is an experimental Lombok syntax, created to support a layer of indirection when referencing multiple annotations, rather than use a Class<?>[].

The syntax is a little strange; to use any of the 3 onX features, you must wrap the annotations to be applied to the constructor / method / parameter in @__(@AnnotationGoesHere). To apply multiple annotations, use @__({@Annotation1, @Annotation2}). The annotations can themselves obviously have parameters as well.

https://projectlombok.org/features/experimental/onX.html

An explanation from Lombok developer Roel Spilker:

The reason for it is that javac already resolves annotations in the parsing phase, and gives errors if it can determine that the annotations are invalid. By using a non-existent annotation @__ it cannot determine it is bogus (it might be created by an annotation processor) and will not give an error right away. That gives Lombok the time to do its work and remove the @__ from the code.

Community
  • 1
  • 1
OrangeDog
  • 36,653
  • 12
  • 122
  • 207
  • 11
    The reason for it is that javac already resolves annotations in the parsing phase, and gives errors if it can determine that the annotations are invalid. By using a non-existent annotation `@__` it cannot determine it is bogus (it might be created by an annotation processor) and will not give an error right away. That gives Lombok the time to do its work and remove the `@__` from the code. – Roel Spilker Jun 28 '16 at 08:43
  • @RoelSpilker does this mean it could have been anything else? Like `@placeholder_annotation` or `@temp_annotation` or `@ignore_this_it_is_ephemeral` – asgs Jan 10 '23 at 19:53
12

It means that the generated constructor (not controller) will also have the @Autowired annotation added to it so that spring can do its magic. With lombok you can write your code like

@RequiredArgsConstructor(onConstructor=@__(@Autowired(required=true)))
public class FooController {
    private final FooService service;
    interface FooService {}
}

and lombok will convert it during compilation to

public class FooController {
    private final FooService service;
    @Autowired(required=true)
    public FooController(FooService service) {
        this.service = service;
    }
}

@__ is used to overcome the type limitations of annotations because

@interface MultipleAnnotations {
    Annotation[] value();
}

does not work because the supertype of all annotations is itself not an annotation and

@interface MultipleAnnotations {
    Class<? extends Annotation>[] value();
}

does not allow parameters in annotations: @MultipleAnnotations(SomeAnnotation.class)

zapl
  • 63,179
  • 10
  • 123
  • 154
  • Could have just used `Class[]` though, and checked `isAnnotation()` during compilation. – OrangeDog Jun 27 '16 at 17:00
  • 1
    @OrangeDog that would not allow parameters in annotations – zapl Jun 27 '16 at 17:01
  • 3
    The lombok team has [submitted a proposal](https://projectlombok.org/anyannotation/) to add the possibilities for Annotation[] to annotations, but it had been rejected. Maybe we can revive it some day... – Roel Spilker Jun 28 '16 at 09:05
6

For JDK8 users who are confused about this weird syntax, there is a little bit cleaner way as mentioned here - On javac8 and up, you add an underscore after onMethod, onParam, or onConstructor.

So it will change from @RequiredArgsController(onController = @__(@Autowired)) to @RequiredArgsController(onController_ = @Autowired)

sinujohn
  • 2,506
  • 3
  • 21
  • 26
  • 3
    i think its a @RequiredArgsConstructor(onConstructor_ = @Autowired) not @RequiredArgsController – Krishna Oct 15 '20 at 06:28
  • This is where explicit methods are much preferable over Lombok (or similar) implicit declarations. The explicit case makese it easy to grep the code for references and quick scan for a human to see the data/dependency flow. Concise is good, but terse is when you take it too far. Remember, other people have to be able to read your code. – Charlie Reitzel Jul 14 '23 at 13:44