micronaut-core: Lombok + @Introspected generates incorrect parameter names

Summary

The TLDR is that this simple class

@Introspected
@Value
public class Payload {
  private final String id;
}

leads to different parameter names:

// id
Payload.class.getConstructors()[0].getParameters()[0].getName();

// arg0
BeanIntrospection.getIntrospection(Payload.class).getConstructorArguments()[0].getName();

The longer version is that a application.yml:

jackson:
    bean-introspection-module: true

and a controller:

  @Post
  public String create(@Body Payload body) {
    return body.getId();
  }

fails when doing:

POST /bad

{
  "id": "123"
}

with a stack trace like:

io.micronaut.http.client.exceptions.HttpClientResponseException: Failed to convert argument [body] for value [null] due to: Cannot construct instance of `micronaut.introspection.issue.Payload`, problem: Null argument specified for [arg0]. If this argument is allowed to be null annotate it with @Nullable
     at [Source: UNKNOWN; line: -1, column: -1]

It fails in both gradle and maven.

Strangely, it works in eclipse.

Steps to Reproduce

  1. git clone https://github.com/achaphiv/micronaut-introspection-issue
  2. ./gradlew test -i or ./mvnw test

Expected Behaviour

Tests should pass.

Actual Behaviour

Tests fail.

Environment Information

  • Operating System: Mac & Linux
  • Micronaut Version: 1.1.0
  • JDK Version: 1.8.0_202 & 1.8.0_191

Example Application

https://github.com/achaphiv/micronaut-introspection-issue

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 19 (14 by maintainers)

Most upvoted comments

Possibly the problem is that both annotation processors are in the same round. Together with MapStruct, we’ve been working on a way to have multiple annotation processors that have to run in a specific order, including to run in a next round. Could this be the case here as well?

Alternatively, did someone try to generate a java file using an annotation processor that contains the @Introspected annotation? I see that the example project passes the -parameters argument, but I don’t know if javac itself also passes that information to annotation processors for files that are generated.

Confirmed fixed with (finally released) lombok v1.18.16.

In case, when you use Lombok’s @AllArgsConstructor or @RequiredArgsConstructor and Micronaut’s @Introspected there is an issue even if you have processors ordered correctly. Micronaut finds created constructor, but when doing Bean Introspection constructor argument names are: arg0, arg1 etc.

Simple reproducer: https://github.com/asodja/micronaut-lombok-reproducer.

I think MapStruct has similar issues and has special interface that is implemented by Lombok: https://github.com/mapstruct/mapstruct/blob/12bfff8f46c00b22c384f9441d2928b2e588406d/processor/src/main/java/org/mapstruct/ap/spi/AstModifyingAnnotationProcessor.java. With that it can wait a round before visiting the type that is handled by Lombok.

Thanks for noticing, @SchulteMarkus , the link is now corrected 🙈