Expand my Community achievements bar.

Introducing Adobe LLM Optimizer: Own your brand’s presence in AI-Powered search and discovery

Implement "replace" mode for a nested node in filter.xml

Avatar

Level 2

My filter.xml under ui.content looks like this -

<workspaceFilter version="1.0">
<filter root="/conf/myproject" mode="merge"/>
</workspaceFilter>

I have a subfolder under /conf/myproject containing some queries that I want to have mode="replace".

So I excluded that path from my filter.xml and added it as a separate filter as follows - 

<workspaceFilter version="1.0">
<filter root="/conf/myproject" mode="merge">
<exclude pattern="/conf/myproject/settings/graphql/persistentQueries(/.*)?"/>
</filter
<filter root="/conf/myproject/settings/graphql/persistentQueries" mode="replace"/>
</workspaceFilter>

When I deploy using mvn clean install, I see old node properties for queries under /conf/myproject/settings/graphql/persistentQueries. The replace functionality doesn't seem to be working correctly.
What am I doing wrong? 
Please note that when I place <filter root="/conf/myproject/settings/graphql/persistentQueries" mode="replace"/> at the very top of the file, everything seems to be working as expected.

Topics

Topics help categorize Community content and increase your ability to discover relevant content.

5 Replies

Avatar

Level 2

You're encountering a known behavior of Content Package Plugin's filter order evaluation during deployment in AEM.

Root Cause

The order of <filter> entries in filter.xml matters, especially when using different mode values like merge and replace.

  • AEM processes filters top to bottom.

  • If a merge filter appears before a replace filter (and covers the same or a parent path), the merge behavior will take precedence, and the replace will not override as expected — even with the <exclude>.

In your case, even though you've excluded the persistentQueries path in the merge filter, AEM still processes the parent node first, and the merge mode wins unless replace is declared earlier.


Correct Fix

Move the replace filter to the top of your filter.xml, like so:

<workspaceFilter version="1.0">
    <filter root="/conf/myproject/settings/graphql/persistentQueries" mode="replace"/>
    <filter root="/conf/myproject" mode="merge">
        <exclude pattern="/conf/myproject/settings/graphql/persistentQueries(/.*)?"/>
    </filter>
</workspaceFilter>

This ensures:

  • The replace operation happens before any merging.

  • The persistent queries node is fully replaced, removing old properties/nodes.

 

Avatar

Level 2

Thank you. So as per your code snippet above, considering I move the "replace" rule at the very top, do I still need to use an "exclude" rule?
or can I just use this?

<workspaceFilter version="1.0">
    <filter root="/conf/myproject/settings/graphql/persistentQueries" mode="replace"/>
    <filter root="/conf/myproject" mode="merge"/>
</workspaceFilter>



Avatar

Level 2

Yes, if you place the replace filter at the top, you don’t need the <exclude>.

AEM processes filters in order, so the replace on /persistentQueries runs first and overrides everything there. The following merge on /conf/myproject won’t reprocess that path.

Avatar

Administrator

Hi @ArchitAr2,

Did the shared solution help you out? If yes, kindly consider marking the answer as ‘correct’.

If you’re still facing any challenges, please feel free to continue the conversation here. We’re happy to support further.

 

Avatar

Community Advisor

Hi @ArchitAr2 ,

The correct way is to put the replace filter at the top of the file. This ensures that AEM applies the replacement before processing any parent-level merge.

filter.xml:

<workspaceFilter version="1.0">
    <filter root="/conf/myproject/settings/graphql/persistentQueries" mode="replace"/>
    <filter root="/conf/myproject" mode="merge"/>
</workspaceFilter>

With this setup:

  - The persistentQueries node is fully replaced.

  - No need for any <exclude> rule.

  - Everything else under /conf/myproject is merged as usual.


Regards,
Amit