CAS7 bean creation override question

155 views
Skip to first unread message

Yan Zhou

unread,
May 6, 2024, 11:53:07 AM5/6/24
to CAS Community
Hi,

CAS 7.1.0 overlay, I need to override password change implementation, using my own PasswordManagementService.

I basically want to provide my own impl. of JdbcPasswordManagementConfiguration. See below QuestCasConfiguration,

also defined in META-INF/spring/...AutoImports
org.apereo.cas.config.CasOverlayOverrideConfiguration
org.apereo.cas.config.QuestCasConfiguration


@EnableTransactionManagement(proxyTargetClass = false)
@EnableConfigurationProperties(CasConfigurationProperties.class)
@Configuration(value = "QuestCasConfiguration", proxyBeanMethods = false)
public class QuestCasConfiguration {

@Bean(name = "jdbcPasswordChangeService")
public PasswordManagementService passwordChangeService(
.......................
final PasswordHistoryService passwordHistoryService) {
return new QuestJdbcPasswordManagementService(passwordManagementCipherExecutor,
casProperties.getServer().getPrefix(), casProperties.getAuthn().getPm(), jdbcPasswordManagementDataSource,
jdbcPasswordManagementTransactionTemplate, passwordHistoryService, encoder); <=== this is Not called
}

@Bean(name = "jdbcPasswordManagementDataSource")
public DataSource jdbcPasswordManagementDataSource(final CasConfigurationProperties casProperties) {
return JpaBeans.newDataSource(casProperties.getAuthn().getJdbc().getQuery().get(0)); <=== this is called
}
}

the problem is that the two bean methods, one (jdbcPasswordManagementDataSource) is called but the other(passwordChangeService) is not, not sure why. I set a breakpoint in my class to see how the code is invoked.

This means passwordChangeService is already created somewhere else, but I cannot figure that out, either.

I set a breakpoint in CAS source code: JdbcPasswordManagementConfiguration, I do not see any method stopped during debug when CAS starts up.

what did I miss? here are related logs

2024-05-06 10:49:55,104 DEBUG [restartedMain] [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Overriding bean definition for bean 'localeResolver' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=localeResolver; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]] with [Root bean: class [null]; scope=refresh; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=CasWebAppConfiguration; factoryMethodName=localeResolver; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/apereo/cas/config/CasWebAppConfiguration.class]]>
2024-05-06 10:49:55,107 DEBUG [restartedMain] [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Overriding bean definition for bean 'jdbcPasswordManagementDataSource' with a different definition: replacing [Root bean: class [null]; scope=refresh; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=JdbcPasswordManagementDataConfiguration; factoryMethodName=jdbcPasswordManagementDataSource; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/apereo/cas/config/JdbcPasswordManagementConfiguration$JdbcPasswordManagementDataConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=QuestCasConfiguration; factoryMethodName=jdbcPasswordManagementDataSource; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/apereo/cas/config/QuestCasConfiguration.class]]>
2024-05-06 10:49:55,257 DEBUG [restartedMain] [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.AutoConfigurationPackages'>
....


   JdbcPasswordHistoryManagementConfiguration matched:
      - Requested features [PasswordManagementHistory] are enabled (CasFeatureEnabledCondition)

   JdbcPasswordManagementConfiguration matched:
      - Requested features [PasswordManagement] are enabled (CasFeatureEnabledCondition)

   JdbcPasswordManagementConfiguration.JdbcPasswordManagementDataConfiguration#jdbcPasswordManagementDataSource matched:
      - @ConditionalOnMissingBean (names: jdbcPasswordManagementDataSource; SearchStrategy: all) did not find any beans (OnBeanCondition)

   JdbcPasswordManagementConfiguration.JdbcPasswordManagementServiceConfiguration#passwordChangeService matched:
      - @ConditionalOnMissingBean (names: jdbcPasswordChangeService; SearchStrategy: all) did not find any beans (OnBeanCondition)

   JdbcPasswordManagementConfiguration.JdbcPasswordManagementTransactionConfiguration#jdbcPasswordManagementTransactionTemplate matched:
      - @ConditionalOnMissingBean (names: jdbcPasswordManagementTransactionTemplate; SearchStrategy: all) did not find any beans (OnBeanCondition)

thanks!
Yan

Yan Zhou

unread,
May 6, 2024, 9:49:45 PM5/6/24
to CAS Community, Yan Zhou
My thought is that this bean ( jdbcPasswordChangeService)  is already created somehow, see below logs, but I do not know how to find it who created it,  I set a breakpoint in the only occurrence of this bean definition,  JdbcPasswordManagementConfiguration, the method does not appear invoked in debugger.

2024-05-06 12:23:41,783 DEBUG [restartedMain] [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Creating shared instance of singleton bean 'jdbcAuthenticationHandlers'>   <== i have my class re-defined this and breakpoint is invoked successfully

2024-05-06 12:23:41,804 DEBUG [restartedMain] [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Creating shared instance of singleton bean 'jdbcPasswordChangeService'>  <==  do Not know who created it.

2024-05-06 12:23:41,836 DEBUG [restartedMain] [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Creating shared instance of singleton bean 'requestContextFilter'>

any idea to find out who created this instance?

Yan Zhou

unread,
May 7, 2024, 6:53:13 PM5/7/24
to CAS Community, Yan Zhou
Finally figured this out. The bean seems incorrectly named in the CAS source code.

I will see if I can submit a fix.

Yan

Ray Bon

unread,
May 7, 2024, 6:53:14 PM5/7/24
to cas-...@apereo.org, yana...@gmail.com
Yan,

Configuration classes are driven by spring. Perhaps this class runs before the debugger can connect to the [starting] app.

For your Configuration class to be called, it needs to be added to src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

Ray

On Mon, 2024-05-06 at 10:04 -0700, Yan Zhou wrote:
Notice: This message was sent from outside the University of Victoria email system. Please be cautious with links and sensitive information.

My thought is that this bean ( jdbcPasswordChangeService)  is already created somehow, see below logs, but I do not know how to find it who created it,  I set a breakpoint in the only occurrence of this bean definition,  JdbcPasswordManagementConfiguration, the method does not appear invoked in debugger.

2024-05-06 12:23:41,783 DEBUG [restartedMain] [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Creating shared instance of singleton bean 'jdbcAuthenticationHandlers'>   <== i have my class re-defined this and breakpoint is invoked successfully

2024-05-06 12:23:41,804 DEBUG [restartedMain] [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Creating shared instance of singleton bean 'jdbcPasswordChangeService'>  <==  do Not know who created it.

2024-05-06 12:23:41,836 DEBUG [restartedMain] [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Creating shared instance of singleton bean 'requestContextFilter'>

any idea to find out who created this instance?

On Monday, May 6, 2024 at 11:53:07 AM UTC-4 Yan Zhou wrote:
Hi,

CAS 7.1.0 overlay, I need to override password change implementation, using my own PasswordManagementService.

I basically want to provide my own impl. of JdbcPasswordManagementConfiguration. See below QuestCasConfiguration,

also defined in META-INF/spring/...AutoImports
org.apereo.cas.config.CasOverlayOverrideConfiguration
org.apereo.cas.config.QuestCasConfiguration


@EnableTransactionManagement(proxyTargetClass = false)
@EnableConfigurationProperties(CasConfigurationProperties.class)
@Configuration(value = "QuestCasConfiguration", proxyBeanMethods = false)
public class QuestCasConfiguration {

@Bean(name = "jdbcPasswordChangeService")
public PasswordManagementService passwordChangeService(
.......................
final PasswordHistoryServicepasswordHistoryService) {
return new QuestJdbcPasswordManagementService(passwordManagementCipherExecutor,
casProperties.getServer().getPrefix(), casProperties.getAuthn().getPm(), jdbcPasswordManagementDataSource,
jdbcPasswordManagementTransactionTemplate, passwordHistoryService, encoder); <=== this is Not called
}

@Bean(name = "jdbcPasswordManagementDataSource")
public DataSourcejdbcPasswordManagementDataSource(finalCasConfigurationProperties casProperties) {

return JpaBeans.newDataSource(casProperties.getAuthn().getJdbc().getQuery().get(0)); <=== this is called
}
}

the problem is that the two bean methods, one (jdbcPasswordManagementDataSource) is called but the other(passwordChangeService) is not, not sure why. I set a breakpoint in my class to see how the code is invoked.

This means passwordChangeService is already created somewhere else, but I cannot figure that out, either.

I set a breakpoint in CAS source code:JdbcPasswordManagementConfiguration, I do not see any method stopped during debug when CAS starts up.

what did I miss? here are related logs

2024-05-06 10:49:55,104 DEBUG [restartedMain] [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Overriding bean definition for bean 'localeResolver' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration; factoryMethodName=localeResolver; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]] with [Root bean: class [null]; scope=refresh; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=CasWebAppConfiguration; factoryMethodName=localeResolver; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/apereo/cas/config/CasWebAppConfiguration.class]]>
2024-05-06 10:49:55,107 DEBUG [restartedMain] [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Overriding bean definition for bean 'jdbcPasswordManagementDataSource' with a different definition: replacing [Root bean: class [null]; scope=refresh; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=JdbcPasswordManagementDataConfiguration; factoryMethodName=jdbcPasswordManagementDataSource; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/apereo/cas/config/JdbcPasswordManagementConfiguration$JdbcPasswordManagementDataConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=QuestCasConfiguration; factoryMethodName=jdbcPasswordManagementDataSource; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in class path resource [org/apereo/cas/config/QuestCasConfiguration.class]]>
2024-05-06 10:49:55,257 DEBUG [restartedMain] [org.springframework.beans.factory.support.DefaultListableBeanFactory] - <Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.AutoConfigurationPackages'>

Yan Zhou

unread,
May 9, 2024, 12:17:51 AM5/9/24
to CAS Community, Ray Bon, yana...@gmail.com
Here is what I found, is this a bug in CAS source code?

Reading this code, I declared my bean to override "jdbcPasswordChangeService", that did Not work.

class JdbcPasswordManagementConfiguration { 
              static class JdbcPasswordManagementServiceConfiguration { 
                        @ConditionalOnMissingBean(name = "jdbcPasswordChangeService") 
                      public PasswordManagementService passwordChangeService(

because the framework is looking for a different name, Once I named my bean as "passwordChangeService", it worked well. But I had to go through a lot scratching-my-head and debugging in order to figure this out.  I noted that such naming inconsistency does not exist in password-pm-rest and password-pm-ldap module.   

I am hoping to create a unit test to demonstrate this as a bug to be fixed in CAS7.1.0 RC.

public interface PasswordManagementService { 
      String DEFAULT_BEAN_NAME = "passwordChangeService";
Reply all
Reply to author
Forward
0 new messages