Skip to content
This repository has been archived by the owner on Feb 23, 2023. It is now read-only.

Lombok copyable annotations not working with spring graalvm native #381

Closed
ArjanSchouten opened this issue Nov 24, 2020 · 3 comments
Closed
Labels
status: declined A suggestion or change that we don't feel we should currently apply

Comments

@ArjanSchouten
Copy link

ArjanSchouten commented Nov 24, 2020

The lombok feature lombok.copyableannotations (https://projectlombok.org/features/constructor) together with a RequiredArgsConstructor and a Spring @Value annotation do not work with the following code:

@ToString
@Component
@RequiredArgsConstructor
public class NotWorking {
    @Value("${graalvm.native.is}")
    public final String springGraalNativeIs;
}

However this works:

@ToString
@Component
public class Working {
    public final String springGraalNativeIs;

    public Working(@Value("${graalvm.native.is}")
                       String springGraalNativeIs) {
        this.springGraalNativeIs = springGraalNativeIs;
    }
}

The output when building with graalvm native is:

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-11-24 20:29:31.777 ERROR 1 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'work.NotWorking': Injection of autowired dependencies failed; nested exception is java.lang.IllegalAccessException: Cannot set final field: com.example.demo.Work$NotWorking.springGraalNativeIs. Enable by specifying "allowWrite" for this field in the reflection configuration.
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:405) ~[com.example.demo.DemoApplication:5.3.1]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1415) ~[na:na]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:608) ~[na:na]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531) ~[na:na]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[na:na]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[na:na]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[na:na]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[na:na]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[na:na]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925) ~[na:na]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:588) ~[na:na]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767) ~[na:na]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) ~[na:na]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) ~[na:na]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) ~[na:na]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1309) ~[na:na]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1298) ~[na:na]
	at com.example.demo.DemoApplication.main(DemoApplication.java:16) ~[com.example.demo.DemoApplication:na]
Caused by: java.lang.IllegalAccessException: Cannot set final field: com.example.demo.Work$NotWorking.springGraalNativeIs. Enable by specifying "allowWrite" for this field in the reflection configuration.
	at java.lang.reflect.Field.set(Field.java:780) ~[na:na]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:667) ~[na:na]
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[na:na]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[com.example.demo.DemoApplication:5.3.1]
	... 17 common frames omitted

Steps to reproduce (requires docker):

git clone git@github.com:ArjanSchouten/lombok-value-constructor.git
cd lombok-value-constructor
./gradlew clean bootRun # This works and logs the expected results

# Following doesn't work as expected
./gradlew clean bootBuildImage
docker run --name demo demo:0.0.1-SNAPSHOT

Is this a bug in spring-graalvm-native?

Spring-graalvm-native version: 0.8.3
Spring boot version: 2.4.0
Java version: 11.0.9

@sdeleuze sdeleuze added the status: waiting-for-triage An issue we've not yet triaged or decided on label Nov 25, 2020
@aclement
Copy link
Contributor

aclement commented Dec 7, 2020

Yes I think we could do better here. If you want your app to work, place this in src/main/resources/META-INF/native-image/reflect-config.json:

[
{
  "name":"com.example.demo.Work$NotWorking",
  "allDeclaredFields":true,
  "fields": [
          {"name":"springGraalNativeIs","allowWrite": true }
  ],
  "allDeclaredMethods":true,
  "allDeclaredConstructors":true
}
]

@aclement aclement added in: feature and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Dec 7, 2020
@ArjanSchouten
Copy link
Author

Thanks. Isn't it more a general issue with Lombok? For example using Lombok with Jackson won't work without a reflect-config.json.

@sdeleuze
Copy link
Contributor

Lombok generally work well with Spring Native, it is possible that some Lombok feature will require some configuration. See for example a52d9f1 where we added a sample and some Lombok hint. For now you can just define native hints on your application. If you think something deserves dedicated support after testing the latest Spring Native version, please create a new issue with an attached repro project.

@sdeleuze sdeleuze added the status: declined A suggestion or change that we don't feel we should currently apply label Mar 29, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
status: declined A suggestion or change that we don't feel we should currently apply
Development

No branches or pull requests

3 participants