[ 
https://issues.apache.org/jira/browse/GROOVY-11409?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17855431#comment-17855431
 ] 

Eric Milles commented on GROOVY-11409:
--------------------------------------

When you run your demo using the {{groovy}} command, the script is parsed into 
classes at run-time.  These classes are not locate-able using Spring's default 
path-based resource loader.  I did not work out how to make spring aware of 
these, but there are some ideas on SO.  Maybe someone with more experience 
could say how to connect spring to groovy's dynamic script parsing mechanisms.

I compiled the script with {{groovyc}} first and then ran with {{groovy}} and 
it could then find the nested interface class.

> 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");
>         }
>         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?
>  



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to