Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-11409

Spring Boot JPA Repository Class is not autowired in Groovy

Attach filesAttach ScreenshotAdd voteVotersWatch issueWatchersCreate sub-taskLinkCloneUpdate Comment AuthorReplace String in CommentUpdate Comment VisibilityDelete Comments
    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Critical
    • Resolution: Unresolved
    • 4.0.21
    • None
    • None
    • None
    • linux

    Description

      I have a code that works in java. its sample spring-boot application:

       

      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();
          }
      
      }
       

      And its property file (application.yaml):

       

       

      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
       

       

       

      Running it works as expected, "All good" is shown into console.

      After converting the same code to groovy this code fail. The error is: 

       

      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)}
       

      So, the spring is not seeing static nested class IF it is in groovy. 

       

      This is the groove code I run:

       

      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();
          }
      } 

       

      I run it with this script:

       

      #!/bin/env bash
      groovy -version
      java -version
      cd groovy && groovy src/com/example/demo2/DemoApplication.groovy --spring.config.location=application.yaml 

      Ans this is output (boht java case and groovy case):

       

       

      ✔ 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] ------------------------------------------------------------------------
      ✔ 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> 
      

       

      Why the groovy version is not working with literally the same code?

       

      Attachments

        Activity

          This comment will be Viewable by All Users Viewable by All Users
          Cancel

          People

            Unassigned Unassigned
            msangel msangel

            Dates

              Created:
              Updated:

              Slack

                Issue deployment