Aem Sling Service User Mapper Header image

AEM: Service User (Mapper) – do you really know it?

Starting from AEM 6 developers are encouraged to create special service users for their bundles/services instead of using administrative sessions. Adobe has documentation on this topic here. However, there are some features which are either not widely used, either – not well documented. So, let’s uncover them!

Report on configured Service Users in AEM

Since Service User Mapper 1.2.2

There is a page in Web Console where you can check all configured system users – /system/console/status-slingserviceusers

AEM Service Users Mapping report

For each service user you can see service and sub service names it’s configured for. This UI is much better than using Configuration Manager Console to check this, right?

Allow non-system users to be used in mappings

Since Service User Mapper 1.2.2

Yes, the heading is totally correct – you can use regular users in the mapping. To achieve this, you should create configuration for Apache Sling JCR System User Validator (org.apache.sling.jcr.resource.internal.JcrSystemUserValidator) where you should disable validation (allow.only.system.user).

I am not sure what was the reason for implementing this feature, but you would not want to use this on production.

Delay OSGi component activation until service user configuration is available

Since Service User Mapper 1.2.0

There can be cases when you do not want your component to be active if service user’s mapping is not available. In such situations, you can use ServiceUserMapped. You reference this service in your component and it will be resolved only when the corresponding mapping is available. Check example bellow:

package com.taradevko.aem.usm;

import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.sling.serviceusermapping.ServiceUserMapped;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(immediate = true)
public class SomeComponent {

    public static final Logger LOG = LoggerFactory.getLogger(SomeComponent.class);

    @Reference
    private ServiceUserMapped serviceUserMapped;

    @Activate
    private void activate() {
        System.out.println("I am active");
    }
}

Now, after deploy, it is in the state “unsatisfied” (click image for full size):

Example of sling serviceusermapped referenced in component.

Then, after adding mapping “com.taradevko.aem.usm.core=testaem” it’s getting active. Nice, isn’t it?

Also, you can specify subservice in the target of the reference if you use it: @Reference(target = “(subServiceName=mySubService)”) .

Write custom Service User Validator

Above we talked about the case when you want any user to be used with ResourceResolverFactory.getServiceResourceResolver(). But what if you want to use some different constraints instead (e.g. allow usage of the regular user which have “service-” in its name)? To achieve this, you can provide service which implements interface ServiceUserValidator.

Note: this feature has been introduced in Service User Mapper 1.1.0 but in that version, the user is allowed to use only if ALL validators returned true. Since 1.2.0 user is allowed if ANY of validators returns true.

Mapping amendments for service user mapper

If you are still not using service user mapping amendments – you are doing a big mistake! This feature allows you to define mappings in a modular way. To use it, create config for factory org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended. Check example bellow:

<!--file name is org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-someuniqueid.xml-->
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
          xmlns:jcr="http://www.jcp.org/jcr/1.0" 
          jcr:primaryType="sling:OsgiConfig"
          user.mapping="[com.taradevko.aem.usm=userid]" />

Conclusion

I hope this article will help you to fully leverage Sling Service User Mapper functionality.

Your thoughts are welcome