Uploaded image for project: 'Crowd Data Center'
  1. Crowd Data Center
  2. CWD-3255

Incremental sync fails after authentication if default groups have been added to a remote Crowd directory or the user has been synced via authentication

      Symptoms

      The next incremental sync just after an authentication fails and produces an stacktrace in the logs:

      2013-04-12 10:21:48,053 scheduler_Worker-1 ERROR [atlassian.crowd.directory.DbCachingRemoteDirectory] Incremental synchronisation was unexpectedly interrupted, falling back to a full synchronisation
      com.atlassian.crowd.exception.MembershipAlreadyExistsException: Membership already exists in directory [32770] from child entity [user] to parent entity [group]
      	at com.atlassian.crowd.dao.membership.MembershipDAOHibernate.addUserToGroup(MembershipDAOHibernate.java:102)
      	at com.atlassian.crowd.directory.AbstractInternalDirectory.addUserToGroup(AbstractInternalDirectory.java:712)
      	at com.atlassian.crowd.directory.DbCachingRemoteChangeOperations.addUserToGroup(DbCachingRemoteChangeOperations.java:1151)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:601)
      	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:319)
      	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
      	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
      	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
      	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
      	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
      	at com.atlassian.crowd.directory.$Proxy159.addUserToGroup(Unknown Source)
      	at com.atlassian.crowd.directory.DirectoryCacheImplUsingChangeOperations.addUserToGroup(DirectoryCacheImplUsingChangeOperations.java:189)
      	at com.atlassian.crowd.directory.ldap.cache.EventTokenChangedCacheRefresher.synchroniseChanges(EventTokenChangedCacheRefresher.java:119)
      	at com.atlassian.crowd.directory.DbCachingRemoteDirectory.synchroniseCache(DbCachingRemoteDirectory.java:629)
      	at com.atlassian.crowd.manager.directory.DirectorySynchroniserImpl.synchronise(DirectorySynchroniserImpl.java:63)
      	at com.atlassian.crowd.directory.DbCachingDirectoryPoller.pollChanges(DbCachingDirectoryPoller.java:50)
      

      Steps to reproduce

      1. Set up a Remote Crowd directory, configure it to automatically add users to a group on login.
      2. Sync the directory.
      3. In the remote Crowd server, create a user. Do not add him to the group.
      4. Authenticate as the new user in the client application. This causes the user and his memberships to be copied from the server. It also causes the user to be added to the default group in both the client application and the remote server.
      5. Sync the directory.

      Expected result

      Client and server are already in sync, the incremental sync should succeed without making any update.

      Actual outcome

      Incremental sync attempts to create the membership to the default group again. Since this membership already exists in the client, an exception is thrown and incremental sync fails.

          Form Name

            [CWD-3255] Incremental sync fails after authentication if default groups have been added to a remote Crowd directory or the user has been synced via authentication

            how about a Release Date of Crowd 2.10 ?

            Patrick Joericke added a comment - how about a Release Date of Crowd 2.10 ?

            Needs checking whether the fallback is working as expected. We've seen a GroupMembershipAlreadyExists exception, which failed the incremental sync, and didn't fall back to the full sync (as com.atlassian.crowd.directory.DbCachingRemoteDirectory#synchroniseCache only seems to do that on RuntimeExceptions).

            Associated stacktrace is :

            2016-06-01 07:23:48,344 ERROR [schedulerServiceQuartzScheduler_Worker-9 ] com.atlassian.crowd.directory.DbCachingDirectoryPoller noClassMethodInfo - Error occurred while refreshing the cache for directo
            ry [ 2 ].
            com.atlassian.crowd.exception.OperationFailedException: com.atlassian.crowd.exception.MembershipAlreadyExistsException: Membership already exists in directory [2] from child entity [tzwierzchowski] to p
            arent entity [gdansk]
                    at com.atlassian.crowd.directory.DbCachingRemoteChangeOperations.addUserToGroup(DbCachingRemoteChangeOperations.java:1380)
                    at com.atlassian.crowd.directory.DirectoryCacheImplUsingChangeOperations.addUserToGroup(DirectoryCacheImplUsingChangeOperations.java:203)
                    at com.atlassian.crowd.directory.ldap.cache.EventTokenChangedCacheRefresher.synchroniseChanges(EventTokenChangedCacheRefresher.java:172)
                    at com.atlassian.crowd.directory.DbCachingRemoteDirectory.synchroniseCache(DbCachingRemoteDirectory.java:1119)
                    at com.atlassian.crowd.manager.directory.DirectorySynchroniserImpl.synchronise(DirectorySynchroniserImpl.java:76)
                    at sun.reflect.GeneratedMethodAccessor2550.invoke(Unknown Source)
                    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                    at java.lang.reflect.Method.invoke(Method.java:498)
                    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
                    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
                    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
                    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
                    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
                    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
                    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
                    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
                    at com.sun.proxy.$Proxy80.synchronise(Unknown Source)
                    at com.atlassian.fecru.user.crowd.NotifyingDirectorySynchroniser.synchronise(NotifyingDirectorySynchroniser.java:26)
                    at com.atlassian.crowd.directory.DbCachingDirectoryPoller.pollChanges(DbCachingDirectoryPoller.java:50)
                    at com.atlassian.crowd.manager.directory.monitor.poller.DirectoryPollerJobRunner.runJob(DirectoryPollerJobRunner.java:93)
                    at com.atlassian.fecru.scheduler.FeCruSchedulerService$SessionTerminatingJobRunner.runJob(FeCruSchedulerService.java:71)
                    at com.atlassian.scheduler.core.JobLauncher.runJob(JobLauncher.java:153)
                    at com.atlassian.scheduler.core.JobLauncher.launchAndBuildResponse(JobLauncher.java:118)
                    at com.atlassian.scheduler.core.JobLauncher.launch(JobLauncher.java:97)
                    at com.atlassian.scheduler.quartz1.Quartz1Job.execute(Quartz1Job.java:32)
                    at org.quartz.core.JobRunShell.run(JobRunShell.java:195)
                    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520)
            Caused by: com.atlassian.crowd.exception.MembershipAlreadyExistsException: Membership already exists in directory [2] from child entity [foo] to parent entity [bar]
                    at com.atlassian.crowd.dao.membership.MembershipDAOHibernate.addUserToGroup(MembershipDAOHibernate.java:150)
                    at sun.reflect.GeneratedMethodAccessor1723.invoke(Unknown Source)
                    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                    at java.lang.reflect.Method.invoke(Method.java:498)
                    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
                    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
                    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
                    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
                    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
                    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
                    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
                    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
                    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
                    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
                    at com.sun.proxy.$Proxy73.addUserToGroup(Unknown Source)
            

            Lukasz Pater added a comment - Needs checking whether the fallback is working as expected. We've seen a GroupMembershipAlreadyExists exception, which failed the incremental sync, and didn't fall back to the full sync (as com.atlassian.crowd.directory.DbCachingRemoteDirectory#synchroniseCache only seems to do that on RuntimeExceptions). Associated stacktrace is : 2016-06-01 07:23:48,344 ERROR [schedulerServiceQuartzScheduler_Worker-9 ] com.atlassian.crowd.directory.DbCachingDirectoryPoller noClassMethodInfo - Error occurred while refreshing the cache for directo ry [ 2 ]. com.atlassian.crowd.exception.OperationFailedException: com.atlassian.crowd.exception.MembershipAlreadyExistsException: Membership already exists in directory [2] from child entity [tzwierzchowski] to p arent entity [gdansk] at com.atlassian.crowd.directory.DbCachingRemoteChangeOperations.addUserToGroup(DbCachingRemoteChangeOperations.java:1380) at com.atlassian.crowd.directory.DirectoryCacheImplUsingChangeOperations.addUserToGroup(DirectoryCacheImplUsingChangeOperations.java:203) at com.atlassian.crowd.directory.ldap.cache.EventTokenChangedCacheRefresher.synchroniseChanges(EventTokenChangedCacheRefresher.java:172) at com.atlassian.crowd.directory.DbCachingRemoteDirectory.synchroniseCache(DbCachingRemoteDirectory.java:1119) at com.atlassian.crowd.manager.directory.DirectorySynchroniserImpl.synchronise(DirectorySynchroniserImpl.java:76) at sun.reflect.GeneratedMethodAccessor2550.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) at com.sun.proxy.$Proxy80.synchronise(Unknown Source) at com.atlassian.fecru.user.crowd.NotifyingDirectorySynchroniser.synchronise(NotifyingDirectorySynchroniser.java:26) at com.atlassian.crowd.directory.DbCachingDirectoryPoller.pollChanges(DbCachingDirectoryPoller.java:50) at com.atlassian.crowd.manager.directory.monitor.poller.DirectoryPollerJobRunner.runJob(DirectoryPollerJobRunner.java:93) at com.atlassian.fecru.scheduler.FeCruSchedulerService$SessionTerminatingJobRunner.runJob(FeCruSchedulerService.java:71) at com.atlassian.scheduler.core.JobLauncher.runJob(JobLauncher.java:153) at com.atlassian.scheduler.core.JobLauncher.launchAndBuildResponse(JobLauncher.java:118) at com.atlassian.scheduler.core.JobLauncher.launch(JobLauncher.java:97) at com.atlassian.scheduler.quartz1.Quartz1Job.execute(Quartz1Job.java:32) at org.quartz.core.JobRunShell.run(JobRunShell.java:195) at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520) Caused by: com.atlassian.crowd.exception.MembershipAlreadyExistsException: Membership already exists in directory [2] from child entity [foo] to parent entity [bar] at com.atlassian.crowd.dao.membership.MembershipDAOHibernate.addUserToGroup(MembershipDAOHibernate.java:150) at sun.reflect.GeneratedMethodAccessor1723.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) at com.sun.proxy.$Proxy73.addUserToGroup(Unknown Source)

            So is this fixed in post 2.6?

            Patrick van der Rijst added a comment - So is this fixed in post 2.6?

            David Adam added a comment -

            Well, we use Confluence 5.7 which syncs from a Crowd 2.6.4 and the issue still occurs in Confluence.

            David Adam added a comment - Well, we use Confluence 5.7 which syncs from a Crowd 2.6.4 and the issue still occurs in Confluence.

            We still use Crowd 2.6.4 and the issue still occurs on our end. And Crowd doesn't fall back to full sync.

            David Adam added a comment - We still use Crowd 2.6.4 and the issue still occurs on our end. And Crowd doesn't fall back to full sync.

            The fix for CWD-3188 reduces the severity of the problem, since failed incremental synchronisation now immediately fallbacks to full sync, without the need to implement any workaround. After the successful full sync, the sync will revert to incremental again, also automatically.

            A "duplicate key" exception may still be logged, but it will not prevent the sync from completing successfully.

            The root cause of the problem still persists, i.e., Crowd still generates a "membership added" event that is inconsistent with the client state. Note, however, that it does not cause any serious harm to the client application (if it contains the fix for CWD-3188) besides the exception in the logs and the performance penalty associated with falling back to a full sync (just once).

            Diego Berrueta added a comment - The fix for CWD-3188 reduces the severity of the problem, since failed incremental synchronisation now immediately fallbacks to full sync, without the need to implement any workaround. After the successful full sync, the sync will revert to incremental again, also automatically. A "duplicate key" exception may still be logged, but it will not prevent the sync from completing successfully. The root cause of the problem still persists, i.e., Crowd still generates a "membership added" event that is inconsistent with the client state. Note, however, that it does not cause any serious harm to the client application (if it contains the fix for CWD-3188 ) besides the exception in the logs and the performance penalty associated with falling back to a full sync (just once).

              ppetrowski Patryk
              dberrueta Diego Berrueta
              Affected customers:
              8 This affects my team
              Watchers:
              20 Start watching this issue

                Created:
                Updated:
                Resolved: