Vous consultez actuellement l'aide de la version:

This section describes how to extend the Query Builder by implementing a custom predicate evaluator.


The Query Builder offers an easy way of querying the content repository. CQ ships with a set of predicate evaluators that helps you deal with your data.

However you might want to simplify your queries by implementing a custom predicate evaluator that hides some complexity and ensures a better semantic.

A custom predicate could also perform other things not directly possible with XPath, for example:

  • looking up some data from some service
  • custom filtering based on calculation

Remarque :

Performance issues must be considered when implementing a custom predicate.

Remarque :

You can find examples of queries in the Query Builder section.

Code on GitHub

You can find the code of this page on GitHub

Predicate Evaluator in Detail

A predicate evaluator handles the evaluation of certain predicates, which are the defining constraints of a query.

It maps a higher-level search constraint (such as "width > 200") to a specific JCR query that fits the actual content model (e.g. metadata/@width > 200). Or it can manually filter nodes and check their constraints.

Remarque :

For more information about the PredicateEvaluator and the com.day.cq.search package see the Java documentation.

Implementing a Custom Predicate Evaluator for Replication Metadata

As an example this section describes how to create a custom predicate evaluator that helps data based on the replication metadata:

  • cq:lastReplicated that stores the date of the last replication action
  • cq:lastReplicatedBy that stores the id of the user who triggered the last replication action
  • cq:lastReplicationAction that stores the last replication action (e.g. Activation, Deactivation)

Querying Replication Metadata with Default Predicate Evaluators

The following query fetches the list of nodes in /content branch that have been activated by admin since the beginning of the year.





This query is valid but hard to read and does not highlight the relationship between the three replication properties. Implementing a custom predicate evaluator will reduce the complexity and improve the semantic of this query.


The goal of the ReplicationPredicateEvaluator is to support the above query using the following syntax.



Grouping replication metadata predicates with a custom predicate evaluator helps to create a meaningful query.

Updating Maven Dependencies

Remarque :

The set up of new AEM projects using maven is documented by How to Build AEM Projects using Apache Maven.

First you need to update the Maven dependencies of your project. The PredicateEvaluator is part of the cq-search artifact so it needs to be added to your Maven pom file.

Remarque :

The scope of the cq-search dependency is set to provided because cq-search will be provided by the OSGi container.


The following snippet shows the differences, in unified diff format

@@ -120,6 +120,12 @@
+            <groupid>com.day.cq</groupid>
+            <artifactid>cq-search</artifactid>
+            <version>5.6.4</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>

Writing The ReplicationPredicateEvaluator

The cq-search project contains the AbstractPredicateEvaluator abstract class. This can be extended with a few steps to implement your own custom predicate evaluator(PredicateEvaluator).

Remarque :

The following procedure explains how to build an Xpath expression to filter data. Another option would be to implement the includes method that selects data on a row basis. See the Java documentation for more information.

  1. Create a new Java class which extends com.day.cq.search.eval.AbstractPredicateEvaluator

  2. Annotate your class with a @Component like the following


    The following snippet shows the differences, in unified diff format

    @@ -19,8 +19,11 @@
     package com.adobe.aem.docs.search;
    +import org.apache.felix.scr.annotations.Component;
     import com.day.cq.search.eval.AbstractPredicateEvaluator;
    +@Component(metatype = false, factory = "com.day.cq.search.eval.PredicateEvaluator/repli")
     public class ReplicationPredicateEvaluator extends AbstractPredicateEvaluator {

    Remarque :

    The factory must be a unique string starting with com.day.cq.search.eval.PredicateEvaluator/ and ending with the name of your custom PredicateEvaluator.

    Remarque :

    The name of the PredicateEvaluator is the predicate name, which is used when building queries.

  3. Override:

    public String getXPathExpression(Predicate predicate, EvaluationContext context)

    In the override method you build a Xpath expression based on the Predicate given in argument.

Example of a Custom Predicate Evalutor for Replication Metadata

The complete implementation of this PredicateEvaluator might be similar to the following class.

src/main/java/com/adobe/aem/docs/search/ReplicationPredicateEvaluator.java Open on GitHub

 * #%L
 * aem-docs-custom-predicate-evaluator
 * %%
 * Copyright (C) 2013 Adobe Research
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *      http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
package com.adobe.aem.docs.search;
import org.apache.felix.scr.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.day.cq.search.Predicate;
import com.day.cq.search.eval.AbstractPredicateEvaluator;
import com.day.cq.search.eval.EvaluationContext;
@Component(metatype = false, factory = "com.day.cq.search.eval.PredicateEvaluator/repli")
public class ReplicationPredicateEvaluator extends AbstractPredicateEvaluator {
    static final String PE_NAME = "replic";
    static final String PN_LAST_REPLICATED_BY = "cq:lastReplicatedBy";
    static final String PN_LAST_REPLICATED = "cq:lastReplicated";
    static final String PN_LAST_REPLICATED_ACTION = "cq:lastReplicationAction";
    static final String PREDICATE_BY = "by";
    static final String PREDICATE_SINCE = "since";
    static final String PREDICATE_SINCE_OP = " >= ";
    static final String PREDICATE_ACTION = "action";
    Logger log = LoggerFactory.getLogger(getClass());
     * Returns a XPath expression filtering by replication metadata.
     * @see com.day.cq.search.eval.AbstractPredicateEvaluator#getXPathExpression(com.day.cq.search.Predicate,
     *      com.day.cq.search.eval.EvaluationContext)
    public String getXPathExpression(Predicate predicate,
            EvaluationContext context) {
        log.debug("predicate {}", predicate);
        String date = predicate.get(PREDICATE_SINCE);
        String user = predicate.get(PREDICATE_BY);
        String action = predicate.get(PREDICATE_ACTION);
        StringBuilder sb = new StringBuilder();
        if (date != null) {
        if (user != null) {
        if (action != null) {
        String xpath = sb.toString();
        log.debug("xpath **{}**", xpath);
        return xpath;
     * Add an and operator if the builder is not empty.
     * @param sb a {@link StringBuilder} containing the query under construction
    private void addAndOperator(StringBuilder sb) {
        if (sb.length() != 0) {
            sb.append(" and ");