Groovy获取JCR两级父节点属性及parent()方法报错问题求助
Groovy控制台更新标题组件问题修复
场景说明
在Groovy控制台执行脚本,需要根据页面标题值更新页面内的标题组件属性,初始实现代码如下:
getNode('/content/').recurse { resourceNode -> if (resourceNode.hasProperty('sling:resourceType')) { final def resourceType = resourceNode.getProperty('sling:resourceType').string if (resourceType.equals('components/title')) { resourceNode.setProperty('jcr:title', resourceNode.parent().parent().getProperty('jcr:title')) // 问题行 resourceNode.save(); } } }
需求为获取当前节点向上两级父节点的jcr:title属性值,执行时抛出如下异常:
groovy.lang.MissingMethodException: No signature of method: org.apache.jackrabbit.oak.jcr.session.NodeImpl.parent() is applicable for argument types: () values: []
问题根因
- 你调用的
parent()方法不属于JCR标准Node接口,当前拿到的Oak节点实例org.apache.jackrabbit.oak.jcr.session.NodeImpl没有提供无参的parent()方法,JCR标准API中获取父节点的方法为getParent(),方法名不匹配直接触发方法不存在异常。 - 原代码存在两处额外隐患:一是没有对上级节点、目标属性做存在性校验,遇到特殊结构节点会触发空指针或属性不存在异常;二是在循环内反复调用
save()方法,会产生不必要的事务开销,甚至引发版本冲突。
修正后可运行代码
def session = getSession() getNode('/content/').recurse { resourceNode -> if (resourceNode.hasProperty('sling:resourceType')) { def resourceType = resourceNode.getProperty('sling:resourceType').string if (resourceType == 'components/title') { // 逐级获取父节点,做空值校验 def firstLevelParent = resourceNode.getParent() if (!firstLevelParent) return def targetPageNode = firstLevelParent.getParent() // 校验目标页面节点存在、且包含jcr:title属性再赋值 if (targetPageNode?.hasProperty('jcr:title')) { def pageTitle = targetPageNode.getProperty('jcr:title').string resourceNode.setProperty('jcr:title', pageTitle) } } } } // 所有节点处理完成后统一提交会话变更 session.save()
额外注意点
- 脚本执行前建议先打印待修改的节点路径做预跑校验,确认匹配的节点符合预期后再执行写入操作,避免误改内容。
- 如果你的环境中Groovy控制台对Node的递归扩展支持不稳定,可以换成Sling Resource API遍历资源,代码可读性和兼容性更好。
内容的提问来源于stack exchange,提问作者alex
相关产品推荐
相关产品推荐

