Expand my Community achievements bar.

Dive into Adobe Summit 2024! Explore curated list of AEM sessions & labs, register, connect with experts, ask questions, engage, and share insights. Don't miss the excitement.
SOLVED

Custom User Profile Properties - Synchronization across Author and Publishers (Non-UGC)

Avatar

Level 5

Hi all,

Had a question about user profile synchronization.

Existing State (AEM 5.6.1):
Right now we have an offline process create an XML dump of users and their custom properties and store them in a file. Everyday at 5am, we've got a scheduler running in AEM that parses that file and updates the "/profile" child node of each rep:User in AEM if a property's value has changed. If something was changed, we mark a cq:Page under the rep:User as modified and needing forward replication, to which a workflow launcher listens to. The workflow that runs then activates that rep:User node, effectively pushing the updated "/profile" child node to all publish instances. This works fine right now because "/home/users/t/test-user" is the path on author and all publishers.

Future State (AEM 6.2):
I could keep doing what I'm doing for 5.6.1 but wanted to see if anyone else has tried or done something differently. I kinda feel like this method is less than stellar. I thought about User Sync[1] but that's really only for profile properties that were modified on a Publish instance, which as far as I'm aware, don't even get stored back on the Author instance when changed. Also, given the user node name changes[2] between versions, activating a user node on Author has some weird behavior when it gets to the Publish instance.

BEFORE ACTIVATION:
Author: "/home/users/p/pMyHnSw5-WblDPZIVlph [test-user]"
Publish: "/home/users/V/VEmvMSsosOQKYc8p72t6 [test-user]"

AFTER ACTIVATION:
Author: "/home/users/p/pMyHnSw5-WblDPZIVlph [test-user]"
Publish: "/home/users/p/VEmvMSsosOQKYc8p72t6 [test-user]"

It replicated the rep:User and "/profile" node properly, but it just moved the rep:User node to a different rep:AuthorizableFolder path. I feel like after updating a few user profile properties, this would get extremely confusing (visually). Users would still have to be looked up programmatically by their userID though, so it wouldn't be that bad, just weird. Also, because rep:User node(s) were modified on Publish, if User Sync IS setup, it kicks back a reverse replication package to Author telling it to update/delete any nodes that have changed:

19.12.2016 11:49:29.503 *INFO* [sling-threadpool-788bd608-1fcc-47b6-b22e-420e5f85890d-(apache-sling-job-thread-pool)-9-org_apache_sling_distribution_queue_socialpubsync_endpoint0(org/apache/sling/distribution/queue/socialpubsync/endpoint0)] org.apache.sling.distribution.agent.impl.SimpleDistributionAgent [agent][socialpubsync] [endpoint0] PACKAGE-DELIVERED DSTRQ36: ADD paths=[/home/users/p/VEmvMSsosOQKYc8p72t6, /home/users/p/VEmvMSsosOQKYc8p72t6/profile, /home/users/p/VEmvMSsosOQKYc8p72t6/rep:policy], importTime=5ms, execTime=242ms, size=5963B 19.12.2016 11:49:29.573 *INFO* [sling-threadpool-788bd608-1fcc-47b6-b22e-420e5f85890d-(apache-sling-job-thread-pool)-10-org_apache_sling_distribution_queue_socialpubsync_endpoint0(org/apache/sling/distribution/queue/socialpubsync/endpoint0)] org.apache.sling.distribution.agent.impl.SimpleDistributionAgent [agent][socialpubsync] [endpoint0] PACKAGE-DELIVERED DSTRQ36: DELETE paths=[/home/users/V/VEmvMSsosOQKYc8p72t6], importTime=1ms, execTime=312ms, size=49B

Question:
What is the best way to handle these custom profile properties and keep them in sync across all publish instances? These aren't properties that can be modified on the publish instance (not really UGC), so User Sync wouldn't work. I've considered possibly reading/writing these with the SRP API anyway, even though they're not UGC. This would prevent the need for replication of non-content, just wondering what (if any) drawbacks that may have?

[1] https://docs.adobe.com/docs/en/aem/6-2/administer/security/security/sync.html
[2] http://help-forums.adobe.com/content/adobeforums/en/experience-manager-forum/adobe-experience-manage...

1 Accepted Solution

Avatar

Correct answer by
Level 4
5 Replies

Avatar

Level 5

No one has any input on this? :(

Avatar

Level 5

Just wanted to update on something that I tried and an issue I've run into with that method...

Since my user profile property update scheduler is a @Service, I've grabbed a @Reference to Replicator[1] and am trying to queue up the "/home/users/a/aFb4JUP9Z7XAr1z2wQle/profile" node but because that userId exists in the Publish instance under some other random hash path, I'm getting the following in the publish's error.log:

2.12.2016 08:52:58.270 *ERROR* [127.0.0.1 [1482418378267] POST /bin/receive HTTP/1.1] com.day.cq.replication.impl.content.durbo.DurboImportTransformer Cannot create authorizable aFb4JUP9Z7XAr1z2wQle org.xml.sax.SAXException: a node with uuid 71541653-edfd-31ee-8ae6-2fb1fd1be011 already exists! at org.apache.jackrabbit.oak.jcr.xml.SysViewImportHandler.processNode(SysViewImportHandler.java:91) at org.apache.jackrabbit.oak.jcr.xml.SysViewImportHandler.endElement(SysViewImportHandler.java:220) at org.apache.jackrabbit.oak.jcr.xml.ImportHandler.endElement(ImportHandler.java:197) at com.day.cq.replication.impl.content.durbo.DurboImportTransformer.endElement(DurboImportTransformer.java:893) at com.day.cq.replication.impl.content.durbo.DurboImportTransformer.addSimpleAuthorizable(DurboImportTransformer.java:934) at com.day.cq.replication.impl.content.durbo.DurboImporter.createParentPath(DurboImporter.java:108) at com.day.cq.replication.impl.content.durbo.DurboImporter.createParentPath(DurboImporter.java:156) at com.day.cq.replication.impl.content.durbo.DurboImporter.createNode(DurboImporter.java:272) at com.day.cq.replication.impl.content.durbo.DurboImporter.createNode(DurboImporter.java:214) at com.day.cq.replication.impl.ReplicationReceiverImpl.receive(ReplicationReceiverImpl.java:183) at com.day.cq.replication.impl.servlets.ReplicationServlet.doPost(ReplicationServlet.java:204) at org.apache.sling.api.servlets.SlingAllMethodsServlet.mayService(SlingAllMethodsServlet.java:149) at org.apache.sling.api.servlets.SlingSafeMethodsServlet.service(SlingSafeMethodsServlet.java:345) at org.apache.sling.api.servlets.SlingSafeMethodsServlet.service(SlingSafeMethodsServlet.java:376) at org.apache.sling.engine.impl.request.RequestData.service(RequestData.java:546) ... skipped a bunch of stack traces ... Caused by: javax.jcr.ItemExistsException: a node with uuid 71541653-edfd-31ee-8ae6-2fb1fd1be011 already exists! at org.apache.jackrabbit.oak.jcr.xml.ImporterImpl.resolveUUIDConflict(ImporterImpl.java:224) at org.apache.jackrabbit.oak.jcr.xml.ImporterImpl.startNode(ImporterImpl.java:455) at org.apache.jackrabbit.oak.jcr.xml.SysViewImportHandler.processNode(SysViewImportHandler.java:80) ... 116 common frames omitted 22.12.2016 08:52:58.270 *ERROR* [127.0.0.1 [1482418378267] POST /bin/receive HTTP/1.1] com.day.cq.replication.impl.servlets.ReplicationServlet Error during replication: null java.lang.NullPointerException: null at com.day.cq.replication.impl.content.durbo.DurboImportTransformer.createNode(DurboImportTransformer.java:305) at com.day.cq.replication.impl.content.durbo.DurboImportTransformer.traverse(DurboImportTransformer.java:220) at com.day.cq.replication.impl.content.durbo.DurboImportTransformer.transform(DurboImportTransformer.java:157) at com.day.cq.replication.impl.content.durbo.DurboImporter.createNode(DurboImporter.java:282) at com.day.cq.replication.impl.content.durbo.DurboImporter.createNode(DurboImporter.java:214) at com.day.cq.replication.impl.ReplicationReceiverImpl.receive(ReplicationReceiverImpl.java:183) at com.day.cq.replication.impl.servlets.ReplicationServlet.doPost(ReplicationServlet.java:204) at org.apache.sling.api.servlets.SlingAllMethodsServlet.mayService(SlingAllMethodsServlet.java:149) at org.apache.sling.api.servlets.SlingSafeMethodsServlet.service(SlingSafeMethodsServlet.java:345) at org.apache.sling.api.servlets.SlingSafeMethodsServlet.service(SlingSafeMethodsServlet.java:376) at org.apache.sling.engine.impl.request.RequestData.service(RequestData.java:546) at org.apache.sling.engine.impl.filter.SlingComponentFilterChain.render(SlingComponentFilterChain.java:44)

Should I just be trying to replicate the whole rep:User ("/home/users/a/aFb4JUP9Z7XAr1z2wQle") instead?

[1] https://docs.adobe.com/docs/en/aem/6-2/develop/ref/javadoc/com/day/cq/replication/Replicator.html

Avatar

Community Advisor

Hi Gdubz,

Please follow the below steps to sync users across Publisher in AEM 6.1 and above:

  1. You should make sure that user node should not be created with its name and should be with some random name.

       e.g.  /home/users/p/test1 it should be with   /home/users/p/VEmvMSsosOQKYc8p72t6.

      2. Write a script(or groovy script) to handle the above difference in user path by the below logic:

        If UUID is same in Author and Publish for a user but user path is different then identify those whose user node is random.

      3. Do the sling distribution to sync users across Publishers.

 

Regards,

Varun Rawat

Avatar

Level 9

Hi Gdubz,

     Firstly, when you set up publishers configure to sync profiles using sling distribution has documented. Any subsequent new user creation Or modification takes care of sync.   You can execute your scheduler on any one instance.  

 In case current user path is not in sync. I would say clone one publisher to other instnace so that random user node matches.

Thanks,

Avatar

Correct answer by
Level 4