Uploaded image for project: 'Syncope'
  1. Syncope
  2. SYNCOPE-1635

Create Rules with configurations for each domain, make creation thread safe

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 2.1.6, 2.1.9
    • 2.1.10, 3.0.0-M0
    • core
    • None

    Description

      Class org.apache.syncope.core.spring.ImplementationManager registers singleton bean for Rules that contains Configuration. Example of rule class org.apache.syncope.core.spring.policy.DefaultPasswordRule, example of confugration class that may contain the rule: org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf.

      There is only one spring bean of rule of a particular type in the Spring Application Context.
      Issue 1: The registration of singleton bean contains the concurrent issue: if the singletone is already registered further creation of the prototype scoped bean of the same class throws exception like:

      org.springframework.beans.factory.BeanCreationException: Error creating bean with name '${beanName}': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named '${beanName}' available
          at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:382)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1404)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:351)
          at sun.reflect.GeneratedMethodAccessor195.invoke(Unknown Source)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
          at java.lang.reflect.Method.invoke(Method.java:498)
          at com.zeroturnaround.javarebel.ix.invokeMethod(SourceFile:288)
          at org.apache.syncope.core.spring.ImplementationManager.buildJavaWithConf(ImplementationManager.java:240)
          at org.apache.syncope.core.spring.ImplementationManager.buildPasswordRule(ImplementationManager.java:112)
          at ch.usp.syncope.wrapper.ImplementationManagerWrapper.buildPasswordRule(ImplementationManagerWrapper.java:25)
          at ch.usp.syncope.core.provisioning.java.job.ExecLogic.getPasswordLifeTime(ExecLogic.java:89)
          at ch.usp.syncope.core.provisioning.java.job.ExecLogic.execute(ExecLogic.java:57)
          at ch.usp.syncope.core.provisioning.java.job.ExecLogic$$FastClassBySpringCGLIB$$1.invoke(<generated>)
          at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
          at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:752)
          at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
          at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295)
          at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
          at org.apache.syncope.core.persistence.jpa.spring.DomainTransactionInterceptor.invoke(DomainTransactionInterceptor.java:69)
          at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
          at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
          at ch.usp.syncope.core.provisioning.java.job.ExecLogic$$EnhancerBySpringCGLIB$$1.execute(<generated>)
          at ch.usp.syncope.core.provisioning.java.job.ExecEImpl.lambda$call$0(ExecEImpl.java:23)
          at org.apache.syncope.core.spring.security.AuthContextUtils.execWithAuthContext(AuthContextUtils.java:117)
          at ch.usp.syncope.core.provisioning.java.job.ExecEImpl.call(ExecEImpl.java:21)
          at ch.usp.syncope.core.provisioning.java.job.ExecEImpl.call(ExecEImpl.java:8)
          at java.util.concurrent.FutureTask.run(FutureTask.java:266)
          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
          at java.lang.Thread.run(Thread.java:748)
      Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'ch.usp.syncope.core.persistence.jpa.dao.UspPasswordRule' available
          at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:779)
          at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1221)
          at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedBeanDefinition(AbstractBeanFactory.java:1008)
          at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1214)
          at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1191)
          at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.resolvedCachedArgument(AutowiredAnnotationBeanPostProcessor.java:556)
          at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.access$000(AutowiredAnnotationBeanPostProcessor.java:118)
          at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586)
          at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
          at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:376)
          ... 31 more
      
      org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named '${beanName}' available
          at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:779)
          at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1221)
          at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedBeanDefinition(AbstractBeanFactory.java:1008)
          at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1214)
          at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1191)
          at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.resolvedCachedArgument(AutowiredAnnotationBeanPostProcessor.java:556)
          at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.access$000(AutowiredAnnotationBeanPostProcessor.java:118)
          at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586)
          at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
          at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:376)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1404)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
          at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:351)
          at sun.reflect.GeneratedMethodAccessor195.invoke(Unknown Source)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
          at java.lang.reflect.Method.invoke(Method.java:498)
          at com.zeroturnaround.javarebel.ix.invokeMethod(SourceFile:288)
          at org.apache.syncope.core.spring.ImplementationManager.buildJavaWithConf(ImplementationManager.java:240)
          at org.apache.syncope.core.spring.ImplementationManager.buildPasswordRule(ImplementationManager.java:112)
          at ch.usp.syncope.wrapper.ImplementationManagerWrapper.buildPasswordRule(ImplementationManagerWrapper.java:25)
          at ch.usp.syncope.core.provisioning.java.job.ExecLogic.getPasswordLifeTime(ExecLogic.java:89)
          at ch.usp.syncope.core.provisioning.java.job.ExecLogic.execute(ExecLogic.java:57)
          at ch.usp.syncope.core.provisioning.java.job.ExecLogic$$FastClassBySpringCGLIB$$1.invoke(<generated>)
          at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
          at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:752)
          at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
          at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:295)
          at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
          at org.apache.syncope.core.persistence.jpa.spring.DomainTransactionInterceptor.invoke(DomainTransactionInterceptor.java:69)
          at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
          at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
          at ch.usp.syncope.core.provisioning.java.job.ExecLogic$$EnhancerBySpringCGLIB$$1.execute(<generated>)
          at ch.usp.syncope.core.provisioning.java.job.ExecEImpl.lambda$call$0(ExecEImpl.java:23)
          at org.apache.syncope.core.spring.security.AuthContextUtils.execWithAuthContext(AuthContextUtils.java:117)
          at ch.usp.syncope.core.provisioning.java.job.ExecEImpl.call(ExecEImpl.java:21)
          at ch.usp.syncope.core.provisioning.java.job.ExecEImpl.call(ExecEImpl.java:8)
          at java.util.concurrent.FutureTask.run(FutureTask.java:266)
          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
          at java.lang.Thread.run(Thread.java:748)
      

      This may happen when two threads are trying to register singleton bean in Spring Application Context concurrently and at the same time. Thus, the org.apache.syncope.core.spring.ImplementationManager#buildJavaWithConf requires additional synchronization.

      Issue 2: Moreover, the rule that is registered as a singleton bean has a state that can be changed. And if there're more than one domain with the same rule type but a different configuration for this rule -> then wrong logic can be executed in runtime as a wrong configuration can be used for this domain.
      To solve this issue I see that for each domain the singleton bean should exist

      Attachments

        Issue Links

          Activity

            People

              ilgrosso Francesco Chicchiriccò
              DmitriyB. Dmitriy Brashevets
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: