-1

I am trying to build graalvm native image of my micronaut application. I see the werid issue that some of the properties from application.yaml are ignored, though when I run the app via

./gradlew run

all works fine.

Here is my yaml

micronaut:
  application:
    name: phonebook
  caches:
    phonebook:
      charset: UTF-8
  router:
    static-resources:
      swagger:
        paths: classpath:META-INF/swagger
        mapping: /swagger/**
      swagger-ui:
        paths: classpath:META-INF/swagger/views/swagger-ui
        mapping: /doc/**

endpoints:
  caches:
    enabled: true
    # sensitive: false
  env:
    enabled: true
   # sensitive: false

fauna:
  secret: '${FAUNA_KEY}'
  endpoint: https://db.eu.fauna.com:443

Here is how I read the properties in the class

@Value("${fauna.secret}")
  private String faunaKey;

@Value("${fauna.endpoint}")
  private String faunaEndpoint;

What could cause an issue?

Alex Bondar
  • 1,167
  • 4
  • 18
  • 35

1 Answers1

1

I know this question has been asked a while ago, but after having spent some hours figuring out the solution to a very similar problem, I thought I'd share the solution here.

I found that apparently the graal compiler throws any private fields away, thus throwing an error saying something like:

Caused by: java.lang.NoSuchFieldError: No field 'value1' found for type: com.example.ConferenceConfig

The solution that worked for me, was to annotate the classes in question with @ReflectiveAccess.

However other solutions also work; use constructor injection or configure src/main/graal/reflect.json

@Factory
public class ConferenceConfig {
    private final String value1;

    public ConferenceConfig(@Value("${my.value1}") final String value1) {
        this.value1 = value1;
    }

    @Context
    public ConferenceConfigBean confBean() {
        return new ConferenceConfigBean(value1);
    }

    public record ConferenceConfigBean(String value) {
        public String getValue() {
            return value;
        }
    }
}

This also works for records:

    @Singleton
    public record ConferenceService(@Value("${my.value1}") String value1) {
    
        private static final List<Conference> CONFERENCES = Arrays.asList(
                new Conference("Greach"),
                new Conference("GR8Conf EU"),
                new Conference("Micronaut Summit"),
                new Conference("Devoxx Belgium"),
                new Conference("Oracle Code One"),
                new Conference("CommitConf"),
                new Conference("Codemotion Madrid")
        );
    public Conference randomConf() {
        return CONFERENCES.get(new Random().nextInt(CONFERENCES.size()));
    }

    public String getV1() {
        return value1;
    }
}

Another