Trouble CAS 6.3.x autowire JPA Repository Beans

490 views
Skip to first unread message

Yan Zhou

unread,
May 11, 2021, 9:43:05 AM5/11/21
to CAS Community
Hello,

CAS uses Spring JdbcTemplate, it does not use Spring JPA Data Repository. I was able to easily add that in CAS 5.3, but run into difficulty with CAS 6.3.

The Spring JPA Data Repository allows me to define interface and Spring provides beans that implement them and Spring cares for all the injection.   In Cas 6.3, I keep getting error: NoSuchBeanDefinition, in other words, Spring did not instantiate beans for repository interfaces as it should. 

I believe all my Spring Data Repository configuration is correct and that is why it is working in CAS5.3, such as the spring-data-jpa dependencies, specifying packages for @EnableJpaRepository, @EntityScan in a @Configuration class. 

Here is CAS 5.3. I can see Spring is instantiating beans for repository interfaces, but this is not happening in CAS 6.3

Did the wiring and bean instantiation change in cas 6.3?

Thanks,
Yan

2021-05-11 02:00:29,041 DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@66345a4f: defining beans  ............. (some of them are the JPA Data Repository beans)

Pablo Vidaurri

unread,
May 12, 2021, 2:33:07 PM5/12/21
to CAS Community, Yan Zhou
Having same problem with the autowire of the repository annotated class. Any help would be appreciated.

-psv

Yan Zhou

unread,
May 13, 2021, 6:42:23 PM5/13/21
to CAS Community, Pablo Vidaurri, Yan Zhou
Hello,

I am about to give up, and stay with jdbcTemplate.  I am unable to get Spring JPA Data Repository to work with CAS 6.4 snapshot.

This is my CasWebApplication, everything about data repository is enabled. But there is no indication in logs that data-jpa autoConfiguration is taking place. 

@SpringBootApplication(
scanBasePackages  = {"org.apereo.cas", "com.quest.cas"}, 
exclude = {
    GroovyTemplateAutoConfiguration.class
}, 
proxyBeanMethods = false)
@EnableJpaRepositories(basePackages = {"com.quest.cas.prs.model"})
@EntityScan(basePackages =  {"com.quest.cas.prs.model"})
@EnableConfigurationProperties(CasConfigurationProperties.class)
@EnableAsync
@EnableAspectJAutoProxy(proxyTargetClass = true)
@EnableTransactionManagement(proxyTargetClass = true)
@EnableScheduling
@NoArgsConstructor
@Slf4j
public class CasWebApplication {
    

There must be something preventing Data repository running, see below for some conditions from Spring,  I think my runtime environment should allow it to run, but it does not. 

@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(DataSource.class)
@ConditionalOnClass(JpaRepository.class)
@ConditionalOnMissingBean({ JpaRepositoryFactoryBean.class, JpaRepositoryConfigExtension.class })
@ConditionalOnProperty(prefix = "spring.data.jpa.repositories", name = "enabled", havingValue = "true",
matchIfMissing = true)
@Import(JpaRepositoriesRegistrar.class)
@AutoConfigureAfter({ HibernateJpaAutoConfiguration.class, TaskExecutionAutoConfiguration.class })
public class JpaRepositoriesAutoConfiguration {

Yan

Pablo Vidaurri

unread,
May 13, 2021, 9:55:00 PM5/13/21
to CAS Community, Yan Zhou, Pablo Vidaurri
I assume you are also using
org.springframework.boot:spring-boot-starter-data-jpa

or is there a special CAS dependency to use instead?

Yan Zhou

unread,
May 14, 2021, 5:10:12 PM5/14/21
to CAS Community, Pablo Vidaurri, Yan Zhou
I figured out before I was about to give up.  All I had to do is:   -Dspring.index.ignore=true    add this to startup script.  

Spring 5 has this new feature that CAS builds on, it won’t load JPA repository beans unless one of its modules has it included in META-INF/spring.components

 Once I understood that, I can follow CAS framework to get it done without using that flag.  


Ivan Green

unread,
Aug 30, 2021, 4:12:43 AM8/30/21
to CAS Community, Yan Zhou, Pablo Vidaurri
Hello!

I would be very grateful for your help.

Faced the same problem on CAS 5.2.3.

I am using spring data jpa.

In the application.properties file, I described the connection to the database through the standard:

spring.datasource.url =
spring.datasource.username =
spring.datasource.password =
spring.jpa.show-sql =
spring.jpa.hibernate.ddl-auto =
spring.jpa.properties.hibernate.dialect =

Next, I created entities and repository extends CrudRepository.

When trying to @Autowired my repos in services, I get a NoSuchBeanDefinition error. 

The configuration goes through the spring.factories file:

org.springframework.boot.autoconfigure.EnableAutoConfiguration = ru.test.security.core.cas.config.CasMainPropertiesConfig

CasMainPropertiesConfig, which contains:

@Configuration ("ConfigurationName")
@EnableConfigurationProperties (CasConfigurationProperties.class)
@ComponentScan ("ru.test.security.core")
@PropertySource ("file: C /.../ cas.standalone.properties")
public class CasMainPropertiesConfig {

}

When trying to insert @EnableJpaRepository or @EntityScan here, the application simply does not start with an error:

[org.apereo.cas.web.CasWebApplicationContext] - <Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [org.apereo.cas.web. CasWebApplication]; nested exception is java.lang.NoClassDefFoundError: org / springframework / data / repository / config / BootstrapMode>

What's going wrong? Tried adding -Dspring.index.ignore = true to run and nothing changes.

I hope very much for your help.

суббота, 15 мая 2021 г. в 00:10:12 UTC+3, Yan Zhou:

Yan

unread,
Aug 30, 2021, 1:16:38 PM8/30/21
to Ivan Green, CAS Community, Pablo Vidaurri
Hello,

CAS6 and CAS5 are different, but they both disable DataSourceAutoConfiguration, so we need to configure database ourselves. 

this is what I do.  under org.apereo.cas.config package.  And then,  under spring.factories, include it in auto-configuration: 

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
............MyConfiguration....

Hope that works.

Yan

@Configuration("MyDatabaseConfiguration")
@EnableJpaRepositories(
   entityManagerFactoryRef = "entityManagerFactory",
   basePackages = { "....................."}  // packages where repository live
)
public class MyDatabaseConfiguration  {
private static final Logger logger = LoggerFactory.getLogger(QuestDatabaseConfiguration.class);


@Bean(name = "casDataSource")
    protected DataSource casDS() {
    try {
JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
bean.setJndiName("java:comp/.........");
bean.setProxyInterface(DataSource.class);
bean.setLookupOnStartup(false);
bean.afterPropertiesSet();
return (DataSource)bean.getObject();
    } catch (Exception ex) {
    logger.error("Cannot find datasource.", ex);
    return null;
    }
    }  

    @Bean(name = "entityManagerFactory")
    public EntityManagerFactory entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();

LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setJpaProperties(additionalProperties());

// packages where entities live
factory.setPackagesToScan(new String[] {"..................."});

factory.setDataSource(casDS());
factory.afterPropertiesSet();

return factory.getObject();
    }

    Properties additionalProperties() {
        Properties properties = new Properties();
        properties.setProperty(
          "hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
         
        return properties;
    }

    @Bean
    public PlatformTransactionManager transactionManager(
    @Qualifier("entityManagerFactory") EntityManagerFactory emf) {
    JpaTransactionManager txManager = new JpaTransactionManager();
    txManager.setEntityManagerFactory(emf);
        return txManager;
    }

Ivan Green

unread,
Aug 31, 2021, 9:21:30 AM8/31/21
to CAS Community, Yan Zhou, CAS Community, Pablo Vidaurri, Ivan Green
Thanks a lot for the answer! 
It helped me! 

I slightly changed the bean DataSource, namely:


@Bean(name = "casDataSource")
protected DataSource casDS() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();

dataSource.setDriverClassName(driver);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setUrl(url);


return dataSource;
}

The rest of your example is left unchanged

After that, my repos and entities were noticed and I was able to use them.
понедельник, 30 августа 2021 г. в 20:16:38 UTC+3, Yan Zhou:

Pablo Vidaurri

unread,
Sep 8, 2021, 11:22:22 PM9/8/21
to CAS Community, fryc...@gmail.com, Yan Zhou, CAS Community, Pablo Vidaurri
This also worked for me with a few exceptions.

In my entity class, I had to use @Table and @Column annotations to provide the name of my table and columns. I was expecting the CamelCase naming convention of the class and properties to translate to snake case (userId -> user_id) but it looked like it defaulted to all lower case (userId ->userid). 

Googling, it appears that we now need to define our own strategy extending PhysicalNamingStrategyStandardImpl  or resort to explicit table and column names.

Thanks for pointing out how to enable jpa in cas

-psv

Pablo Vidaurri

unread,
Mar 1, 2022, 11:05:41 AM3/1/22
to CAS Community, Yan Zhou, CAS Community, Pablo Vidaurri, fryc...@gmail.com
Hi Yan, have you tried this with CAS 6.4.5 which uses SpringBoot 2.5.4? I am seeing issues finding my repositiory beans, I have not been able to get it working. All continue to works with 6.3.7.4.

Pablo Vidaurri

unread,
Mar 31, 2022, 10:42:33 AM3/31/22
to CAS Community, Pablo Vidaurri, Yan Zhou, CAS Community, fryc...@gmail.com
I'm still having trouble with this.

Has anyone upgraded to 6.4.x or above with jpa repository classes?

It's as if  @EnableJpaRepositories is being ignored.

Yan

unread,
Mar 31, 2022, 12:56:18 PM3/31/22
to Pablo Vidaurri, CAS Community, fryc...@gmail.com
Hi,

If  JPA worked for you in 6.3 but not in 6.4, you may have a different problem than I had. 

JPA Repository does work for me in 6.4.4.,  this is what I did.  under project's  resources/META-INF/spring.components,  I explicitly spelled out all Repo and Entity classes.

==  these are my classes ==

............
com.......model.CasUserPwdresEventRepository=org.springframework.data.repository.Repository
com.......model.CasUser=javax.persistence.Entity=javax.persistence.Entity
...........

==

Like i said, this would be the same for 6.3 and 6.4.

Yan

Pablo Vidaurri

unread,
Apr 1, 2022, 4:52:59 PM4/1/22
to CAS Community, Yan Zhou, CAS Community, fryc...@gmail.com, Pablo Vidaurri
Thanks for the input Yan.

I would hate to do that for every class, but I'll try it for one or two entities/repos to see if it gets past my problem.

In my current project that works for 6.3 ...
1) META-INF/spring.factories:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.xxx.cas.config.MyDbConfiguration

note, i have repos, entities, services for jpa related classes in a different repo than the cas classes I overlay.

2) in  MyDbConfiguration.java class:
@Configuration
@EnableConfigurationProperties(CustomConfigurationProperties.class)
@EnableJpaRepositories(
        entityManagerFactoryRef = "myEntityManagerFactory",
        basePackages = {"com.xxx.cas.repository"}    <--- repository interfaces
        )

@Bean(name = "=myEntityManagerFactory")
    public EntityManagerFactory myEntityManagerFactory() {
      .
      .
     .

        // entity packages
        factory.setPackagesToScan("com.xxx.cas.entity");  <-- entity classes

        .
        .
         .
    }

Error on startup:
022-04-01 15:46:49,438 WARN [org.apereo.cas.web.CasWebApplicationContext] - <Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'scopedTarget.UserViewService': Unsatisfied dependency expressed through field 'userViewRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.xxx.cas.repository.UserViewRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}>


-psv

Yan

unread,
Apr 4, 2022, 12:07:46 PM4/4/22
to Pablo Vidaurri, CAS Community, fryc...@gmail.com
Hi, 

I remember spending a lot of time on this when we moved from CAS5 to CAS6, to get Spring Data Repository working, the reason was because Spring 5 feature changes. 

All I had to do is:   -Dspring.index.ignore=true    add this to startup script.   Spring 5 has this new feature that CAS builds on, it won’t load JPA repository beans unless one of its modules has it included in META-INF/spring.components


you do NOT need to manually specify JPA and Repo classes in sprint.components file, but you will have to use this flag which alters default Spring 5 behavior.  I am sure it is there for a good reason, I do not mind adding entity and repo classes manually, because I prefer simply sticking to the default behavior of Spring and CAS.


Yan

Reply all
Reply to author
Forward
0 new messages