Expand my Community achievements bar.

SOLVED

[AEM6.5] Issue with PageManager API to move content from one path to another within same hirearchy.

Avatar

Level 2

The problem I am facing here that If I move the node from one path to another by creating the same hirearchy and if we move the parent of parent node then I am facing issues like some pages are not moving means the pages whoes child or child of childs are already moved,
I am moving and iterating the node using PageManager API

Example if we pass payload to our workflow : [/content/project/websites/en-us/c/cfolder/cfolder-relateddocs/elevated/super-parent-1/parent-b/child-b/child-of-child-b/grand-child-b]

Marcos_aem_5-1681979519995.png

So we can see our code perfectly moved the grand-child-b to /content/archived/websites/en-us/c/cfolder/cfolder-relateddocs/elevated/super-parent-1/parent-b/child-b/child-of-child-b/grand-child-b: 

Marcos_aem_1-1681977495139.png

 

But Now if we want to move parent-b [/content/archived/websites/en-us/c/cfolder/cfolder-relateddocs/elevated/super-parent-1/parent-b]
the expectation will be it should move all the node from source and retain the already moved node : 

Marcos_aem_6-1681979674204.png

 

But it is moving its child of childs of first child page and returns out of loop:
Archived like only chid of child-b moved and it came out of loop:

Marcos_aem_8-1681979888852.png

 

and we can see in source : in the child-b jcr:content and childs are are moved and rest didn't moved

Marcos_aem_9-1681980003026.png

 

 Can Anyone please guide here the optimized approach to achive this issue:
here is the sample code I have written for this

 

@Override
    public void execute(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap metaDataMap) throws WorkflowException {
        String payload = workItem.getWorkflowData().getPayload().toString();
        ResourceResolver resourceResolver = resourceResolverUtil.getResourceResolver();
        Session session = resourceResolver.adaptTo(Session.class);
        Page rootPage = Objects.requireNonNull(resourceResolver.getResource(payload)).adaptTo(Page.class);
        Resource resource = resourceResolver.getResource(payload);
        PageManager pageManager = resourceResolver.adaptTo(PageManager.class);
        if (rootPage != null) {
            List<String> list = new ArrayList<>();
            list.add(payload);
            Iterator<Page> childPages;
            childPages = rootPage.listChildren(new PublishedPageFilter(), true);
            if (childPages != null) {
                while (childPages.hasNext()) {
                    Page page1 = childPages.next();
                    list.add(page1.getPath());
                }
            }
            String[] paths = list.toArray(new String[0]);
            try {
                assert resource != null;
                Page page = resource.adaptTo(Page.class);
                String archivePath = StringUtils.substringAfter(payload, ROOT_PATH);
                archivePath = StringUtils.substringBeforeLast(archivePath, DELIMITER_SLASH);
                archivePath = StringUtils.join("/content/archived", archivePath);
                Node archived = JcrUtils.getOrCreateByPath(archivePath, "cq:Page", session);
                String targetPath = archived.getPath() + "/" + rootPage.getName();
                if (session.nodeExists(targetPath)) {
                    callingChildOc(pageManager, rootPage, session);
                } else {
                    if (pageManager != null) {
                        pageManager.move(page, targetPath, null, false, true, null);
                    }
                }
                if (!session.nodeExists(targetPath + "/jcr:content") && session.nodeExists(rootPage.getPath() + "/jcr:content")) {
                    Node jcr = session.getNode(rootPage.getPath() + "/jcr:content");
                    String targetJcr = jcr.getPath().replace("/content/project", "/content/archived");
                    session.move(jcr.getPath(), targetJcr);
                    pageManager.delete(rootPage, true);
                    //session.save();

                }
                session.save();
           } catch (RepositoryException | WCMException e) {
                loggerService.postLog(LogLevel.ERROR, "RepositoryException exception occurred at :: {}" + Arrays.toString(paths));
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                if (resourceResolver.isLive()) {
                    resourceResolver.close();
                }

            }
        } else {
            String workflowId = workItem.getWorkflow().getId();
            Workflow workflow = workflowSession.getWorkflow(workflowId);
            workflowSession.terminateWorkflow(workflow);
            loggerService.postLog(LogLevel.ERROR, "Workflow Terminated as path does not start with /content/wem-content :: {}" + workflowId + " or payload is having more than one level of child pages ");
        }
    }

    private static void callingChildOc(PageManager pageManager, Page rootPath, Session session) throws WCMException, RepositoryException, InterruptedException {
        Iterator<Page> childIterators = rootPath.listChildren();
        LOG.debug("1  :: " + rootPath.getName());
        if (childIterators != null) {
            while (childIterators.hasNext()) {
                Page innerPage = childIterators.next();
                callingChildOc(pageManager, innerPage, session);
            }
        }
        String rootPathPayload = rootPath.getPath();
        LOG.debug("2 :: {}" + rootPathPayload);
        String childOfChildPathTarget = rootPathPayload.replace("/content/wem-content", "/content/wem-archived");

        if (!session.nodeExists(childOfChildPathTarget)) {
            LOG.debug("3 archive  ::{}" + childOfChildPathTarget);
            pageManager.move(rootPath, childOfChildPathTarget, null, false, true, null);
        } else {
            if (!session.nodeExists(rootPathPayload.replace("/content/wem-content", "/content/wem-archived") + "/jcr:content")
                    && session.nodeExists(rootPathPayload + "/jcr:content")) {
                Node jcr = session.getNode(rootPath.getPath() + "/jcr:content");
                String childOfChildPathTargets = jcr.getPath().replace("/content/wem-content", "/content/wem-archived");
                LOG.debug("4 final jcr move :: {}" + childOfChildPathTargets);
                session.move(jcr.getPath(), childOfChildPathTargets);
                pageManager.delete(rootPath, true);
                //session.save();
            }
        }

    }
    
}

 

 

Thanks

@arunpatidar  @kautuk_sahni  @lukasz-m  @Tanika02 

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

@Marcos_aem - 

Hope below solution helps for recursive movement of child nodes from source to the target.

private static void callingChildOc(PageManager pageManager, Page rootPage, Session session) throws WCMException {
    Iterator<Page> childIterators = rootPage.listChildren();
    if (childIterators != null) {
        while (childIterators.hasNext()) {
            Page childPage = childIterators.next();
            String childPath = childPage.getPath();
            String childArchivePath = StringUtils.replace(childPath, "/content/project", "/content/archived");
            if (!session.nodeExists(childArchivePath)) {
                pageManager.move(childPage, childArchivePath, null, false, true, null);
            } else{
            callingChildOc(pageManager, childPage, session);
        }
    }
}

View solution in original post

8 Replies

Avatar

Level 2

True, similar implementation is done on above code but

This issue here is if we move the parent of parent node then I am getting ItemExistException or IllegaleArgumentException shallow not possible on empty page aem

Example if I move page from child-1 [/content/project/partent/sub-parent/child-1]

/content
   /project

      /partent

        /sub-parent

          /child-1

          /child-2

So our code will move it to  [/content/archived/parent/sub-parent/child-1]

But Getting exception when I am moving Parent page [/content/archived/parent] {ItemExistException or shallow not possible on empty page aem.

Avatar

Level 6

@Marcos_aem 

ItemExistException is thrown because you already have page with same name at location where you trying to move a page and shallow not possible on empty page is thrown when there is no jcr:content node under a page and you try that page move with shallow option as 'true'.

 

Can you try this below code? I have tested it in my local and it works.

 

public void execute(WorkItem item, WorkflowSession session, MetaDataMap args)
      throws WorkflowException {
    final WorkflowData workflowData = item.getWorkflowData();
    String payload = workflowData.getPayload().toString();
    PageManager pageManager = resourceResolver.adaptTo(PageManager.class);
    Page pageTreeToMove = pageManager.getPage(payload);
    // Assuming /content/archived hierarchy already exists (This needs to be created manually)
    String[] strArray = StringUtils.split(pageTreeToMove.getPath(), "/");
    String targetRootPath = "/content/archived";
    String sourceRootPath = "/" + strArray[0] + "/" + strArray[1];

    String sourcePath = sourceRootPath;
    String targetPath = targetRootPath;

    for (int i = 2; i < strArray.length; i++) { // Skipping /content/project
      sourcePath = sourcePath + "/" + strArray[i];
      targetPath = targetPath + "/" + strArray[i];
      Page sourcePage = pageManager.getPage(sourcePath);
      Page targetPage = pageManager.getPage(targetPath);
      if (Objects.isNull(targetPage)) {
        try {
          pageManager.move(sourcePage, targetPath, null, true, false, new String[] {});
        } catch (WCMException e) {
          log.error("error occured while moving parent pages: ", e);
        }
      }
    }

    Iterator<Page> childPagesIterator = pageTreeToMove.listChildren();
    while (childPagesIterator.hasNext()) {
      Page childPage = childPagesIterator.next();
      String childPageArchivePath =
          StringUtils.replace(childPage.getPath(), sourceRootPath, "/content/archived");
      if (Objects.isNull(pageManager.getPage(childPageArchivePath))) {
        try {
          pageManager.move(childPage, childPageArchivePath, null, false, false, new String[] {});
        } catch (WCMException e) {
          log.error("error occured while moving child pages: ", e);
        }
      }
    }
  }

 

Here I am first moving whole parent pages hierarchy by checking each page in hierarchy if its exist or not in archived path. Please note here that shallow option is set to true. After moving parent hierarchy I am moving all child pages by setting shallow option as false.

Avatar

Level 2

Hi @salamswapnil ,

I tried with the approach you suggested it is still breaking for me  I have updated the above question with my working code, the only thing is it is breaking for some hirearchy which is already present in moved path.

Could you please review the above and provide your guidance 
Thanks

 

Avatar

Community Advisor

@Marcos_aem -

As per my understanding : 

  • I think that is because while you are trying to recursively loop through the list of child pages , as part of it you already moved a child page and therefore the parent node structure (parent/sub-parent/) would have been automatically created at the target location.
  • Therefore, Later when you are trying to add parent node to the target node tree since the parent node has already been created you are getting ItemExistException.

Possible Solution : 

  • If lets say you want to move multiple child nodes (Child1,Child2) to the new target location you should start creating nodes following Top => Bottom hierarchy only.

 

 

Avatar

Administrator

@Tanika02,good to see the first reply from you to help others. AEM community needs wonderful SMEs like you. Keep it up.



Kautuk Sahni

Avatar

Correct answer by
Community Advisor

@Marcos_aem - 

Hope below solution helps for recursive movement of child nodes from source to the target.

private static void callingChildOc(PageManager pageManager, Page rootPage, Session session) throws WCMException {
    Iterator<Page> childIterators = rootPage.listChildren();
    if (childIterators != null) {
        while (childIterators.hasNext()) {
            Page childPage = childIterators.next();
            String childPath = childPage.getPath();
            String childArchivePath = StringUtils.replace(childPath, "/content/project", "/content/archived");
            if (!session.nodeExists(childArchivePath)) {
                pageManager.move(childPage, childArchivePath, null, false, true, null);
            } else{
            callingChildOc(pageManager, childPage, session);
        }
    }
}