Uploaded image for project: 'PUBLIC - Liferay Portal Community Edition'
  1. PUBLIC - Liferay Portal Community Edition
  2. LPS-128290

Local staging can cause circular parent page references in certain configurations

    Details

      Description

      Reproduction steps:

      1. Set up a new portal
      2. Activate on local staging on the default Liferay site
      3. Create a few random pages in staging and delete them (this makes sure that the layoutIds will be different between Live and Staging sites)
      4. Create 4 widget pages in a hierarchy: PageA ==> PageB ==> PageC ==> PageD
      5. Create new basic web content "WC1". In the content, create a link to PageD.
      6. Open PageB and add "WC1" in a web content display portlet
      7. Publish everything to Live
      8. Edit WC1, point the link to the Live version of PageD instead of the staging one. Basically, change the link "/web/guest-staging/paged" to "/web/guest/paged".
      9. Publish everything to Live again
      10. Shut down the portal
      11. Execute the following SQL commands on the portal's database. The purpose of this is to make some specific layoutIds equal. This can happen by accident as well, but for the reproduction, it's the only way to make sure:
        update Layout set layoutId = 555
        where friendlyURL = '/pageb'
        and groupId = (select g.groupId from Group_ g where g.friendlyURL = '/guest-staging');
        
        update Layout set parentLayoutId = 555
        where friendlyURL = '/pagec'
        and groupId = (select g.groupId from Group_ g where g.friendlyURL = '/guest-staging');
        
        update Layout set layoutId = 555
        where friendlyURL = '/paged'
        and groupId = (select g.groupId from Group_ g where g.friendlyURL = '/guest');
        
      1. Start the portal again, make sure the page structures look the same as before
      2. Start a new publication, select only PageC and PageD
      3. Open PageC in Live: http://localhost:8080/web/guest/pagec

      Expected: PageC is shown without any errors
      Actual: You are redirected to a random page and a StackOverflow error is thrown in the logs

      23-Feb-2021 17:42:15.515 SEVERE [http-nio-8080-exec-8] org.apache.catalina.core.ApplicationDispatcher.invoke Servlet.service() for servlet [Main Servlet] threw exception
              java.lang.StackOverflowError
                      at com.liferay.portal.servlet.filters.threadlocal.ThreadLocalFilterThreadLocal.isFilterInvoked(ThreadLocalFilterThreadLocal.java:25)
                      at com.liferay.portal.cache.internal.dao.orm.EntityCacheImpl._isLocalCacheEnabled(EntityCacheImpl.java:435)
                      at com.liferay.portal.cache.internal.dao.orm.EntityCacheImpl.getResult(EntityCacheImpl.java:169)
                      at com.liferay.portal.kernel.service.persistence.impl.BasePersistenceImpl.fetchByPrimaryKey(BasePersistenceImpl.java:295)
                      at com.liferay.portal.service.persistence.impl.LayoutPersistenceImpl.fetchByPrimaryKey(LayoutPersistenceImpl.java:15749)
                      at com.liferay.portal.service.persistence.impl.LayoutPersistenceImpl.fetchByPrimaryKey(LayoutPersistenceImpl.java:83)
                      at com.liferay.portal.cache.internal.dao.orm.FinderCacheImpl.getResult(FinderCacheImpl.java:220)
                      at com.liferay.portal.kernel.dao.orm.FinderCacheUtil.getResult(FinderCacheUtil.java:52)
                      at com.liferay.portal.service.persistence.impl.LayoutPersistenceImpl.fetchByG_P_L(LayoutPersistenceImpl.java:8896)
                      at com.liferay.portal.service.persistence.impl.LayoutPersistenceImpl.fetchByG_P_L(LayoutPersistenceImpl.java:8867)
                      at com.liferay.portal.service.persistence.impl.LayoutPersistenceImpl.findByG_P_L(LayoutPersistenceImpl.java:8827)
                      at com.liferay.portal.service.impl.LayoutLocalServiceImpl.getLayout(LayoutLocalServiceImpl.java:1276)
                      at sun.reflect.GeneratedMethodAccessor337.invoke(Unknown Source)
                      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                      at java.lang.reflect.Method.invoke(Method.java:498)
                      at com.liferay.portal.service.impl.LayoutLocalServiceStagingAdvice$LayoutLocalServiceStagingInvocationHandler._invoke(LayoutLocalServiceStagingAdvice.java:830)
                      at com.liferay.portal.service.impl.LayoutLocalServiceStagingAdvice$LayoutLocalServiceStagingInvocationHandler.invoke(LayoutLocalServiceStagingAdvice.java:681)
                      at com.sun.proxy.$Proxy121.getLayout(Unknown Source)
                      at sun.reflect.GeneratedMethodAccessor337.invoke(Unknown Source)
                      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                      at java.lang.reflect.Method.invoke(Method.java:498)
                      at com.liferay.portal.kernel.bean.ClassLoaderBeanHandler.invoke(ClassLoaderBeanHandler.java:66)
                      at com.sun.proxy.$Proxy975.getLayout(Unknown Source)
                      at com.liferay.portal.kernel.service.LayoutLocalServiceWrapper.getLayout(LayoutLocalServiceWrapper.java:825)
                      at sun.reflect.GeneratedMethodAccessor337.invoke(Unknown Source)
                      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                      at java.lang.reflect.Method.invoke(Method.java:498)
                      at com.liferay.portal.kernel.bean.ClassLoaderBeanHandler.invoke(ClassLoaderBeanHandler.java:66)
                      at com.sun.proxy.$Proxy976.getLayout(Unknown Source)
                      at sun.reflect.GeneratedMethodAccessor337.invoke(Unknown Source)
                      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
                      at java.lang.reflect.Method.invoke(Method.java:498)
                      at com.liferay.portal.spring.aop.AopMethodInvocationImpl.proceed(AopMethodInvocationImpl.java:50)
                      at com.liferay.portal.spring.transaction.TransactionInterceptor.invoke(TransactionInterceptor.java:69)
                      at com.liferay.portal.spring.aop.AopMethodInvocationImpl.proceed(AopMethodInvocationImpl.java:57)
                      at com.liferay.portal.spring.aop.AopInvocationHandler.invoke(AopInvocationHandler.java:49)
                      at com.sun.proxy.$Proxy121.getLayout(Unknown Source)
                      at com.liferay.portal.kernel.service.LayoutLocalServiceUtil.getLayout(LayoutLocalServiceUtil.java:806)
                      at com.liferay.portal.service.permission.LayoutPermissionImpl.containsWithoutViewableGroup(LayoutPermissionImpl.java:272)
                      at com.liferay.portal.service.permission.LayoutPermissionImpl.containsWithoutViewableGroup(LayoutPermissionImpl.java:340)
                      at com.liferay.portal.service.permission.LayoutPermissionImpl.containsWithViewableGroup(LayoutPermissionImpl.java:354)
                      at com.liferay.portal.service.permission.LayoutPermissionImpl._contains(LayoutPermissionImpl.java:616)
                      at com.liferay.portal.service.permission.LayoutPermissionImpl.contains(LayoutPermissionImpl.java:148)
                      at com.liferay.portal.service.permission.LayoutPermissionImpl.contains(LayoutPermissionImpl.java:162)
      

      Notes:

      • PageC and PageD will reference each other in their parentLayoutIds. This circular reference causes the permission check to fail.
      • The main cause of the issue is that during import, LayoutStagedModelDataHandler.doImportMissingReference(..) updates the layouts data map stored in PortletDataContext with the wrong layoutId. PageD is a missing reference from the web content's point of view, since it does not refer to a page in staging, but the one in live. Later, when the import of PageC is finished (LayoutStagedModelDataHandler.doImportStagedModel(..)), it finds the wrong layout in the PortletDataContext and updates the wrong parentLayoutId in the database.

        Attachments

          Activity

            People

            Assignee:
            yang.cao Yang Cao
            Reporter:
            vendel.toreki Vendel Töreki
            Participants of an Issue:
            Recent user:
            Rafaela Nascimento
            Engineering Assignee:
            Minhchau Dang
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved:
              Days since last comment:
              15 weeks, 3 days ago

                Packages

                Version Package
                7.2.10 DXP FP12
                7.2.X
                7.3.X
                7.4.0 CE GA1
                Master