Skip to main content
Developer Jahia 8.2

How do I make two mixins mutually exclusive, and what does removeMixin do if the node does not have it?

Question

How do I make two mixins mutually exclusive, and what does removeMixin do if the node does not have it?

Answer

You cannot declare it in the CND

There is no attribute for it. JCR lets a node carry any combination of mixins, and nothing in Jahia's CND grammar expresses "these two are incompatible". Verified on 8.2.3.2 - applying two unrelated mixins to one node succeeds with no complaint:

both mixins applied : OK -> [jmix:keywords, mix:title]

Do not reach for validator. The CND grammar still accepts validator=<something>, and the reader logs

Warning : validator is not supported anymore

and ignores it. Your constraint is not applied, and the only sign is one warning line at startup. This is worse than a syntax error, because the definition deploys and looks fine.

Enforce it with a rule

Jahia's rules DSL has both halves of what you need - a condition for "this mixin was just added" and a consequence that removes another:

rule "mymix:A and mymix:B are mutually exclusive"
    when
        The type mymix:A has been assigned to a node
            - the node has the type mymix:B
    then
        Remove the type mymix:B
end

Measured on 8.2.3.2: a node carrying mix:title had jmix:keywords added, and the rule stripped the first.

before: [mix:title]
after : [jmix:keywords]

The guard on the second line is not optional

Write the rule without - the node has the type mymix:B and it still works, but it throws:

javax.jcr.nodetype.NoSuchNodeTypeException: Mixin mix:title not included in node
/sites/systemsite/contents/mixtest2

The rule is loaded by more than one listener, so it runs more than once per change. The first run removes the mixin; the second tries to remove it again and fails, because removing a mixin a node does not have is an error (see below).

With the guard, the same test produced one clean firing and no exception. Add it.

For symmetry you normally want the mirrored rule as well, so that adding B strips A. Two rules, each guarded.

removeMixin on a node that does not have the mixin

It throws. Measured:

javax.jcr.nodetype.NoSuchNodeTypeException: Mixin jmix:cache not included in node
/sites/systemsite/contents/mixtest

So check first - node.isNodeType("jmix:cache") - or guard in the rule as above.

By contrast, addMixin twice is harmless: the second call is a no-op and raises nothing. The two are not symmetric, which is the trap.

removeMixin also deletes child nodes

Worth knowing before you make removal automatic: removing a mixin also removes any child nodes that mixin defined. If your mixin contributes a child node rather than just properties, a mutual-exclusion rule that strips it is destroying content, not just clearing a flag.

Decide deliberately whether exclusivity should remove the other mixin or simply refuse the change.

This is the data layer only

The above governs what is stored. Whether the editing UI still offers the other option is a separate concern, handled in Content Editor rather than in the CND or in rules, and is not covered here.


This article was drafted with AI assistance, then reviewed and curated by Jahia Customer Support engineers before publication.