-
Bug
-
Resolution: Fixed
-
High
-
9.2.7
-
Severity 2 - Major
-
Issue Summary
Apart from displaying all favourited (Saved for Later) pages, the Favourite Pages Macro will display all pages that have been labelled with "favourite".
If an anonymous user visits a page with the Favourite Pages Macro, the macro will trigger a query to all favourite pages and check permissions on all pages.
Fixed in 9.2.10
Steps to Reproduce
- Assuming several hundred pages have been labelled with the "favourite" label
- Create a page with the "Favourite Pages Macro"
- Visit the page with the Favourite Pages Macro as an anonymous user
Expected Results
The "Favourite Pages Macro" displays normally, and pagination is applied in the background to accommodate a large number of favourite pages.
Actual Results
The "Favourite Pages Macro" tries to query all favourite pages, checks their permissions, and only limits the results at the very end.
contents.addAll(labelManager.getContentForLabel(LabelManagerInternal.NO_OFFSET, LabelManagerInternal.NO_MAX_RESULTS, label).getList()); ... contents = permissionManager.getPermittedEntities(AuthenticatedUserThreadLocal.get(), Permission.VIEW, contents); ... #set ($contentSublist = $generalUtil.safeSubList($contents, $maxResults))
There is a high chance of stuck threads building up, such as the one below:
"http-nio-8090-exec-120 url: /pages/viewpage.action" #30615 [426048] daemon prio=5 os_prio=0 cpu=449066.11ms elapsed=54782.61s tid=0x00007f4380344e80 nid=426048 runnable [0x00007f42374f1000] java.lang.Thread.State: RUNNABLE at org.hibernate.internal.util.collections.IdentityMap.get(IdentityMap.java:104) at org.hibernate.engine.internal.StatefulPersistenceContext.getCollectionEntry(StatefulPersistenceContext.java:484) at org.hibernate.engine.internal.Collections.processReachableCollection(Collections.java:151) at org.hibernate.event.internal.FlushVisitor.processCollection(FlushVisitor.java:53) at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:104) at org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:65) at org.hibernate.event.internal.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:59) at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:187) at org.hibernate.event.internal.AbstractFlushingEventListener$$Lambda/0x00007f444a26ed58.accept(Unknown Source) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:229) at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:93) at org.hibernate.event.internal.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:50) at org.hibernate.internal.SessionImpl$$Lambda/0x00007f4449bcfb78.accept(Unknown Source) at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:107) at org.hibernate.internal.SessionImpl.autoFlushIfRequired(SessionImpl.java:1372) at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1452) at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1649) at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1617) at com.atlassian.confluence.security.persistence.dao.hibernate.HibernateContentPermissionSetDao.lambda$getInheritedContentPermissionSets$2(HibernateContentPermissionSetDao.java:133) at com.atlassian.confluence.security.persistence.dao.hibernate.HibernateContentPermissionSetDao$$Lambda/0x00007f444bd1fdc0.doInHibernate(Unknown Source) at org.springframework.orm.hibernate5.HibernateTemplate.doExecute(HibernateTemplate.java:366) at org.springframework.orm.hibernate5.HibernateTemplate.execute(HibernateTemplate.java:319) at com.atlassian.confluence.security.persistence.dao.hibernate.HibernateContentPermissionSetDao.getInheritedContentPermissionSets(HibernateContentPermissionSetDao.java:104) at com.atlassian.confluence.core.DefaultInheritedContentPermissionManager.getInheritedContentPermissionSets(DefaultInheritedContentPermissionManager.java:44) at com.atlassian.confluence.core.DefaultInheritedContentPermissionManager.getInheritedContentPermissionSetsIncludeEdit(DefaultInheritedContentPermissionManager.java:37) at com.atlassian.confluence.impl.security.CachingInheritedContentPermissionManager.lambda$getInheritedContentPermissionSets$2(CachingInheritedContentPermissionManager.java:96) at com.atlassian.confluence.impl.security.CachingInheritedContentPermissionManager$$Lambda/0x00007f444bce73e0.get(Unknown Source) at com.atlassian.confluence.impl.security.ContentPermissionSetCache.lambda$getOrLoad$0(ContentPermissionSetCache.java:41) at com.atlassian.confluence.impl.security.ContentPermissionSetCache$$Lambda/0x00007f444bce77e8.get(Unknown Source) at com.atlassian.confluence.cache.CacheOperations.lambda$get$0(CacheOperations.java:172) at com.atlassian.confluence.cache.CacheOperations$$Lambda/0x00007f4449bc9d80.apply(Unknown Source) at java.util.HashMap.computeIfAbsent(java.base@21.0.7/HashMap.java:1228) at com.atlassian.confluence.cache.CacheOperations.get(CacheOperations.java:172) at com.atlassian.confluence.cache.DeferredOperationsCache.getOrLoad(DeferredOperationsCache.java:92) at com.atlassian.confluence.cache.DeferredOperationsCache.get(DeferredOperationsCache.java:56) at com.atlassian.confluence.cache.TransactionalCacheFactory$TransactionalCache.get(TransactionalCacheFactory.java:327) at com.atlassian.confluence.impl.cache.tx.TransactionAwareCache$1.get(TransactionAwareCache.java:43) at com.atlassian.confluence.impl.security.ContentPermissionSetCache.getOrLoad(ContentPermissionSetCache.java:39) at com.atlassian.confluence.impl.security.CachingInheritedContentPermissionManager.getInheritedContentPermissionSets(CachingInheritedContentPermissionManager.java:96) at com.atlassian.confluence.impl.security.CachingInheritedContentPermissionManager.getInheritedContentPermissionSetsIncludeEdit(CachingInheritedContentPermissionManager.java:87) at com.atlassian.confluence.core.DefaultContentPermissionManager.getInheritedContentPermissionSets(DefaultContentPermissionManager.java:175) at com.atlassian.confluence.core.DefaultContentPermissionManager.hasInheritedContentLevelViewPermissions(DefaultContentPermissionManager.java:310) at com.atlassian.confluence.core.DefaultContentPermissionManager.hasContentLevelPermission(DefaultContentPermissionManager.java:212) at java.lang.invoke.LambdaForm$DMH/0x00007f444bcd4000.invokeInterface(java.base@21.0.7/LambdaForm$DMH) at java.lang.invoke.LambdaForm$MH/0x00007f444bfb4800.invoke(java.base@21.0.7/LambdaForm$MH) at java.lang.invoke.LambdaForm$MH/0x00007f4448004800.invokeExact_MT(java.base@21.0.7/LambdaForm$MH) at jdk.internal.reflect.DirectMethodHandleAccessor.invokeImpl(java.base@21.0.7/DirectMethodHandleAccessor.java:156) at jdk.internal.reflect.DirectMethodHandleAccessor.invoke(java.base@21.0.7/DirectMethodHandleAccessor.java:103) at java.lang.reflect.Method.invoke(java.base@21.0.7/Method.java:580) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:355) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.transaction.interceptor.TransactionInterceptor$$Lambda/0x00007f4449a1c3c8.proceedWithInvocation(Unknown Source) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:379) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223) at jdk.proxy4.$Proxy250.hasContentLevelPermission(jdk.proxy4/Unknown Source) at com.atlassian.confluence.security.delegate.PagePermissionsDelegate.hasContentLevelViewPermission(PagePermissionsDelegate.java:132) at com.atlassian.confluence.security.delegate.PagePermissionsDelegate.canView(PagePermissionsDelegate.java:24) at com.atlassian.confluence.security.delegate.PagePermissionsDelegate.canView(PagePermissionsDelegate.java:13) at com.atlassian.confluence.security.delegate.TargetToLatestVersionDecorator.canView(TargetToLatestVersionDecorator.java:24) at com.atlassian.confluence.security.delegate.SharedAccessInterceptor$$Lambda/0x00007f444bcd9060.test(Unknown Source) at com.atlassian.confluence.security.delegate.SharedAccessInterceptor.checkAccess(SharedAccessInterceptor.java:88) at com.atlassian.confluence.security.delegate.SharedAccessInterceptor.canView(SharedAccessInterceptor.java:26) at com.atlassian.confluence.security.Permission$1.checkAgainst(Permission.java:19) at com.atlassian.confluence.security.DefaultPermissionManager.hasPermissionNoExemptions(DefaultPermissionManager.java:116) at com.atlassian.confluence.security.DefaultPermissionManager.hasPermission(DefaultPermissionManager.java:57) at com.atlassian.confluence.security.DefaultPermissionManager.getPermittedEntities(DefaultPermissionManager.java:177) at java.lang.invoke.LambdaForm$DMH/0x00007f4449590000.invokeInterface(java.base@21.0.7/LambdaForm$DMH) at java.lang.invoke.LambdaForm$MH/0x00007f4449739400.invoke(java.base@21.0.7/LambdaForm$MH) at java.lang.invoke.LambdaForm$MH/0x00007f4448004800.invokeExact_MT(java.base@21.0.7/LambdaForm$MH) at jdk.internal.reflect.DirectMethodHandleAccessor.invokeImpl(java.base@21.0.7/DirectMethodHandleAccessor.java:156) at jdk.internal.reflect.DirectMethodHandleAccessor.invoke(java.base@21.0.7/DirectMethodHandleAccessor.java:103) at java.lang.reflect.Method.invoke(java.base@21.0.7/Method.java:580) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:355) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at com.atlassian.spring.interceptors.SpringProfilingInterceptor.invoke(SpringProfilingInterceptor.java:16) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.transaction.interceptor.TransactionInterceptor$$Lambda/0x00007f4449a1c3c8.proceedWithInvocation(Unknown Source) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:379) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223) at jdk.proxy4.$Proxy240.getPermittedEntities(jdk.proxy4/Unknown Source) at java.lang.invoke.LambdaForm$DMH/0x00007f4449590000.invokeInterface(java.base@21.0.7/LambdaForm$DMH) at java.lang.invoke.LambdaForm$MH/0x00007f4449739400.invoke(java.base@21.0.7/LambdaForm$MH) at java.lang.invoke.LambdaForm$MH/0x00007f4448004800.invokeExact_MT(java.base@21.0.7/LambdaForm$MH) at jdk.internal.reflect.DirectMethodHandleAccessor.invokeImpl(java.base@21.0.7/DirectMethodHandleAccessor.java:156) at jdk.internal.reflect.DirectMethodHandleAccessor.invoke(java.base@21.0.7/DirectMethodHandleAccessor.java:103) at java.lang.reflect.Method.invoke(java.base@21.0.7/Method.java:580) at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:26) at jdk.proxy4.$Proxy375.getPermittedEntities(jdk.proxy4/Unknown Source) at java.lang.invoke.LambdaForm$DMH/0x00007f4449590000.invokeInterface(java.base@21.0.7/LambdaForm$DMH) at java.lang.invoke.LambdaForm$MH/0x00007f4449739400.invoke(java.base@21.0.7/LambdaForm$MH) at java.lang.invoke.LambdaForm$MH/0x00007f4448004800.invokeExact_MT(java.base@21.0.7/LambdaForm$MH) at jdk.internal.reflect.DirectMethodHandleAccessor.invokeImpl(java.base@21.0.7/DirectMethodHandleAccessor.java:156) at jdk.internal.reflect.DirectMethodHandleAccessor.invoke(java.base@21.0.7/DirectMethodHandleAccessor.java:103) at java.lang.reflect.Method.invoke(java.base@21.0.7/Method.java:580) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:56) at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:60) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:70) at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:53) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.eclipse.gemini.blueprint.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:57) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:241) at jdk.proxy10.$Proxy1017.getPermittedEntities(jdk.proxy10/Unknown Source) at com.atlassian.confluence.plugins.macros.advanced.FavouritePagesMacro.execute(FavouritePagesMacro.java:68) at com.atlassian.renderer.v2.macro.ResourceAwareMacroDecorator.execute(ResourceAwareMacroDecorator.java:51) at com.atlassian.confluence.macro.V2CompatibilityMacro.execute(V2CompatibilityMacro.java:35) at com.atlassian.confluence.macro.LazyLoadingMacroWrapper.execute(LazyLoadingMacroWrapper.java:27) at com.atlassian.confluence.content.render.xhtml.view.macro.ViewMacroMarshaller.executeMacro(ViewMacroMarshaller.java:244) at com.atlassian.confluence.content.render.xhtml.view.macro.ViewMacroMarshaller.marshalInternal(ViewMacroMarshaller.java:159) at com.atlassian.confluence.content.render.xhtml.view.macro.ViewMacroMarshaller.lambda$marshal$0(ViewMacroMarshaller.java:116) at com.atlassian.confluence.content.render.xhtml.view.macro.ViewMacroMarshaller$$Lambda/0x00007f444be6cfc8.marshal(Unknown Source) at com.atlassian.confluence.impl.content.render.xhtml.analytics.MetricsCollectingMarshaller.marshal(MetricsCollectingMarshaller.java:49) at com.atlassian.confluence.content.render.xhtml.view.macro.ViewMacroMarshaller.marshal(ViewMacroMarshaller.java:120) at com.atlassian.confluence.content.render.xhtml.view.macro.ViewMacroMarshaller.marshal(ViewMacroMarshaller.java:52) at com.atlassian.confluence.content.render.xhtml.UnmarshalMarshalFragmentTransformer.transform(UnmarshalMarshalFragmentTransformer.java:29) at com.atlassian.confluence.content.render.xhtml.transformers.DefaultFragmentTransformer.transformFragment(DefaultFragmentTransformer.java:141) at com.atlassian.confluence.content.render.xhtml.transformers.DefaultFragmentTransformer.transform(DefaultFragmentTransformer.java:123) at com.atlassian.confluence.content.render.xhtml.view.ViewTableWrappingFragmentTransformer.transform(ViewTableWrappingFragmentTransformer.java:62) at com.atlassian.confluence.content.render.xhtml.transformers.DefaultFragmentTransformer.transformFragment(DefaultFragmentTransformer.java:141) at com.atlassian.confluence.content.render.xhtml.transformers.DefaultFragmentTransformer.transform(DefaultFragmentTransformer.java:123) at com.atlassian.confluence.content.render.xhtml.storage.StorageXhtmlTransformer.transform(StorageXhtmlTransformer.java:41) at com.atlassian.confluence.content.render.xhtml.TransformerChain.transform(TransformerChain.java:38) at com.atlassian.confluence.content.render.xhtml.TransformerChain.transform(TransformerChain.java:38) at com.atlassian.confluence.content.render.xhtml.PluggableTransformerChain.transform(PluggableTransformerChain.java:42) at com.atlassian.confluence.content.render.xhtml.DefaultRenderer.renderWithoutMetrics(DefaultRenderer.java:190) at com.atlassian.confluence.content.render.xhtml.DefaultRenderer.renderWithResult(DefaultRenderer.java:151) at com.atlassian.confluence.content.render.xhtml.DefaultRenderer.render(DefaultRenderer.java:135) at com.atlassian.confluence.content.render.xhtml.DefaultRenderer.render(DefaultRenderer.java:118) at com.atlassian.confluence.content.render.xhtml.DefaultRenderer.render(DefaultRenderer.java:112) at com.atlassian.confluence.content.render.xhtml.DeviceTypeAwareRenderer.render(DeviceTypeAwareRenderer.java:43) at com.atlassian.confluence.pages.actions.ViewPageAction.execute(ViewPageAction.java:208)
Workaround
Temporarily replace "Favourite Pages Macro with the "List Labels Macro" as the "List Labels Macro" has a pagination service that would avoid querying all pages at once.