Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

False positive: OakConstraint0025: /apps/acs-commons[[nt:folder]]: Unexpected child node install found in a new node #92

Open
kwin opened this issue Mar 26, 2022 · 8 comments

Comments

@kwin
Copy link

kwin commented Mar 26, 2022

In Adobe-Consulting-Services/acs-aem-commons@2d17ee5#diff-d8b13fb5ab2dc98ee98e3347a250f6517268c27b716832b47e3d76969f6a3654R151 I had to disable oakpal-maven-plugin:scan as otherwise the following build exception was emitted:

[ERROR] Error during install.
javax.jcr.nodetype.ConstraintViolationException: OakConstraint0025: /apps/acs-commons[[nt:folder]]: Unexpected child node install found in a new node
    at org.apache.jackrabbit.oak.api.CommitFailedException.asRepositoryException (CommitFailedException.java:226)
    at org.apache.jackrabbit.oak.api.CommitFailedException.asRepositoryException (CommitFailedException.java:213)
    at org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.newRepositoryException (SessionDelegate.java:669)
    at org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.save (SessionDelegate.java:495)
    at org.apache.jackrabbit.oak.jcr.session.SessionImpl$8.performVoid (SessionImpl.java:424)
    at org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.performVoid (SessionDelegate.java:273)
    at org.apache.jackrabbit.oak.jcr.session.SessionImpl.save (SessionImpl.java:421)
    at org.apache.jackrabbit.vault.fs.io.AutoSave.save (AutoSave.java:177)
    at org.apache.jackrabbit.vault.fs.io.Importer.commit (Importer.java:815)
    at org.apache.jackrabbit.vault.fs.io.Importer.commit (Importer.java:839)
    at org.apache.jackrabbit.vault.fs.io.Importer.commit (Importer.java:839)
    at org.apache.jackrabbit.vault.fs.io.Importer.commit (Importer.java:839)
    at org.apache.jackrabbit.vault.fs.io.Importer.commit (Importer.java:839)
    at org.apache.jackrabbit.vault.fs.io.Importer.commit (Importer.java:839)
    at org.apache.jackrabbit.vault.fs.io.Importer.commit (Importer.java:839)
    at org.apache.jackrabbit.vault.fs.io.Importer.commit (Importer.java:839)
    at org.apache.jackrabbit.vault.fs.io.Importer.run (Importer.java:440)
    at org.apache.jackrabbit.vault.packaging.impl.ZipVaultPackage.extract (ZipVaultPackage.java:232)
    at org.apache.jackrabbit.vault.packaging.impl.JcrPackageImpl.extract (JcrPackageImpl.java:400)
    at org.apache.jackrabbit.vault.packaging.impl.JcrPackageImpl.extract (JcrPackageImpl.java:359)
    at org.apache.jackrabbit.vault.packaging.impl.JcrPackageImpl.extract (JcrPackageImpl.java:345)
    at net.adamcin.oakpal.core.OakMachine.processPackage (OakMachine.java:817)
    at net.adamcin.oakpal.core.OakMachine.internalProcessSubpackage (OakMachine.java:918)
    at net.adamcin.oakpal.core.OakMachine.processSubpackage (OakMachine.java:935)
    at net.adamcin.oakpal.core.OakMachine.processPackage (OakMachine.java:831)
    at net.adamcin.oakpal.core.OakMachine.processUploadedPackage (OakMachine.java:966)
    at net.adamcin.oakpal.core.OakMachine.processPackageFile (OakMachine.java:1044)
    at net.adamcin.oakpal.core.OakMachine.scanPackages (OakMachine.java:696)
    at net.adamcin.oakpal.maven.mojo.AbstractITestWithPlanMojo.performScan (AbstractITestWithPlanMojo.java:477)
    at net.adamcin.oakpal.maven.mojo.ScanArtifactMojo.executeGuardedIntegrationTest (ScanArtifactMojo.java:65)
    at net.adamcin.oakpal.maven.mojo.AbstractITestMojo.execute (AbstractITestMojo.java:146)
    at net.adamcin.oakpal.maven.mojo.ScanArtifactMojo.execute (ScanArtifactMojo.java:37)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:301)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:211)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:165)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:157)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:121)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:127)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:294)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:960)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:293)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:196)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:566)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: org.apache.jackrabbit.oak.api.CommitFailedException: OakConstraint0025: /apps/acs-commons[[nt:folder]]: Unexpected child node install found in a new node
    at org.apache.jackrabbit.oak.plugins.nodetype.TypeEditor$1.onConstraintViolation (TypeEditor.java:109)
    at org.apache.jackrabbit.oak.plugins.nodetype.TypeEditor.constraintViolation (TypeEditor.java:234)
    at org.apache.jackrabbit.oak.plugins.nodetype.TypeEditor.checkNodeTypeConstraints (TypeEditor.java:487)
    at org.apache.jackrabbit.oak.plugins.nodetype.TypeEditor.enter (TypeEditor.java:276)
    at org.apache.jackrabbit.oak.spi.commit.VisibleEditor.enter (VisibleEditor.java:53)
    at org.apache.jackrabbit.oak.spi.commit.CompositeEditor.enter (CompositeEditor.java:65)
    at org.apache.jackrabbit.oak.spi.commit.EditorDiff.childNodeChanged (EditorDiff.java:144)
    at org.apache.jackrabbit.oak.plugins.memory.MemoryNodeState.compareAgainstBaseState (MemoryNodeState.java:161)
    at org.apache.jackrabbit.oak.spi.commit.EditorDiff.childNodeChanged (EditorDiff.java:147)
    at org.apache.jackrabbit.oak.plugins.memory.MemoryNodeState.compareAgainstBaseState (MemoryNodeState.java:161)
    at org.apache.jackrabbit.oak.spi.commit.EditorDiff.process (EditorDiff.java:51)
    at org.apache.jackrabbit.oak.spi.commit.EditorHook.processCommit (EditorHook.java:54)
    at org.apache.jackrabbit.oak.spi.commit.CompositeHook.processCommit (CompositeHook.java:60)
    at org.apache.jackrabbit.oak.spi.commit.CompositeHook.processCommit (CompositeHook.java:60)
    at org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore$MemoryNodeStoreBranch.merge (MemoryNodeStore.java:294)
    at org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore.merge (MemoryNodeStore.java:133)
    at org.apache.jackrabbit.oak.core.MutableRoot.commit (MutableRoot.java:251)
    at org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.commit (SessionDelegate.java:346)
    at org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.save (SessionDelegate.java:493)
    at org.apache.jackrabbit.oak.jcr.session.SessionImpl$8.performVoid (SessionImpl.java:424)
    at org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.performVoid (SessionDelegate.java:273)
    at org.apache.jackrabbit.oak.jcr.session.SessionImpl.save (SessionImpl.java:421)
    at org.apache.jackrabbit.vault.fs.io.AutoSave.save (AutoSave.java:177)
    at org.apache.jackrabbit.vault.fs.io.Importer.commit (Importer.java:815)
    at org.apache.jackrabbit.vault.fs.io.Importer.commit (Importer.java:839)
    at org.apache.jackrabbit.vault.fs.io.Importer.commit (Importer.java:839)
    at org.apache.jackrabbit.vault.fs.io.Importer.commit (Importer.java:839)
    at org.apache.jackrabbit.vault.fs.io.Importer.commit (Importer.java:839)
    at org.apache.jackrabbit.vault.fs.io.Importer.commit (Importer.java:839)
    at org.apache.jackrabbit.vault.fs.io.Importer.commit (Importer.java:839)
    at org.apache.jackrabbit.vault.fs.io.Importer.commit (Importer.java:839)
    at org.apache.jackrabbit.vault.fs.io.Importer.run (Importer.java:440)
    at org.apache.jackrabbit.vault.packaging.impl.ZipVaultPackage.extract (ZipVaultPackage.java:232)
    at org.apache.jackrabbit.vault.packaging.impl.JcrPackageImpl.extract (JcrPackageImpl.java:400)
    at org.apache.jackrabbit.vault.packaging.impl.JcrPackageImpl.extract (JcrPackageImpl.java:359)
    at org.apache.jackrabbit.vault.packaging.impl.JcrPackageImpl.extract (JcrPackageImpl.java:345)
    at net.adamcin.oakpal.core.OakMachine.processPackage (OakMachine.java:817)
    at net.adamcin.oakpal.core.OakMachine.internalProcessSubpackage (OakMachine.java:918)
    at net.adamcin.oakpal.core.OakMachine.processSubpackage (OakMachine.java:935)
    at net.adamcin.oakpal.core.OakMachine.processPackage (OakMachine.java:831)
    at net.adamcin.oakpal.core.OakMachine.processUploadedPackage (OakMachine.java:966)
    at net.adamcin.oakpal.core.OakMachine.processPackageFile (OakMachine.java:1044)
    at net.adamcin.oakpal.core.OakMachine.scanPackages (OakMachine.java:696)
    at net.adamcin.oakpal.maven.mojo.AbstractITestWithPlanMojo.performScan (AbstractITestWithPlanMojo.java:477)
    at net.adamcin.oakpal.maven.mojo.ScanArtifactMojo.executeGuardedIntegrationTest (ScanArtifactMojo.java:65)
    at net.adamcin.oakpal.maven.mojo.AbstractITestMojo.execute (AbstractITestMojo.java:146)
    at net.adamcin.oakpal.maven.mojo.ScanArtifactMojo.execute (ScanArtifactMojo.java:37)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:301)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:211)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:165)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:157)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:121)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:127)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:294)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:960)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:293)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:196)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:566)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)

The actual installation in a repository works fine and both the install node as well as the parent /apps/acs-aem-commons node are of type nt:folder which is perfectly valid.

@adamcin
Copy link
Owner

adamcin commented Mar 27, 2022

Agreed. Nothing about that install node looks unexpected to me. I'll have to look into to the TypeEditor to see how that constraint is evaluated. Can you paste the log lines for the scan goal related to Oak repository initialization? I wonder if the CND for nt:folder is somehow being redefined at runtime to not extend nt:hierarchyNode.

@adamcin
Copy link
Owner

adamcin commented Mar 27, 2022

@kwin I'm not going to be able to run any builds myself until April 4 at the earliest (I'm between laptops until then). Do you know if there is a possibility that AutoSave can commit between adding a child node and setting its primary type when it is a folder that doesn't contain a .content.xml file?

@kwin
Copy link
Author

kwin commented Apr 7, 2022

I don't think that the primary type is modified but is set to nt:folder during creation already by FileVault.

@adamcin
Copy link
Owner

adamcin commented Apr 10, 2022

Reproduced on java 11 with relevant oakpal execution log output:

[INFO] --- oakpal-maven-plugin:2.2.3-SNAPSHOT:scan-many (oakpal-scan-min) @ acs-aem-commons-content ---
[INFO] Found a new index node [reference]. Reindexing is requested
[INFO] Reindexing will be performed for following indexes: [/oak:index/uuid, /oak:index/reference, /oak:index/nodetype]
[INFO] Indexing report
    - /oak:index/uuid*(0)
    - /oak:index/reference*(0)
    - /oak:index/nodetype*(1258)

[INFO] Reindexing completed
[INFO] Reindexing will be performed for following indexes: [/oak:index/principalName, /oak:index/authorizableId, /oak:index/acPrincipalName, /oak:index/repMembers]
[INFO] Indexing report
    - /oak:index/principalName*(2)
    - /oak:index/authorizableId*(2)
    - /oak:index/acPrincipalName*(0)
    - /oak:index/repMembers*(0)

[INFO] Reindexing completed
[INFO] Node type change for vlt:PackageDefinition appears to be trivial
[INFO] Node type changes: [vlt:PackageDefinition] appear to be trivial, repository will not be scanned
[ERROR] error during auto save - retrying after refresh...
[ERROR] Error while committing /apps/acs-commons/console/createpagewizard: javax.jcr.nodetype.ConstraintViolationException: OakConstraint0025: /apps/acs-commons[[nt:folder]]: Unexpected child node install found in a new node
[ERROR] Error while committing /apps/acs-commons/console: javax.jcr.nodetype.ConstraintViolationException: OakConstraint0025: /apps/acs-commons[[nt:folder]]: Unexpected child node install found in a new node
[ERROR] Error while committing /apps/acs-commons: javax.jcr.nodetype.ConstraintViolationException: OakConstraint0025: /apps/acs-commons[[nt:folder]]: Unexpected child node install found in a new node
[ERROR] Error while committing /apps: javax.jcr.nodetype.ConstraintViolationException: OakConstraint0025: /apps/acs-commons[[nt:folder]]: Unexpected child node install found in a new node
[ERROR] Error while committing : javax.jcr.nodetype.ConstraintViolationException: OakConstraint0025: /apps/acs-commons[[nt:folder]]: Unexpected child node install found in a new node
[WARNING] Error while committing changes. Retrying import from checkpoint at /. Retries 1/10

@adamcin
Copy link
Owner

adamcin commented Apr 10, 2022

curious. the install node appears to be defined as nt:unstructured:

image

@adamcin
Copy link
Owner

adamcin commented Apr 11, 2022

@kwin oakpal is currently linked to version 3.4.4 of filevault, and the relevant logic is happening in FolderArtifactHandler.java:

See: https://github.com/apache/jackrabbit-filevault/blob/jackrabbit-filevault-3.4.4/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FolderArtifactHandler.java#L82-L90

The order of extraction is:

  1. -content, with filter:
<workspaceFilter version="1.0">
    <filter root="/apps/acs-commons/config"/>
    <filter root="/apps/acs-commons/config.author"/>
    <filter root="/apps/acs-commons/config.publish"/>
</workspaceFilter>
  1. -ui.apps, with filter:
<filter root="/apps/acs-commons">
    <!-- ... includes /apps/acs-commons but excludes /apps/acs-commons/install -->
    <exclude pattern="/apps/acs-commons/install(/.*)?" />
</filter>
  1. -ui.content and everything else

The constraint violation on autosave is confusing, because it looks like /apps/acs-commons is imported as nt:folder, and then we attempt to import /apps/acs-commons/install as nt:unstructured.

But actually, the FolderArtifactHandler imports all of /apps, acs-commons, and install as nt:unstructured nodes during the -content package installation, because the -content workspace filter does not contain any of those paths, and because both jcr:root and nt:unstructured nodetypes specifies + * = nt:unstructured, every segment passes the parent.getPrimaryNodeType().canAddChildNode(dir.getRelativePath()) test.

When the -ui.apps subpackage is installed, the FolderArtifactHandler accepts /apps/acs-commons for a second time, but because it already exists, and because it is contained by the -ui.apps workspace filter, its primary node type is switched to FolderArtifactHandler.nodeType, which is set to nt:folder by default.

See: https://github.com/apache/jackrabbit-filevault/blob/jackrabbit-filevault-3.4.4/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/FolderArtifactHandler.java#L106-L108

It is the next autosave after this point that fails with the constraint violation, because the install folder still exists as a child of type nt:unstructured, which is now not allowed by the nt:folder nodetype of /apps/acs-commons.

The reason this isn't reproduced when installing the -content package in any Sling or AEM distribution is that /apps is universally pre-created by these products as an nt:folder node, which causes every child of /apps that is imported by filevault to fail the parent.getPrimaryNodeType().canAddChildNode(dir.getRelativePath()) test and therefore default to nt:folder all the way down.

I think the proper resolution is to configure oakpal-maven-plugin in acs-aem-commons/pom.xml with an /apps{nt:folder} forcedRoot, because that goes along with the other expected installation environment context that is already defined.

<forcedRoots>
    <forcedRoot>
        <path>/apps</path>
        <primaryType>nt:folder</primaryType>
    </forcedRoot>
</forcedRoots>

I'll submit a PR with this change and any other related fixes and request a review from you.

@kwin
Copy link
Author

kwin commented Apr 11, 2022

Thanks for the analysis. This behavior of FileVault was introduced with https://issues.apache.org/jira/browse/JCRVLT-417. Although some regressions were already fixed with https://issues.apache.org/jira/browse/JCRVLT-544 it seems we need another exclusion for nt:unstructured in FileVault to catch this edge case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants