[ https://issues.apache.org/jira/browse/GROOVY-11409?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
msangel updated GROOVY-11409: ----------------------------- Description: I have a code that works in java. its sample spring-boot application: {code:java} package com.example.demo; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.event.EventListener; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import javax.persistence.*; @SpringBootApplication @EnableJpaRepositories(considerNestedRepositories = true) @Slf4j public class DemoApplication { @Getter @Setter @Entity @Table(name = "record") public static class Record { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; private String data; } @Repository @Transactional(isolation = Isolation.SERIALIZABLE) interface RecordRepository extends CrudRepository<Record, Long> { } @Autowired private DemoApplication.RecordRepository recordRepository; @EventListener(ApplicationReadyEvent.class) public void ready() { Iterable<DemoApplication.Record> all = recordRepository.findAll(); if (all.iterator().hasNext()) { throw new IllegalStateException("There should be no records"); } recordRepository.save(new DemoApplication.Record()); all = recordRepository.findAll(); if (!all.iterator().hasNext()) { throw new IllegalStateException("There should be records"); } log.info("All good"); } public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args).close(); } } {code} And its property file (application.yaml): {code:java} server: port: 8080 spring: sql: init: platform: sqlite mode: always datasource: url: "jdbc:sqlite::memory:" username: password: driver-class-name: org.sqlite.JDBC jpa: database-platform: org.sqlite.hibernate.dialect.SQLiteDialect show-sql: false defer-datasource-initialization: true hibernate: ddl-auto: create jdbc: time_zone: UTC open-in-view: false {code} Running it works as expected, "All good" is shown into console. After converting the same code to groovy this code fail. The error is: {code:java} No qualifying bean of type 'com.example.demo2.DemoApplication$RecordRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} {code} So, the spring is not seeing static nested class IF it is in groovy. This is the groove code I run: {code:java} package com.example.demo2 @GrabConfig @Grab(group = 'org.springframework.boot', module = 'spring-boot-starter-web', version = '2.7.18') @Grab(group = 'org.xerial', module = 'sqlite-jdbc', version = '3.45.3.0') @Grab(group = 'org.springframework.boot', module = 'spring-boot-starter-data-jpa', version = '2.7.18') @Grab(group = 'com.github.gwenn', module = 'sqlite-dialect', version = "0.1.4") @Grab(group = 'jakarta.persistence', module = 'jakarta.persistence-api', version = '2.2.2') @GrabExclude(group = 'javax.persistence', module='javax.persistence-api') @Grab(group = 'org.jboss.spec.javax.transaction', module = 'jboss-transaction-api_1.2_spec', version = '1.1.1.Final') @GrabExclude(group = 'org.jboss.spec.javax.transaction', module='jboss-transaction-api_1.2_spec') @Grab(group = 'jakarta.transaction', module = 'jakarta.transaction-api', version = '1.3.1') @Grab(group = 'com.zaxxer', module = 'HikariCP', version = '5.1.0') @Grab(group='org.slf4j', module='slf4j-simple', version='2.0.13') @Grab(group='org.slf4j', module='slf4j-api', version='2.0.13') @Grab(group='cglib', module='cglib', version='3.2.4') import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.event.ApplicationReadyEvent import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional import org.springframework.context.event.EventListener import javax.persistence.Entity import javax.persistence.GeneratedValue import javax.persistence.GenerationType import javax.persistence.Id import javax.persistence.Table @SpringBootApplication @EnableJpaRepositories(considerNestedRepositories = true) class DemoApplication { @Entity @Table(name = "record") static class Record { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id private String data } @Repository @Transactional(isolation = Isolation.SERIALIZABLE) interface RecordRepository extends CrudRepository<Record, Long> { } @Autowired private DemoApplication.RecordRepository recordRepository; @EventListener(ApplicationReadyEvent.class) void ready() { Iterable<DemoApplication.Record> all = recordRepository.findAll(); if (all.iterator().hasNext()) { throw new IllegalStateException("There should be no records"); } recordRepository.save(new DemoApplication.Record()); all = recordRepository.findAll(); if (!all.iterator().hasNext()) { throw new IllegalStateException("There should be records"); } System.out.println("All good"); } static void main(String[] args) { SpringApplication.run(DemoApplication.class, args).close(); } } {code} I run it with this script: {code:java} #!/bin/env bash groovy -version java -version cd groovy && groovy src/com/example/demo2/DemoApplication.groovy --spring.config.location=application.yaml {code} Ans this is output (boht java case and groovy case): {code:java} ✔ nb6:~/work/bugreport> ./run_java.sh [INFO] Scanning for projects... [INFO] [INFO] --------------------------< com.example:demo >-------------------------- [INFO] Building demo 0.0.1-SNAPSHOT [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- exec-maven-plugin:3.3.0:java (default-cli) @ demo --- . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.7.18)2024-06-16 02:47:55.694 INFO 71733 --- [lication.main()] com.example.demo.DemoApplication : Starting DemoApplication using Java 17 on nb6 with PID 71733 (/home/msangel/work/bugreport/java/target/classes started by msangel in /home/msangel/work/bugreport/java) 2024-06-16 02:47:55.697 INFO 71733 --- [lication.main()] com.example.demo.DemoApplication : No active profile set, falling back to 1 default profile: "default" 2024-06-16 02:47:56.092 INFO 71733 --- [lication.main()] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. 2024-06-16 02:47:56.126 INFO 71733 --- [lication.main()] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 26 ms. Found 1 JPA repository interfaces. 2024-06-16 02:47:56.512 INFO 71733 --- [lication.main()] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default] 2024-06-16 02:47:56.551 INFO 71733 --- [lication.main()] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.6.15.Final 2024-06-16 02:47:56.685 INFO 71733 --- [lication.main()] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.2.Final} 2024-06-16 02:47:56.755 INFO 71733 --- [lication.main()] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.sqlite.hibernate.dialect.SQLiteDialect 2024-06-16 02:47:56.793 INFO 71733 --- [lication.main()] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2024-06-16 02:47:56.927 INFO 71733 --- [lication.main()] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2024-06-16 02:47:56.935 INFO 71733 --- [lication.main()] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.sqlite.hibernate.dialect.SQLiteDialect 2024-06-16 02:47:57.377 INFO 71733 --- [lication.main()] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] 2024-06-16 02:47:57.388 INFO 71733 --- [lication.main()] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2024-06-16 02:47:57.724 INFO 71733 --- [lication.main()] com.example.demo.DemoApplication : Started DemoApplication in 2.489 seconds (JVM running for 4.638) 2024-06-16 02:47:57.874 INFO 71733 --- [lication.main()] com.example.demo.DemoApplication : All good 2024-06-16 02:47:57.877 INFO 71733 --- [lication.main()] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' 2024-06-16 02:47:57.879 INFO 71733 --- [lication.main()] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... 2024-06-16 02:47:57.882 INFO 71733 --- [lication.main()] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed. [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 3.851 s [INFO] Finished at: 2024-06-16T02:47:57+02:00 [INFO] ------------------------------------------------------------------------{code} {code:java} ✔ nb6:~/work/bugreport> ./run_groovy.sh Groovy Version: 4.0.21 JVM: 17 Vendor: Oracle Corporation OS: Linux openjdk version "17" 2021-09-14 OpenJDK Runtime Environment (build 17+35-2724) OpenJDK 64-Bit Server VM (build 17+35-2724, mixed mode, sharing) SLF4J(W): No SLF4J providers were found. SLF4J(W): Defaulting to no-operation (NOP) logger implementation SLF4J(W): See https://www.slf4j.org/codes.html#noProviders for further details. . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.7.18)Caught: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'demoApplication': Unsatisfied dependency expressed through field 'recordRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo2.DemoApplication$RecordRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'demoApplication': Unsatisfied dependency expressed through field 'recordRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo2.DemoApplication$RecordRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:713) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:693) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:408) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:929) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:591) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:409) at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1289) at com.example.demo2.DemoApplication.main(DemoApplication.groovy:70) Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo2.DemoApplication$RecordRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1801) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1357) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:710) ... 20 more ✘-1 nb6:~/work/bugreport> {code} Why the groovy version is not working with literally the same code? was: I have a code that works in java. its sample spring-boot application: {code:java} package com.example.demo; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.event.EventListener; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; import javax.persistence.*; @SpringBootApplication @EnableJpaRepositories(considerNestedRepositories = true) @Slf4j public class DemoApplication { @Getter @Setter @Entity @Table(name = "record") public static class Record { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; private String data; } @Repository @Transactional(isolation = Isolation.SERIALIZABLE) interface RecordRepository extends CrudRepository<Record, Long> { } @Autowired private DemoApplication.RecordRepository recordRepository; @EventListener(ApplicationReadyEvent.class) public void ready() { Iterable<DemoApplication.Record> all = recordRepository.findAll(); if (all.iterator().hasNext()) { throw new IllegalStateException("There should be no records"); } recordRepository.save(new DemoApplication.Record()); all = recordRepository.findAll(); if (!all.iterator().hasNext()) { throw new IllegalStateException("There should be records"); } log.info("All good"); } public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args).close(); } } {code} And its property file (application.yaml): {code:java} server: port: 8080 spring: sql: init: platform: sqlite mode: always datasource: url: "jdbc:sqlite::memory:" username: password: driver-class-name: org.sqlite.JDBC jpa: database-platform: org.sqlite.hibernate.dialect.SQLiteDialect show-sql: false defer-datasource-initialization: true hibernate: ddl-auto: create jdbc: time_zone: UTC open-in-view: false {code} Running it works as expected, "All good" is shown into console. After converting the same code to groovy this code fail. The error is: {code:java} No qualifying bean of type 'com.example.demo2.DemoApplication$RecordRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} {code} So, the spring is not seeing static nested class IF it is in groovy. This is the groove code I run: {code:java} package com.example.demo2 @GrabConfig @Grab(group = 'org.springframework.boot', module = 'spring-boot-starter-web', version = '2.7.18') @Grab(group = 'org.xerial', module = 'sqlite-jdbc', version = '3.45.3.0') @Grab(group = 'org.springframework.boot', module = 'spring-boot-starter-data-jpa', version = '2.7.18') @Grab(group = 'com.github.gwenn', module = 'sqlite-dialect', version = "0.1.4") @Grab(group = 'jakarta.persistence', module = 'jakarta.persistence-api', version = '2.2.2') @GrabExclude(group = 'javax.persistence', module='javax.persistence-api') @Grab(group = 'org.jboss.spec.javax.transaction', module = 'jboss-transaction-api_1.2_spec', version = '1.1.1.Final') @GrabExclude(group = 'org.jboss.spec.javax.transaction', module='jboss-transaction-api_1.2_spec') @Grab(group = 'jakarta.transaction', module = 'jakarta.transaction-api', version = '1.3.1') @Grab(group = 'com.zaxxer', module = 'HikariCP', version = '5.1.0') @Grab(group='org.slf4j', module='slf4j-simple', version='2.0.13') @Grab(group='org.slf4j', module='slf4j-api', version='2.0.13') @Grab(group='cglib', module='cglib', version='3.2.4') import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.event.ApplicationReadyEvent import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional import org.springframework.context.event.EventListener import javax.persistence.Entity import javax.persistence.GeneratedValue import javax.persistence.GenerationType import javax.persistence.Id import javax.persistence.Table @SpringBootApplication @EnableJpaRepositories(considerNestedRepositories = true) class DemoApplication { @Entity @Table(name = "record") static class Record { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long id private String data } @Repository @Transactional(isolation = Isolation.SERIALIZABLE) interface RecordRepository extends CrudRepository<Record, Long> { } @Autowired private DemoApplication.RecordRepository recordRepository; @EventListener(ApplicationReadyEvent.class) void ready() { Iterable<DemoApplication.Record> all = recordRepository.findAll(); if (all.iterator().hasNext()) { throw new IllegalStateException("There should be no records"); } recordRepository.save(new DemoApplication.Record()); all = recordRepository.findAll(); if (!all.iterator().hasNext()) { throw new IllegalStateException("There should be records"); } log.info("All good"); } static void main(String[] args) { SpringApplication.run(DemoApplication.class, args).close(); } } {code} I run it with this script: {code:java} #!/bin/env bash groovy -version java -version cd groovy && groovy src/com/example/demo2/DemoApplication.groovy --spring.config.location=application.yaml {code} Ans this is output (boht java case and groovy case): {code:java} ✔ nb6:~/work/bugreport> ./run_java.sh [INFO] Scanning for projects... [INFO] [INFO] --------------------------< com.example:demo >-------------------------- [INFO] Building demo 0.0.1-SNAPSHOT [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- exec-maven-plugin:3.3.0:java (default-cli) @ demo --- . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.7.18)2024-06-16 02:47:55.694 INFO 71733 --- [lication.main()] com.example.demo.DemoApplication : Starting DemoApplication using Java 17 on nb6 with PID 71733 (/home/msangel/work/bugreport/java/target/classes started by msangel in /home/msangel/work/bugreport/java) 2024-06-16 02:47:55.697 INFO 71733 --- [lication.main()] com.example.demo.DemoApplication : No active profile set, falling back to 1 default profile: "default" 2024-06-16 02:47:56.092 INFO 71733 --- [lication.main()] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. 2024-06-16 02:47:56.126 INFO 71733 --- [lication.main()] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 26 ms. Found 1 JPA repository interfaces. 2024-06-16 02:47:56.512 INFO 71733 --- [lication.main()] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default] 2024-06-16 02:47:56.551 INFO 71733 --- [lication.main()] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.6.15.Final 2024-06-16 02:47:56.685 INFO 71733 --- [lication.main()] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.2.Final} 2024-06-16 02:47:56.755 INFO 71733 --- [lication.main()] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.sqlite.hibernate.dialect.SQLiteDialect 2024-06-16 02:47:56.793 INFO 71733 --- [lication.main()] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2024-06-16 02:47:56.927 INFO 71733 --- [lication.main()] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2024-06-16 02:47:56.935 INFO 71733 --- [lication.main()] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.sqlite.hibernate.dialect.SQLiteDialect 2024-06-16 02:47:57.377 INFO 71733 --- [lication.main()] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] 2024-06-16 02:47:57.388 INFO 71733 --- [lication.main()] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2024-06-16 02:47:57.724 INFO 71733 --- [lication.main()] com.example.demo.DemoApplication : Started DemoApplication in 2.489 seconds (JVM running for 4.638) 2024-06-16 02:47:57.874 INFO 71733 --- [lication.main()] com.example.demo.DemoApplication : All good 2024-06-16 02:47:57.877 INFO 71733 --- [lication.main()] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' 2024-06-16 02:47:57.879 INFO 71733 --- [lication.main()] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... 2024-06-16 02:47:57.882 INFO 71733 --- [lication.main()] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed. [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 3.851 s [INFO] Finished at: 2024-06-16T02:47:57+02:00 [INFO] ------------------------------------------------------------------------{code} {code:java} ✔ nb6:~/work/bugreport> ./run_groovy.sh Groovy Version: 4.0.21 JVM: 17 Vendor: Oracle Corporation OS: Linux openjdk version "17" 2021-09-14 OpenJDK Runtime Environment (build 17+35-2724) OpenJDK 64-Bit Server VM (build 17+35-2724, mixed mode, sharing) SLF4J(W): No SLF4J providers were found. SLF4J(W): Defaulting to no-operation (NOP) logger implementation SLF4J(W): See https://www.slf4j.org/codes.html#noProviders for further details. . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.7.18)Caught: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'demoApplication': Unsatisfied dependency expressed through field 'recordRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo2.DemoApplication$RecordRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'demoApplication': Unsatisfied dependency expressed through field 'recordRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo2.DemoApplication$RecordRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:713) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:693) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:408) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:929) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:591) at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:409) at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) at org.springframework.boot.SpringApplication.run(SpringApplication.java:1289) at com.example.demo2.DemoApplication.main(DemoApplication.groovy:70) Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo2.DemoApplication$RecordRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)} at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1801) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1357) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:710) ... 20 more ✘-1 nb6:~/work/bugreport> {code} Why the groovy version is not working with literally the same code? > Spring Boot JPA Repository Class is not autowired in Groovy > ----------------------------------------------------------- > > Key: GROOVY-11409 > URL: https://issues.apache.org/jira/browse/GROOVY-11409 > Project: Groovy > Issue Type: Bug > Affects Versions: 4.0.21 > Environment: linux > Reporter: msangel > Priority: Critical > Attachments: bugreport.7z > > > I have a code that works in java. its sample spring-boot application: > > {code:java} > package com.example.demo; > import lombok.Getter; > import lombok.Setter; > import lombok.extern.slf4j.Slf4j; > import org.springframework.beans.factory.annotation.Autowired; > import org.springframework.boot.SpringApplication; > import org.springframework.boot.autoconfigure.SpringBootApplication; > import org.springframework.boot.context.event.ApplicationReadyEvent; > import org.springframework.context.event.EventListener; > import org.springframework.data.jpa.repository.config.EnableJpaRepositories; > import org.springframework.data.repository.CrudRepository; > import org.springframework.stereotype.Repository; > import org.springframework.transaction.annotation.Isolation; > import org.springframework.transaction.annotation.Transactional; > import javax.persistence.*; > @SpringBootApplication > @EnableJpaRepositories(considerNestedRepositories = true) > @Slf4j > public class DemoApplication { > @Getter @Setter > @Entity > @Table(name = "record") > public static class Record { > @Id > @GeneratedValue(strategy = GenerationType.IDENTITY) > private long id; > private String data; > } > @Repository > @Transactional(isolation = Isolation.SERIALIZABLE) > interface RecordRepository extends CrudRepository<Record, Long> { > } > @Autowired > private DemoApplication.RecordRepository recordRepository; > @EventListener(ApplicationReadyEvent.class) > public void ready() { > Iterable<DemoApplication.Record> all = recordRepository.findAll(); > if (all.iterator().hasNext()) { > throw new IllegalStateException("There should be no records"); > } > recordRepository.save(new DemoApplication.Record()); > all = recordRepository.findAll(); > if (!all.iterator().hasNext()) { > throw new IllegalStateException("There should be records"); > } > log.info("All good"); > } > public static void main(String[] args) { > SpringApplication.run(DemoApplication.class, args).close(); > } > } > {code} > And its property file (application.yaml): > > > {code:java} > server: > port: 8080 > spring: > sql: > init: > platform: sqlite > mode: always > datasource: > url: "jdbc:sqlite::memory:" > username: > password: > driver-class-name: org.sqlite.JDBC > jpa: > database-platform: org.sqlite.hibernate.dialect.SQLiteDialect > show-sql: false > defer-datasource-initialization: true > hibernate: > ddl-auto: create > jdbc: > time_zone: UTC > open-in-view: false > {code} > > > Running it works as expected, "All good" is shown into console. > After converting the same code to groovy this code fail. The error is: > > {code:java} > No qualifying bean of type > 'com.example.demo2.DemoApplication$RecordRepository' available: expected at > least 1 bean which qualifies as autowire candidate. Dependency annotations: > {@org.springframework.beans.factory.annotation.Autowired(required=true)} > {code} > So, the spring is not seeing static nested class IF it is in groovy. > > This is the groove code I run: > > {code:java} > package com.example.demo2 > @GrabConfig > @Grab(group = 'org.springframework.boot', module = 'spring-boot-starter-web', > version = '2.7.18') > @Grab(group = 'org.xerial', module = 'sqlite-jdbc', version = '3.45.3.0') > @Grab(group = 'org.springframework.boot', module = > 'spring-boot-starter-data-jpa', version = '2.7.18') > @Grab(group = 'com.github.gwenn', module = 'sqlite-dialect', version = > "0.1.4") > @Grab(group = 'jakarta.persistence', module = 'jakarta.persistence-api', > version = '2.2.2') > @GrabExclude(group = 'javax.persistence', module='javax.persistence-api') > @Grab(group = 'org.jboss.spec.javax.transaction', module = > 'jboss-transaction-api_1.2_spec', version = '1.1.1.Final') > @GrabExclude(group = 'org.jboss.spec.javax.transaction', > module='jboss-transaction-api_1.2_spec') > @Grab(group = 'jakarta.transaction', module = 'jakarta.transaction-api', > version = '1.3.1') > @Grab(group = 'com.zaxxer', module = 'HikariCP', version = '5.1.0') > @Grab(group='org.slf4j', module='slf4j-simple', version='2.0.13') > @Grab(group='org.slf4j', module='slf4j-api', version='2.0.13') > @Grab(group='cglib', module='cglib', version='3.2.4') > import org.springframework.beans.factory.annotation.Autowired; > import org.springframework.boot.SpringApplication; > import org.springframework.boot.autoconfigure.SpringBootApplication; > import org.springframework.boot.context.event.ApplicationReadyEvent > import org.springframework.data.jpa.repository.config.EnableJpaRepositories; > import org.springframework.data.repository.CrudRepository; > import org.springframework.stereotype.Repository; > import org.springframework.transaction.annotation.Isolation; > import org.springframework.transaction.annotation.Transactional > import org.springframework.context.event.EventListener > import javax.persistence.Entity > import javax.persistence.GeneratedValue > import javax.persistence.GenerationType > import javax.persistence.Id > import javax.persistence.Table > @SpringBootApplication > @EnableJpaRepositories(considerNestedRepositories = true) > class DemoApplication { > @Entity > @Table(name = "record") > static class Record { > @Id > @GeneratedValue(strategy = GenerationType.IDENTITY) > private long id > private String data > } > @Repository > @Transactional(isolation = Isolation.SERIALIZABLE) > interface RecordRepository extends CrudRepository<Record, Long> { > } > @Autowired > private DemoApplication.RecordRepository recordRepository; > @EventListener(ApplicationReadyEvent.class) > void ready() { > Iterable<DemoApplication.Record> all = recordRepository.findAll(); > if (all.iterator().hasNext()) { > throw new IllegalStateException("There should be no records"); > } > recordRepository.save(new DemoApplication.Record()); > all = recordRepository.findAll(); > if (!all.iterator().hasNext()) { > throw new IllegalStateException("There should be records"); > } > System.out.println("All good"); > } > static void main(String[] args) { > SpringApplication.run(DemoApplication.class, args).close(); > } > } {code} > > I run it with this script: > > {code:java} > #!/bin/env bash > groovy -version > java -version > cd groovy && groovy src/com/example/demo2/DemoApplication.groovy > --spring.config.location=application.yaml {code} > Ans this is output (boht java case and groovy case): > > > {code:java} > ✔ nb6:~/work/bugreport> ./run_java.sh > [INFO] Scanning for projects... > [INFO] > [INFO] --------------------------< com.example:demo > >-------------------------- > [INFO] Building demo 0.0.1-SNAPSHOT > [INFO] --------------------------------[ jar > ]--------------------------------- > [INFO] > [INFO] --- exec-maven-plugin:3.3.0:java (default-cli) @ demo --- . ____ > _ __ _ _ > /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ > ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ > \\/ ___)| |_)| | | | | || (_| | ) ) ) ) > ' |____| .__|_| |_|_| |_\__, | / / / / > =========|_|==============|___/=/_/_/_/ > :: Spring Boot :: (v2.7.18)2024-06-16 02:47:55.694 INFO 71733 > --- [lication.main()] com.example.demo.DemoApplication : Starting > DemoApplication using Java 17 on nb6 with PID 71733 > (/home/msangel/work/bugreport/java/target/classes started by msangel in > /home/msangel/work/bugreport/java) > 2024-06-16 02:47:55.697 INFO 71733 --- [lication.main()] > com.example.demo.DemoApplication : No active profile set, falling > back to 1 default profile: "default" > 2024-06-16 02:47:56.092 INFO 71733 --- [lication.main()] > .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA > repositories in DEFAULT mode. > 2024-06-16 02:47:56.126 INFO 71733 --- [lication.main()] > .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository > scanning in 26 ms. Found 1 JPA repository interfaces. > 2024-06-16 02:47:56.512 INFO 71733 --- [lication.main()] > o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing > PersistenceUnitInfo [name: default] > 2024-06-16 02:47:56.551 INFO 71733 --- [lication.main()] > org.hibernate.Version : HHH000412: Hibernate ORM core > version 5.6.15.Final > 2024-06-16 02:47:56.685 INFO 71733 --- [lication.main()] > o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons > Annotations {5.1.2.Final} > 2024-06-16 02:47:56.755 INFO 71733 --- [lication.main()] > org.hibernate.dialect.Dialect : HHH000400: Using dialect: > org.sqlite.hibernate.dialect.SQLiteDialect > 2024-06-16 02:47:56.793 INFO 71733 --- [lication.main()] > com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... > 2024-06-16 02:47:56.927 INFO 71733 --- [lication.main()] > com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. > 2024-06-16 02:47:56.935 INFO 71733 --- [lication.main()] > org.hibernate.dialect.Dialect : HHH000400: Using dialect: > org.sqlite.hibernate.dialect.SQLiteDialect > 2024-06-16 02:47:57.377 INFO 71733 --- [lication.main()] > o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform > implementation: > [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] > 2024-06-16 02:47:57.388 INFO 71733 --- [lication.main()] > j.LocalContainerEntityManagerFactoryBean : Initialized JPA > EntityManagerFactory for persistence unit 'default' > 2024-06-16 02:47:57.724 INFO 71733 --- [lication.main()] > com.example.demo.DemoApplication : Started DemoApplication in 2.489 > seconds (JVM running for 4.638) > 2024-06-16 02:47:57.874 INFO 71733 --- [lication.main()] > com.example.demo.DemoApplication : All good > 2024-06-16 02:47:57.877 INFO 71733 --- [lication.main()] > j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory > for persistence unit 'default' > 2024-06-16 02:47:57.879 INFO 71733 --- [lication.main()] > com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown > initiated... > 2024-06-16 02:47:57.882 INFO 71733 --- [lication.main()] > com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed. > [INFO] > ------------------------------------------------------------------------ > [INFO] BUILD SUCCESS > [INFO] > ------------------------------------------------------------------------ > [INFO] Total time: 3.851 s > [INFO] Finished at: 2024-06-16T02:47:57+02:00 > [INFO] > ------------------------------------------------------------------------{code} > {code:java} > ✔ nb6:~/work/bugreport> ./run_groovy.sh > Groovy Version: 4.0.21 JVM: 17 Vendor: Oracle Corporation OS: Linux > openjdk version "17" 2021-09-14 > OpenJDK Runtime Environment (build 17+35-2724) > OpenJDK 64-Bit Server VM (build 17+35-2724, mixed mode, sharing) > SLF4J(W): No SLF4J providers were found. > SLF4J(W): Defaulting to no-operation (NOP) logger implementation > SLF4J(W): See https://www.slf4j.org/codes.html#noProviders for further > details. . ____ _ __ _ _ > /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ > ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ > \\/ ___)| |_)| | | | | || (_| | ) ) ) ) > ' |____| .__|_| |_|_| |_\__, | / / / / > =========|_|==============|___/=/_/_/_/ > :: Spring Boot :: (v2.7.18)Caught: > org.springframework.beans.factory.UnsatisfiedDependencyException: Error > creating bean with name 'demoApplication': Unsatisfied dependency expressed > through field 'recordRepository'; nested exception is > org.springframework.beans.factory.NoSuchBeanDefinitionException: No > qualifying bean of type 'com.example.demo2.DemoApplication$RecordRepository' > available: expected at least 1 bean which qualifies as autowire candidate. > Dependency annotations: > {@org.springframework.beans.factory.annotation.Autowired(required=true)} > org.springframework.beans.factory.UnsatisfiedDependencyException: Error > creating bean with name 'demoApplication': Unsatisfied dependency expressed > through field 'recordRepository'; nested exception is > org.springframework.beans.factory.NoSuchBeanDefinitionException: No > qualifying bean of type 'com.example.demo2.DemoApplication$RecordRepository' > available: expected at least 1 bean which qualifies as autowire candidate. > Dependency annotations: > {@org.springframework.beans.factory.annotation.Autowired(required=true)} > at > org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:713) > at > org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:693) > at > org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) > at > org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:408) > at > org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) > at > org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) > at > org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) > at > org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) > at > org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) > at > org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) > at > org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) > at > org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) > at > org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:929) > at > org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:591) > at > org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) > at > org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) > at > org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:409) > at > org.springframework.boot.SpringApplication.run(SpringApplication.java:308) > at > org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) > at > org.springframework.boot.SpringApplication.run(SpringApplication.java:1289) > at com.example.demo2.DemoApplication.main(DemoApplication.groovy:70) > Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: > No qualifying bean of type > 'com.example.demo2.DemoApplication$RecordRepository' available: expected at > least 1 bean which qualifies as autowire candidate. Dependency annotations: > {@org.springframework.beans.factory.annotation.Autowired(required=true)} > at > org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1801) > at > org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1357) > at > org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) > at > org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:710) > ... 20 more > ✘-1 nb6:~/work/bugreport> > {code} > > Why the groovy version is not working with literally the same code? > -- This message was sent by Atlassian Jira (v8.20.10#820010)