CAS 6.6.13 : No qualifying bean of type 'org.springframework.transaction.TransactionManager'

154 views
Skip to first unread message

Mohamed Amdouni

unread,
Nov 8, 2023, 10:44:20 PM11/8/23
to cas-...@apereo.org
Hello,

Given a cas project with these dependencies :

implementation "org.apereo.cas:cas-server-support-saml"
implementation "org.apereo.cas:cas-server-support-saml-idp"
implementation "org.apereo.cas:cas-server-support-saml-idp-metadata-jpa"
implementation "org.apereo.cas:cas-server-support-ldap"
implementation "org.apereo.cas:cas-server-support-spnego-webflow"
implementation "org.apereo.cas:cas-server-support-jpa-ticket-registry"
implementation "org.apereo.cas:cas-server-support-jpa-service-registry"
implementation "org.apereo.cas:cas-server-support-jdbc-drivers"
implementation "org.apereo.cas:cas-server-support-rest-authentication"
implementation "org.apereo.cas:cas-server-support-rest"
When trying to connect a SAML2 client, I encounter the following exception (only for the first connection)

org.springframework.webflow.execution.ActionExecutionException: Exception thrown executing org.apereo.cas.web.flow.GenerateServiceTicketAction@74af4b0 in state 'generateServiceTicket' of flow 'login' -- action execution attributes were 'map[[empty]]'

                at org.springframework.webflow.execution.ActionExecutor.execute(ActionExecutor.java:62)

                at org.springframework.webflow.action.EvaluateAction.doExecute(EvaluateAction.java:77)

                at org.springframework.webflow.action.AbstractAction.execute(AbstractAction.java:188)

                at org.springframework.webflow.execution.ActionExecutor.execute(ActionExecutor.java:51)

                at org.springframework.webflow.engine.ActionState.doEnter(ActionState.java:101)

                at org.springframework.webflow.engine.State.enter(State.java:194)

                at org.springframework.webflow.engine.Transition.execute(Transition.java:228)

                at org.springframework.webflow.engine.DecisionState.doEnter(DecisionState.java:51)

                at org.springframework.webflow.engine.State.enter(State.java:194)

                at org.springframework.webflow.engine.Transition.execute(Transition.java:228)

                at org.springframework.webflow.engine.impl.FlowExecutionImpl.execute(FlowExecutionImpl.java:395)

                at org.springframework.webflow.engine.impl.RequestControlContextImpl.execute(RequestControlContextImpl.java:214)

                at org.springframework.webflow.engine.TransitionableState.handleEvent(TransitionableState.java:116)

                at org.springframework.webflow.engine.Flow.handleEvent(Flow.java:547)

                at org.springframework.webflow.engine.impl.FlowExecutionImpl.handleEvent(FlowExecutionImpl.java:390)

                at org.springframework.webflow.engine.impl.RequestControlContextImpl.handleEvent(RequestControlContextImpl.java:210)

                at org.springframework.webflow.engine.ActionState.doEnter(ActionState.java:105)

                at org.springframework.webflow.engine.State.enter(State.java:194)

                at org.springframework.webflow.engine.Transition.execute(Transition.java:228)

                at org.springframework.webflow.engine.impl.FlowExecutionImpl.execute(FlowExecutionImpl.java:395)

                at org.springframework.webflow.engine.impl.RequestControlContextImpl.execute(RequestControlContextImpl.java:214)

                at org.springframework.webflow.engine.TransitionableState.handleEvent(TransitionableState.java:116)

                at org.springframework.webflow.engine.Flow.handleEvent(Flow.java:547)

                at org.springframework.webflow.engine.impl.FlowExecutionImpl.handleEvent(FlowExecutionImpl.java:390)

                at org.springframework.webflow.engine.impl.RequestControlContextImpl.handleEvent(RequestControlContextImpl.java:210)

                at org.springframework.webflow.engine.ActionState.doEnter(ActionState.java:105)

                at org.springframework.webflow.engine.State.enter(State.java:194)

                at org.springframework.webflow.engine.Transition.execute(Transition.java:228)

                at org.springframework.webflow.engine.impl.FlowExecutionImpl.execute(FlowExecutionImpl.java:395)

                at org.springframework.webflow.engine.impl.RequestControlContextImpl.execute(RequestControlContextImpl.java:214)

                at org.springframework.webflow.engine.TransitionableState.handleEvent(TransitionableState.java:116)

                at org.springframework.webflow.engine.Flow.handleEvent(Flow.java:547)

                at org.springframework.webflow.engine.impl.FlowExecutionImpl.handleEvent(FlowExecutionImpl.java:390)

                at org.springframework.webflow.engine.impl.RequestControlContextImpl.handleEvent(RequestControlContextImpl.java:210)

                at org.springframework.webflow.engine.ActionState.doEnter(ActionState.java:105)

                at org.springframework.webflow.engine.State.enter(State.java:194)

                at org.springframework.webflow.engine.Transition.execute(Transition.java:228)

                at org.springframework.webflow.engine.impl.FlowExecutionImpl.execute(FlowExecutionImpl.java:395)

                at org.springframework.webflow.engine.impl.RequestControlContextImpl.execute(RequestControlContextImpl.java:214)

                at org.springframework.webflow.engine.TransitionableState.handleEvent(TransitionableState.java:116)

                at org.springframework.webflow.engine.Flow.handleEvent(Flow.java:547)

                at org.springframework.webflow.engine.impl.FlowExecutionImpl.handleEvent(FlowExecutionImpl.java:390)

                at org.springframework.webflow.engine.impl.RequestControlContextImpl.handleEvent(RequestControlContextImpl.java:210)

                at org.springframework.webflow.engine.ViewState.handleEvent(ViewState.java:231)

                at org.springframework.webflow.engine.ViewState.resume(ViewState.java:195)

                at org.springframework.webflow.engine.Flow.resume(Flow.java:537)

                at org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:259)

                at org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:168)

                at org.springframework.webflow.mvc.servlet.FlowHandlerAdapter.handle(FlowHandlerAdapter.java:254)

                at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1070)

                at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)

                at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)

                at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)

                at javax.servlet.http.HttpServlet.service(HttpServlet.java:665)

                at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)

                at javax.servlet.http.HttpServlet.service(HttpServlet.java:750)

                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209)

                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)

                at org.springframework.web.servlet.resource.ResourceUrlEncodingFilter.doFilter(ResourceUrlEncodingFilter.java:67)

                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)

                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)

                at org.apereo.cas.web.support.AuthenticationCredentialsThreadLocalBinderClearingFilter.doFilter(AuthenticationCredentialsThreadLocalBinderClearingFilter.java:28)

                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)

                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)

                at org.apereo.cas.web.support.filters.RequestParameterPolicyEnforcementFilter.doFilter(RequestParameterPolicyEnforcementFilter.java:401)

                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)

                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)

                at org.apereo.cas.web.support.filters.ResponseHeadersEnforcementFilter.doFilter(ResponseHeadersEnforcementFilter.java:209)

                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)

                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)

                at org.apereo.cas.web.support.filters.AddResponseHeadersFilter.doFilter(AddResponseHeadersFilter.java:62)

                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)

                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)

                at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)

                at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:186)

                at org.springframework.security.web.debug.DebugFilter.invokeWithWrappedRequest(DebugFilter.java:90)

                at org.springframework.security.web.debug.DebugFilter.doFilter(DebugFilter.java:78)

                at org.springframework.security.web.debug.DebugFilter.doFilter(DebugFilter.java:67)

                at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354)

                at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)

                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)

                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)

                at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)

                at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)

                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)

                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)

                at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)

                at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)

                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)

                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)

                at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96)

                at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)

                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)

                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)

                at org.apereo.cas.logging.web.ThreadContextMDCServletFilter.doFilter(ThreadContextMDCServletFilter.java:104)

                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)

                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)

                at org.apereo.inspektr.common.web.ClientInfoThreadLocalFilter.doFilter(ClientInfoThreadLocalFilter.java:66)

                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)

                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)

                at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)

                at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)

                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)

                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)

                at org.springframework.security.web.context.SecurityContextHolderFilter.doFilterInternal(SecurityContextHolderFilter.java:64)

                at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117)

                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178)

                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153)

                at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:168)

                at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)

                at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:481)

                at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130)

                at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)

                at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)

                at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:670)

                at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:765)

                at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)

                at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390)

                at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)

                at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:928)

                at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1794)

                at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)

                at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)

                at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)

                at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

                at java.base/java.lang.Thread.run(Thread.java:829)

Caused by: org.springframework.dao.CannotAcquireLockException: Failed to lock mutex at 7601b7be-a92f-3e78-b872-9471e27007a3; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.transaction.TransactionManager' available: expected single matching bean but found 2: ticketTransactionManager,transactionManagerServiceReg

                at org.springframework.integration.jdbc.lock.JdbcLockRegistry$JdbcLock.rethrowAsLockException(JdbcLockRegistry.java:197)

                at org.springframework.integration.jdbc.lock.JdbcLockRegistry$JdbcLock.tryLock(JdbcLockRegistry.java:262)

                at org.apereo.cas.util.lock.DefaultLockRepository.lambda$execute$1(DefaultLockRepository.java:28)

                at org.jooq.lambda.Unchecked.lambda$supplier$38(Unchecked.java:1695)

                at org.apereo.cas.util.lock.DefaultLockRepository.execute(DefaultLockRepository.java:38)

                at org.apereo.cas.DefaultCentralAuthenticationService.grantServiceTicket(DefaultCentralAuthenticationService.java:101)

                at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

                at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

                at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

                at java.base/java.lang.reflect.Method.invoke(Method.java:566)

                at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)

                at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)

                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)

                at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)

                at org.apereo.inspektr.audit.AuditTrailManagementAspect.handleAuditTrail(AuditTrailManagementAspect.java:178)

                at jdk.internal.reflect.GeneratedMethodAccessor183.invoke(Unknown Source)

                at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

                at java.base/java.lang.reflect.Method.invoke(Method.java:566)

                at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)

                at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624)

                at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72)

                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)

                at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)

                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)

                at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)

                at com.sun.proxy.$Proxy264.grantServiceTicket(Unknown Source)

                at org.apereo.cas.web.flow.GenerateServiceTicketAction.lambda$grantServiceTicket$1(GenerateServiceTicketAction.java:133)

                at java.base/java.util.Optional.ifPresent(Optional.java:183)

                at org.apereo.cas.web.flow.GenerateServiceTicketAction.grantServiceTicket(GenerateServiceTicketAction.java:130)

                at org.apereo.cas.web.flow.GenerateServiceTicketAction.doExecute(GenerateServiceTicketAction.java:105)

                at org.springframework.webflow.action.AbstractAction.execute(AbstractAction.java:188)

                at org.springframework.webflow.execution.ActionExecutor.execute(ActionExecutor.java:51)

                ... 125 more

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.transaction.TransactionManager' available: expected single matching bean but found 2: ticketTransactionManager,transactionManagerServiceReg

                at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1273)

                at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:494)

                at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349)

                at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)

                at org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:503)

                at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:342)

                at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)

                at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)

                at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)

                at com.sun.proxy.$Proxy263.acquire(Unknown Source)

                at org.springframework.integration.jdbc.lock.JdbcLockRegistry$JdbcLock.doLock(JdbcLockRegistry.java:268)

                at org.springframework.integration.jdbc.lock.JdbcLockRegistry$JdbcLock.tryLock(JdbcLockRegistry.java:249)

                ... 155 more



When looking to the code, the problem is in the bean declaration org.apereo.cas.config.JpaTicketRegistryConfiguration.JpaTicketRegistryLockingConfiguration#jdbcLockRepository
which uses  new org.springframework.integration.jdbc.lock.DefaultLockRepository(dataSourceTicket))
The Spring integration Class DefaultLockRepository uses internally @Transactional without Qualifier.
So it finds multiple Beans and could not choose one because there is no @Primary bean for transaction Manager.
As a workaround, I disabled the locking ("cas.ticket.registry.core.enable-locking") to avoid this exception.
Would you please check and recommend a final solution when building a CAS project with two JPA dependencies (ticket and service)? May declare a third custom PrimaryTransactionManager ?
I think that there is a similar issue on metadata : nullpointer exception when getting /idp/metadata if we build a CAS project with two dependencies 
file and jpa metadata.
@Bean
@RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
public org.springframework.integration.jdbc.lock.LockRepository jdbcLockRepository(
final ConfigurableApplicationContext applicationContext,
@Qualifier("dataSourceTicket")
final CloseableDataSource dataSourceTicket) {
return BeanSupplier.of(org.springframework.integration.jdbc.lock.LockRepository.class)
.when(CONDITION.given(applicationContext.getEnvironment()))
.supply(() -> new org.springframework.integration.jdbc.lock.DefaultLockRepository(dataSourceTicket))
.otherwiseProxy()
.get();
}

Best regards.

Mohamed Amdouni

unread,
Nov 23, 2023, 12:38:55 AM11/23/23
to cas-...@apereo.org
Hello,

Would you please recommend one of the below workaround ? Are anyone is running a cas server with two jpa modules (ticket and services) ? 

- first workaround : keep the lock disabled : 
cas.ticket.registry.core.enable-locking
- create a custom primary bean in the project to be returned when more than one transaction manager is present 

- override the ticket and service bean to not use the spring integration bean that calls @ transactional without qualifier.


Thank you for your help.
Reply all
Reply to author
Forward
0 new messages