Adobe

Including Service Users in Your AEM Package

While working on a project recently, I needed to include a service user within the Adobe Experience Manager package I was deploying. By doing this, administrators wouldn’t have to create the service users manually During this process, I ran into a few exceptions and wanted to share.

A few things to note:

  1. The banner photo is by chuttersnap on Unsplash
  2. You can do this easily with ACS Commons Ensure Authorizable feature, but I did not want to depend on ACS commons.
  3. All of this was done on AEM 6.4, though I assume the same issue would happen on 6.3.

Now onto the good stuff!

Adding my service user to the package

In my package, I created the following path:
/home/users/system/my-project/my-project-service-user
I then added the following properties:

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root
    xmlns:jcr="http://www.jcp.org/jcr/1.0"
    xmlns:rep="internal"
    jcr:primaryType="rep:SystemUser"
    jcr:uuid="bf2451f1-e091-3b27-90b1-52d7701bc60f"
    rep:authorizableId="my-project-service-user"
    rep:principalName="my-project-service-user"/>
Adobe - Content for Everyone
Content for Everyone

Companies that can quickly and consistently meet the demands of consumers are thriving in an era of infinite content. Learn about how to build fluid experiences for your omnichannel customers.

Get the Guide

 
Which is the same as the way ACS commons have their system users set up.

Deploying and errors:

When deploying, this error is printed in the console:

Request failed: org.apache.jackrabbit.vault.packaging.PackageException: javax.jcr.nodetype.ConstraintViolationException: OakConstraint0021: /home/users/system/my-project/my-project-service-user[[rep:SystemUser]]: Mandatory property rep:principalName not found in a new node (500)

But the rep:principalName was there!
Now, looking at the error logs:

5.01.2019 12:07:35.913 *ERROR* [qtp1214328009-1747] org.apache.jackrabbit.vault.fs.impl.io.GenericArtifactHandler Error while parsing jcr_root/home/users/system/my-project/my-project-service-user/.content.xml: {}
org.xml.sax.SAXException: Cannot handle protected PropInfo org.apache.jackrabbit.oak.spi.xml.PropInfo@715c673d. Invalid rep:authorizableId.
  at org.apache.jackrabbit.oak.jcr.xml.SysViewImportHandler.processNode(SysViewImportHandler.java:92) [org.apache.jackrabbit.oak-jcr:1.8.9]
  at org.apache.jackrabbit.oak.jcr.xml.SysViewImportHandler.endElement(SysViewImportHandler.java:221) [org.apache.jackrabbit.oak-jcr:1.8.9]
  at org.apache.jackrabbit.oak.jcr.xml.ImportHandler.endElement(ImportHandler.java:197) [org.apache.jackrabbit.oak-jcr:1.8.9]
  at org.apache.jackrabbit.vault.fs.impl.io.JcrSysViewTransformer.endNode(JcrSysViewTransformer.java:189) [org.apache.jackrabbit.vault:3.2.5.R1844726]
  at org.apache.jackrabbit.vault.fs.impl.io.DocViewSAXImporter.endElement(DocViewSAXImporter.java:1155) [org.apache.jackrabbit.vault:3.2.5.R1844726]
  at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:609)
  at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:183)
  at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:351)
  at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:613)
  at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3132)
  at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:852)
  at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)
  at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112)
  at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:505)
  at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:842)
  at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:771)
  at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
  at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
  at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
  at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.parse(SAXParserImpl.java:327)
  at org.apache.jackrabbit.vault.fs.impl.io.GenericArtifactHandler.accept(GenericArtifactHandler.java:99) [org.apache.jackrabbit.vault:3.2.5.R1844726]
  at org.apache.jackrabbit.vault.fs.io.Importer.commit(Importer.java:929) [org.apache.jackrabbit.vault:3.2.5.R1844726]
  at org.apache.jackrabbit.vault.fs.io.Importer.commit(Importer.java:798) [org.apache.jackrabbit.vault:3.2.5.R1844726]
  at org.apache.jackrabbit.vault.fs.io.Importer.commit(Importer.java:838) [org.apache.jackrabbit.vault:3.2.5.R1844726]
  at org.apache.jackrabbit.vault.fs.io.Importer.commit(Importer.java:838) [org.apache.jackrabbit.vault:3.2.5.R1844726]
  at org.apache.jackrabbit.vault.fs.io.Importer.commit(Importer.java:838) [org.apache.jackrabbit.vault:3.2.5.R1844726]
  at org.apache.jackrabbit.vault.fs.io.Importer.commit(Importer.java:838) [org.apache.jackrabbit.vault:3.2.5.R1844726]
  at org.apache.jackrabbit.vault.fs.io.Importer.commit(Importer.java:838) [org.apache.jackrabbit.vault:3.2.5.R1844726]
  at org.apache.jackrabbit.vault.fs.io.Importer.run(Importer.java:436) [org.apache.jackrabbit.vault:3.2.5.R1844726]
  at org.apache.jackrabbit.vault.packaging.impl.ZipVaultPackage.extract(ZipVaultPackage.java:233) [org.apache.jackrabbit.vault:3.2.5.R1844726]
  at org.apache.jackrabbit.vault.packaging.impl.JcrPackageImpl.extract(JcrPackageImpl.java:400) [org.apache.jackrabbit.vault:3.2.5.R1844726]
  at org.apache.jackrabbit.vault.packaging.impl.JcrPackageImpl.extract(JcrPackageImpl.java:359) [org.apache.jackrabbit.vault:3.2.5.R1844726]
  at org.apache.jackrabbit.vault.packaging.impl.JcrPackageImpl.install(JcrPackageImpl.java:353) [org.apache.jackrabbit.vault:3.2.5.R1844726]
  at com.day.crx.packmgr.impl.servlets.ServiceServlet.doInstall(ServiceServlet.java:437) [com.adobe.granite.crx-packagemgr:1.2.60.CQ640-B0002]
  at com.day.crx.packmgr.impl.servlets.ServiceServlet.upload(ServiceServlet.java:512) [com.adobe.granite.crx-packagemgr:1.2.60.CQ640-B0002]
  at com.day.crx.packmgr.impl.servlets.ServiceServlet.doService(ServiceServlet.java:180) [com.adobe.granite.crx-packagemgr:1.2.60.CQ640-B0002]
  at com.day.crx.packmgr.impl.AbstractServlet.service(AbstractServlet.java:54) [com.adobe.granite.crx-packagemgr:1.2.60.CQ640-B0002]
  at com.day.crx.packmgr.impl.MainServlet.doService(MainServlet.java:158) [com.adobe.granite.crx-packagemgr:1.2.60.CQ640-B0002]
  at com.day.crx.packmgr.impl.MainServlet.service(MainServlet.java:135) [com.adobe.granite.crx-packagemgr:1.2.60.CQ640-B0002]
  at org.apache.felix.http.base.internal.handler.ServletHandler.handle(ServletHandler.java:120) [org.apache.felix.http.jetty:4.0.6]
  at org.apache.felix.http.base.internal.dispatch.InvocationChain.doFilter(InvocationChain.java:86) [org.apache.felix.http.jetty:4.0.6]
  at org.apache.sling.security.impl.ReferrerFilter.doFilter(ReferrerFilter.java:328) [org.apache.sling.security:1.1.12]
  at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:135) [org.apache.felix.http.jetty:4.0.6]
  at org.apache.felix.http.base.internal.dispatch.InvocationChain.doFilter(InvocationChain.java:81) [org.apache.felix.http.jetty:4.0.6]
  at com.adobe.granite.license.impl.LicenseCheckFilter.doFilter(LicenseCheckFilter.java:308) [com.adobe.granite.license:1.2.6.CQ640-B0001]
  at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:135) [org.apache.felix.http.jetty:4.0.6]
  at org.apache.felix.http.base.internal.dispatch.InvocationChain.doFilter(InvocationChain.java:81) [org.apache.felix.http.jetty:4.0.6]
  at org.apache.felix.http.sslfilter.internal.SslFilter.doFilter(SslFilter.java:96) [org.apache.felix.http.sslfilter:1.2.4]
  at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:135) [org.apache.felix.http.jetty:4.0.6]
  at org.apache.felix.http.base.internal.dispatch.InvocationChain.doFilter(InvocationChain.java:81) [org.apache.felix.http.jetty:4.0.6]
  at org.apache.sling.i18n.impl.I18NFilter.doFilter(I18NFilter.java:131) [org.apache.sling.i18n:2.5.14]
  at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:135) [org.apache.felix.http.jetty:4.0.6]
  at org.apache.felix.http.base.internal.dispatch.InvocationChain.doFilter(InvocationChain.java:81) [org.apache.felix.http.jetty:4.0.6]
  at org.apache.felix.http.base.internal.dispatch.Dispatcher$1.doFilter(Dispatcher.java:146) [org.apache.felix.http.jetty:4.0.6]
  at org.apache.felix.http.base.internal.whiteboard.WhiteboardManager.invokePreprocessors(WhiteboardManager.java:1000) [org.apache.felix.http.jetty:4.0.6]
  at org.apache.felix.http.base.internal.dispatch.Dispatcher.dispatch(Dispatcher.java:91) [org.apache.felix.http.jetty:4.0.6]
  at org.apache.felix.http.base.internal.dispatch.DispatcherServlet.service(DispatcherServlet.java:49) [org.apache.felix.http.jetty:4.0.6]
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:725) [org.apache.felix.http.servlet-api:1.1.2]
  at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1340) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1242) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:220) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.server.Server.handle(Server.java:503) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765) [org.apache.felix.http.jetty:4.0.6]
  at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683) [org.apache.felix.http.jetty:4.0.6]
  at java.lang.Thread.run(Thread.java:748)
Caused by: javax.jcr.nodetype.ConstraintViolationException: Cannot handle protected PropInfo org.apache.jackrabbit.oak.spi.xml.PropInfo@715c673d. Invalid rep:authorizableId.
  at org.apache.jackrabbit.oak.security.user.UserImporter.handlePropInfo(UserImporter.java:244) [org.apache.jackrabbit.oak-core:1.8.9]
  at org.apache.jackrabbit.oak.jcr.xml.ImporterImpl.importProperties(ImporterImpl.java:280) [org.apache.jackrabbit.oak-jcr:1.8.9]
  at org.apache.jackrabbit.oak.jcr.xml.ImporterImpl.startNode(ImporterImpl.java:463) [org.apache.jackrabbit.oak-jcr:1.8.9]
  at org.apache.jackrabbit.oak.jcr.xml.SysViewImportHandler.processNode(SysViewImportHandler.java:81) [org.apache.jackrabbit.oak-jcr:1.8.9]
  ... 80 common frames omitted

And that was even more puzzling…

A debugging session to the rescue!

I was perplexed, so I reached out to my coworker, Paul Bjorkstrand, and together we debugged the Jackrabbit source code looking for clues. We later discovered that the jcr:uuid property is actually derived from the rep:authorizableId value, and is NOT just a random UUID.

If you’d like to see for yourself, follow the source code for jackrabbit starting with:
https://github.com/apache/jackrabbit-oak/blob/1.8/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java#L240. specifically, the call to userManager.getAuthorizable(id); and following the code along till you arrive at: https://github.com/apache/jackrabbit-oak/blob/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/UUIDUtils.java#L35

The solution

So, since the UUID is derived from the rep:authorizableId (the user name), I just create that service user manually then copy the generated UUID for that user and add it to my source-code. And voila, problem solved!
Special thanks to Paul Bjorkstrand for the exceptional help with this.

About the Author

Ahmed is an Adobe Technical Lead and expert in the Adobe Experience Cloud.

More from this Author

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Subscribe to the Weekly Blog Digest:

Sign Up
Categories