[MAGNOLIA-6375] NoSuchNodeTypeException when unregistering dependent mgnl:content nodes and then trying to remove mgnl:content Created: 15/Sep/15  Updated: 15/Apr/16  Resolved: 12/Oct/15

Status: Closed
Project: Magnolia
Component/s: core
Affects Version/s: 5.3.11, 5.4.2
Fix Version/s: 5.3.12, 5.4.3

Type: Bug Priority: Major
Reporter: Karel de Witte Assignee: Espen Jervidalo
Resolution: Fixed Votes: 0
Labels: support
Remaining Estimate: 0d
Time Spent: 2d 1h 20m
Original Estimate: 1d

Attachments: Text File MAGNOLIA-6375.patch    
Issue Links:
dependency
Template:
Acceptance criteria:
Empty
Task DoD:
[ ]* Doc/release notes changes? Comment present?
[ ]* Downstream builds green?
[ ]* Solution information and context easily available?
[ ]* Tests
[ ]* FixVersion filled and not yet released
[ ]  Architecture Decision Record (ADR)
Bug DoR:
[ ]* Steps to reproduce, expected, and actual results filled
[ ]* Affected version filled
Date of First Response:
Sprint: Saigon 13, Basel 16
Story Points: 5

 Description   

Mgnl:content dependent nodetypes are unregistered and then mgnl:content node is unregistered causing: required node type does not exist
javax.jcr.nodetype.NoSuchNodeTypeException:

{http://www.magnolia.info/jcr/mgnl}

content in info.magnolia.setup.for5_0.AbstractNodeTypeRegistrationTask#registerNodeTypes. This might be due to the fact that jcr removes mgnl:content implicitly after all dependent nodes are unregistered.
Remove supertype of dependent nodes from the list of nodes to be un-registered.



 Comments   
Comment by Rico Jansen [ 15/Sep/15 ]

Well what I saw was mgnl:content being unregistered including its dependent types. And that during the registration a nodetype is registered that depends on mgnl:content.
If you look in the stacktrace you see that it happens in the registration fase:

org.apache.jackrabbit.spi.commons.nodetype.AbstractNodeTypeManager.createNodeTypeTemplate(AbstractNodeTypeManager.java:92)
	at info.magnolia.setup.for5_0.AbstractNodeTypeRegistrationTask.registerNodeTypes(AbstractNodeTypeRegistrationTask.java:158)
	at info.magnolia.setup.for5_0.AbstractNodeTypeRegistrationTask.doExecute(AbstractNodeTypeRegistrationTask.java:103)

That's why during the debugging I wanted to see the order of the list to be registered again in variable nodeTypeToUnregister.values() in info.magnolia.setup.for5_0.AbstractNodeTypeRegistrationTask#registerNodeTypes#145

If that order is not in dependent order (root at the beginning) you get the exception. We saw mgnl:person registered as the first one, since
that one depends on mgnl:content it will cause an error.

This will also happen in case you have a deeper hierarchy.
For instance mgnl:content <- mgnl:vehicle <- mgnl:car

If in this case the list turns out to be mgnl:content, mgnl:car, mgnl:vehicle you get the same error. Only for mgnl:vehicle instead of mgnl:content
Since it is a hashmap, the order of values() can not be depended upon. So there needs to be an dependent ordered list to register.
Not just the unregistered types hashmap.

Comment by Rico Jansen [ 16/Sep/15 ]

I have made a patch that fixes the issue. In doing so I discovered that there is actually another issue.

Generating a NodeTypeTemplate requires the supertypes to be registered.

Since several dependent subtypes depend on mgnl:content being registered this fails when you do it in one go.
So the solution is to re-register all nodetypes one by one creating a nodetypetemplate inside the loop.

You still have to make sure you do it in the depency order otherwise it will still fail.

The fact that it still works afterwards is because the exception clause registered mgnl:content with the original definition and then tried again with the remaining dependents. Which succeeds in this case. In more complex cases (with deeper trees) this would also fail.

Comment by Sang Ngo Huu [ 05/Oct/15 ]

HI rico.jansen, Thanks for patch file, the patch is fine.

I tried to reproduce this issue by following your case for providing unitest, but I cannot. Could you give me more details?

Thanks,

Comment by Rico Jansen [ 05/Oct/15 ]

I understand that reproducing this is difficult. You need sufficient dependencies on the mgnl:content nodetype to make this happen.
This has to do with the fact that the order of the values() call needs to be 'wrong' to make it fail, the more dependencies the more likely it is to happen.

Also the catch 'fixes' the issue for the next run, so you can only do it on the first real reregistration.

My suggestion would be to make a whole heap of types that depend on mgnl:content and try it that way.

Comment by Sang Ngo Huu [ 07/Oct/15 ]

Hi rico.jansen, could you please provide me the error stack trace?

Comment by Rico Jansen [ 07/Oct/15 ]
INFO   info.magnolia.setup.for5_0.AbstractNodeTypeRegistrationTask 04.09.2015 11:54:59 -- In order to register 'mgnl:content', the following depending node types have to be unregistered first: [mgnl:person, mgnl:role, mgnl:user, mgnl:group, mgnl:systemMessage, mgnl:rssAggregator, mgnl:page, mgnl:category, mgnl:tip, mgnl:content].
ERROR  org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl 04.09.2015 11:55:06 -- required node type does not exist
javax.jcr.nodetype.NoSuchNodeTypeException: {http://www.magnolia.info/jcr/mgnl}content
	at org.apache.jackrabbit.core.nodetype.NodeTypeRegistry.getEffectiveNodeType(NodeTypeRegistry.java:1037)
	at org.apache.jackrabbit.core.nodetype.NodeTypeRegistry.getEffectiveNodeType(NodeTypeRegistry.java:472)
	at org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl.getNodeType(NodeTypeManagerImpl.java:186)
	at org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl.getNodeType(NodeTypeManagerImpl.java:73)
	at org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl.getRequiredPrimaryTypes(NodeDefinitionImpl.java:139)
	at org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionTemplateImpl.<init>(NodeDefinitionTemplateImpl.java:68)
	at org.apache.jackrabbit.spi.commons.nodetype.NodeTypeTemplateImpl.<init>(NodeTypeTemplateImpl.java:99)
	at org.apache.jackrabbit.spi.commons.nodetype.AbstractNodeTypeManager.createNodeTypeTemplate(AbstractNodeTypeManager.java:92)
	at info.magnolia.setup.for5_0.AbstractNodeTypeRegistrationTask.registerNodeTypes(AbstractNodeTypeRegistrationTask.java:158)
	at info.magnolia.setup.for5_0.AbstractNodeTypeRegistrationTask.doExecute(AbstractNodeTypeRegistrationTask.java:103)
	at info.magnolia.module.delta.AbstractRepositoryTask.execute(AbstractRepositoryTask.java:57)
	at info.magnolia.module.ModuleManagerImpl.applyDeltas(ModuleManagerImpl.java:511)
	at info.magnolia.module.ModuleManagerImpl.installOrUpdateModule(ModuleManagerImpl.java:493)
	at info.magnolia.module.ModuleManagerImpl$1.doExec(ModuleManagerImpl.java:274)
	at info.magnolia.context.MgnlContext$VoidOp.exec(MgnlContext.java:421)
	at info.magnolia.context.MgnlContext$VoidOp.exec(MgnlContext.java:418)
	at info.magnolia.context.MgnlContext.doInSystemContext(MgnlContext.java:392)
	at info.magnolia.module.ModuleManagerImpl.performInstallOrUpdate(ModuleManagerImpl.java:268)
	at info.magnolia.module.ui.ModuleManagerNullUI.onStartup(ModuleManagerNullUI.java:66)
	at info.magnolia.cms.beans.config.ConfigLoader.load(ConfigLoader.java:148)
	at info.magnolia.init.MagnoliaServletContextListener$1.doExec(MagnoliaServletContextListener.java:250)
	at info.magnolia.context.MgnlContext$VoidOp.exec(MgnlContext.java:421)
	at info.magnolia.context.MgnlContext$VoidOp.exec(MgnlContext.java:418)
	at info.magnolia.context.MgnlContext.doInSystemContext(MgnlContext.java:392)
	at info.magnolia.init.MagnoliaServletContextListener.startServer(MagnoliaServletContextListener.java:247)
	at info.magnolia.init.MagnoliaServletContextListener.contextInitialized(MagnoliaServletContextListener.java:173)
	at info.magnolia.init.MagnoliaServletContextListener.contextInitialized(MagnoliaServletContextListener.java:127)
	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4973)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5467)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:632)
	at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1083)
	at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1880)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
INFO   info.magnolia.setup.for5_0.AbstractNodeTypeRegistrationTask 04.09.2015 11:55:06 -- Registering the following 'mgnl:content' node type. Reregistered the following dependency: [mgnl:person, mgnl:role, mgnl:user, mgnl:group, mgnl:systemMessage, mgnl:rssAggregator, mgnl:page, mgnl:category, mgnl:tip, mgnl:content]
INFO   info.magnolia.setup.for5_0.AbstractNodeTypeRegistrationTask 04.09.2015 11:55:07 -- In order to register 'mgnl:contentNode', the following depending node types have to be unregistered first: [mgnl:media, mgnl:area, mgnl:component, mgnl:task, mgnl:playlistentry, mgnl:playlist, mgnl:resolutions, mgnl:contentNode].
INFO   info.magnolia.setup.for5_0.AbstractNodeTypeRegistrationTask 04.09.2015 11:55:07 -- Registering the following 'mgnl:contentNode' node type. Reregistered the following dependency: [mgnl:media, mgnl:area, mgnl:component, mgnl:task, mgnl:playlistentry, mgnl:playlist, mgnl:resolutions, mgnl:contentNode]
INFO   info.magnolia.setup.for5_0.AbstractNodeTypeRegistrationTask 04.09.2015 11:55:07 -- In order to register 'mgnl:folder', the following depending node types have to be unregistered first: [mgnl:favoriteGroup, mgnl:folder].
INFO   info.magnolia.setup.for5_0.AbstractNodeTypeRegistrationTask 04.09.2015 11:55:07 -- Registering the following 'mgnl:folder' node type. Reregistered the following dependency: [mgnl:favoriteGroup, mgnl:folder]
INFO   info.magnolia.setup.for5_0.AbstractNodeTypeRegistrationTask 04.09.2015 11:55:07 -- In order to register 'mgnl:resource', the following depending node types have to be unregistered first: [mgnl:resource].
INFO   info.magnolia.setup.for5_0.AbstractNodeTypeRegistrationTask 04.09.2015 11:55:07 -- Registering the following 'mgnl:resource' node type. Reregistered the following dependency: [mgnl:resource]
INFO   info.magnolia.setup.for5_0.AbstractNodeTypeRegistrationTask 04.09.2015 11:55:07 -- No NodeType defined to unregister for the following workspace 'config'
INFO   info.magnolia.setup.for5_0.AbstractNodeTypeRegistrationTask 04.09.2015 11:55:07 -- No NodeType defined to register for the following workspace 'config'
INFO   info.magnolia.setup.for5_0.AbstractNodeTypeRegistrationTask 04.09.2015 11:55:07 -- No NodeType defined to unregister for the following workspace 'config'
Comment by Sang Ngo Huu [ 12/Oct/15 ]

Hi rico.jansen,

Thanks for your infomation, I can reproduce the issue now. It's about the mis-order in Map when updating new value for a key

The issue will happen when registering nodeTypes such as mngl:content and mgnl:rssAggregator, it all will be put into Map with its added orders

All nodeTypes and dependencies are unregistered first, then registered again. So, the order is important, Map.keySet() cannot keep the order. mgnl:rssAggregator is moved on top of mgnl:content that is not registered yet, and NoSuchNodeTypeException will throw

For fixing it, I have applied your patch, and provided unitest for it

Thanks again and happy bug fixing

mgnl:rssAggregator for your reference:

<nodeType hasOrderableChildNodes="true" isAbstract="false" isMixin="false" isQueryable="true" name="mgnl:rssAggregator" primaryItemName="">
        <supertypes>
            <supertype>mgnl:content</supertype>
        </supertypes>
        <childNodeDefinition autoCreated="false" defaultPrimaryType="mgnl:content" mandatory="false" name="feeds" onParentVersion="COPY" protected="false" sameNameSiblings="false">
            <requiredPrimaryTypes>
                <requiredPrimaryType>mgnl:content</requiredPrimaryType>
            </requiredPrimaryTypes>
        </childNodeDefinition>
    </nodeType>
Comment by Rico Jansen [ 12/Oct/15 ]

Good to hear that you have been able to reproduce and solve it.
I'll await the release with the fix before removing the fix in our codebase.

Comment by Espen Jervidalo [ 22/Oct/15 ]

see pull request

Generated at Mon Feb 12 04:13:56 CET 2024 using Jira 9.4.2#940002-sha1:46d1a51de284217efdcb32434eab47a99af2938b.