category itemnotfoundexception referenced Jahia 7.3 Jahia 8

Category removed, but references still exists

Question

When you remove a Category and not the references (when you continue after the warning that references exists), you could run into ItemNotFoundExceptions because the references are not removed automatically

Cause

Some functions can expect that the category references exists. And so they try to read the category when a reference exists.

Solution

Clean the old references. You have two possibilities, use the JCR Integrity tool or a simple groovy script:

import org.jahia.api.Constants
import org.jahia.tools.patches.LoggerWrapper
import org.jahia.services.content.*
import org.jahia.registries.ServicesRegistry
import javax.jcr.NodeIterator
import javax.jcr.RepositoryException
import javax.jcr.query.Query
import javax.jcr.PathNotFoundException
import javax.jcr.ItemNotFoundException


boolean doSave = false;
boolean doPublish = false;
String nodeType = "jmix:categorized";
String categoryFieldName = "j:defaultCategory";


JCRTemplate.getInstance().doExecuteWithSystemSession(null, Constants.EDIT_WORKSPACE, new JCRCallback() {
    @Override
    Object doInJCR(JCRSessionWrapper session) throws RepositoryException {
        checkNodesForDeletedCategories(session, nodeType, categoryFieldName, doSave, doPublish);
     
        return null
    }
})

public void checkNodesForDeletedCategories(JCRSessionWrapper session, String nodetype, String categoryFieldName, boolean doSave, doPublish) throws RepositoryException {
 
    final String stmt = "SELECT * FROM [" + nodetype + "]";
    final NodeIterator iteratorSites = session.getWorkspace().getQueryManager().createQuery(stmt, Query.JCR_SQL2).execute().getNodes();
    
    while (iteratorSites.hasNext()) {
        JCRNodeWrapper node = (JCRNodeWrapper)iteratorSites.nextNode();
        int problem = 0;
  if (node.hasProperty(categoryFieldName)) {
            for (JCRValueWrapper value : node.getProperty(categoryFieldName).getValues()) {
             if (value.getNode() == null) {
             log.info(node.getPath() + " has an not existant category assigned: " + value.toString());
             problem ++;
             }
            }
            if (problem > 0 && doSave) {
    Value[] values = new Value[node.getProperty(categoryFieldName).getValues().length - problem];
    int i = 0;
    for (JCRValueWrapper value : node.getProperty(categoryFieldName).getValues()) {
     if (value.getNode() != null) {
      values[i] = value;
      i++;
     }
    }
    node.getProperty(categoryFieldName).setValue(values);
    node.saveSession();
    log.info("Node " + node.getPath() + " corrected!");
    if (doPublish) {
     if (node.hasProperty("j:published")) {
      JCRPublicationService publicationService = ServicesRegistry.getInstance().getJCRPublicationService();
      List<String> uuids = new ArrayList<>();
      uuids.add(node.getIdentifier());
      publicationService.publish(uuids, "default", "live", null);
      log.info("Node " + node.getPath() + " published!");
     } else {
      log.info("!!!Node " + node.getPath() + " NOT publised, because it was never published (no publication flag exists)!!!");
     }
    }  
   }
  } else {
      log.info("!! Node " + node.getPath() + " is " + nodetype + " but has no " + categoryFieldName);
  }
    }
 
}