onX was introduced as experimental feature in lombok v0.11.8.


Experimental because:

  • Ugly syntax. The syntax of this feature is not optimal, but it is the least convoluted syntax that could possibly work (for now!)
  • Possibly java 9 will offer (much) better ways of supporting this feature.
  • Uncertainty: Future versions of javac may break this feature, and we may not be able to restore it.
Current status: uncertain - Currently we feel this feature cannot move out of experimental status.


This feature is considered 'workaround status' - it exists in order to allow users of lombok that cannot work without this feature to have access to it anyway. If we find a better way to implement this feature, or some future java version introduces an alternative strategy, this feature can disappear without a reasonable deprecation period. Also, this feature may not work in future versions of javac. Use at your own discretion.

Most annotations that make lombok generate methods or constructors can be configured to also make lombok put custom annotations on elements in the generated code.

@Getter, @Setter, and @Wither support the onMethod option, which will put the listed annotations on the generated method.

@AllArgsConstructor, @NoArgsConstructor, and @RequiredArgsConstructor support the onConstructor option which will put the listed annotations on the generated constructor.

@Setter and @Wither support onParam in addition to onMethod; annotations listed will be put on the only parameter that the generated method has. @EqualsAndHashCode also supports onParam; the listed annotation(s) will be placed on the single parameter of the generated equals method, as well as any generated canEqual method.

The syntax is a little strange and depends on the javac you are using.
On javac7, 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.
On javac8 and up, you add an underscore after onMethod, onParam, or onConstructor.

With Lombok

01 import lombok.AllArgsConstructor;
02 import lombok.Getter;
03 import lombok.Setter;
05 import javax.inject.Inject;
06 import javax.persistence.Id;
07 import javax.persistence.Column;
08 import javax.validation.constraints.Max;
10 @AllArgsConstructor(onConstructor=@__(@Inject))
11 public class OnXExample {
12 //  @Getter(onMethod=@__({@Id, @Column(name="unique-id")})) //JDK7
13 //  @Setter(onParam=@__(@Max(10000))) //JDK7
14   @Getter(onMethod_={@Id@Column(name="unique-id")}) //JDK8
15   @Setter(onParam_=@Max(10000)) //JDK8
16   private long unid;
17 }

Vanilla Java

01 import javax.inject.Inject;
02 import javax.persistence.Id;
03 import javax.persistence.Column;
04 import javax.validation.constraints.Max;
06 public class OnXExample {
07   private long unid;
09   @Inject
10   public OnXExample(long unid) {
11     this.unid = unid;
12   }
14   @Id @Column(name="unique-id")
15   public long getUnid() {
16     return unid;
17   }
19   public void setUnid(@Max(10000long unid) {
20     this.unid = unid;
21   }
22 }

Small print

The reason of the weird syntax is to make this feature work in javac 7 compilers; the @__ type is an annotation reference to the annotation type __ (double underscore) which doesn't actually exist; this makes javac 7 delay aborting the compilation process due to an error because it is possible an annotation processor will later create the __ type. Instead, lombok applies the annotations and removes the references so that the error will never actually occur. The point is: The __ type must not exist, otherwise the feature does not work. In the rare case that the __ type does exist (and is imported or in the package), you can simply add more underscores. Technically any non-existent type would work, but to maintain consistency and readability and catch erroneous use, lombok considers it an error if the 'wrapper' annotation is anything but a series of underscores.

In javac8, the above feature should work but due to a bug in javac8 it does not. However, starting in javac8, if the parameter name does not exist in the annotation type, compilation proceeds to a phase where lombok can fix it.

To reiterate: This feature can disappear at any time; if you use this feature, be prepared to adjust your code when we find a nicer way of implementing this feature, or, if a future version of javac forces us to remove this feature entirely with no alternative.

The onX parameter is not legal on any type-wide variant. For example, a @Getter annotation on a class does not support onMethod.