Search code examples
micronautgraalvm

micronaut controller returning empty json in nativeimage


I have a controller in micronaut

package com.mascix.controller;

import java.time.LocalDate;

import javax.ws.rs.core.Response;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;

import io.micronaut.core.annotation.Introspected;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;

@Controller("/hello")
public class GreetController {
    @Get
    public Response hello() {
        return Response.ok(new ApplicationInfo("micronaut", LocalDate.now().getYear())).build();
    }
}

@Introspected
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
class ApplicationInfo {
    public ApplicationInfo(String string, int year) {
        this.name = string;
        this.releaseYear = year;
    }

    String name;
    int releaseYear;
}

which is working fine when I ran from jar and response is

{"name":"micronaut","releaseYear":2022}

when I build the project with graalvm, it return empty json

{}

you can see the whole code here. there is no error or warning in logs. What am I missing ?


Solution

  • I needed to use @ReflectiveAccess for ApplicationInfo.

    package com.mascix.controller;
    
    import java.time.LocalDate;
    
    import javax.ws.rs.core.Response;
    
    import com.fasterxml.jackson.annotation.JsonAutoDetect;
    import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
    
    import io.micronaut.core.annotation.ReflectiveAccess;
    import io.micronaut.http.annotation.Controller;
    import io.micronaut.http.annotation.Get;
    
    @Controller("/hello")
    public class GreetController {
        @Get
        public Response hello() {
            return Response.ok(new ApplicationInfo("micronaut", LocalDate.now().getYear())).build();
        }
    }
    
    @ReflectiveAccess
    @JsonAutoDetect(fieldVisibility = Visibility.ANY)
    class ApplicationInfo {
        public ApplicationInfo(String string, int year) {
            this.name = string;
            this.releaseYear = year;
        }
    
        String name;
        int releaseYear;
    }
    

    And in order to this annotation work I needed to add micronaut-graal to annotationProcessorPaths/path in pom.

        <plugins>
          <plugin>
            <groupId>io.micronaut.build</groupId>
            <artifactId>micronaut-maven-plugin</artifactId>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
              <!-- Uncomment to enable incremental compilation -->
              <!-- <useIncrementalCompilation>false</useIncrementalCompilation> -->
              <annotationProcessorPaths combine.children="append">
                <path>
                  <groupId>io.micronaut</groupId>
                  <artifactId>micronaut-http-validation</artifactId>
                  <version>${micronaut.version}</version>
                </path>
                <path>
                  <groupId>io.micronaut</groupId>
                  <artifactId>micronaut-graal</artifactId>
                  <version>${micronaut.version}</version>
                </path>
              </annotationProcessorPaths>
              <compilerArgs>
                <arg>-Amicronaut.processing.group=com.mascix</arg>
                <arg>-Amicronaut.processing.module=demo</arg>
              </compilerArgs>
            </configuration>
          </plugin>
        </plugins>
    

    see git log and more details