Service Users Mapper in AEM
Goal
Get and use a session/resource resolver with proper and specific Access Control Levels (ACLs) instead of using administrative ones.
Procedure
First thing, create the system user: go to http://localhost:4502/crx/explorer/index.jsp and follow the next images. Remember to check if you are logged in, as highlighted in the first image, and just choose a name for your user, in this case “Lab2020user“


Go to the useradmin page (http://localhost:4502/useradmin), search for your user and set the permissions you want.
Now create the configuration file named org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-<unique-name-for- -your-factory>.xml inside the folder with the other OSGi configurations, e.g org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-lab2020.xml
Here is the file:
<?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"
service.ranking="0"
user.mapping="[Lab2020.core:lab2020ReadWriteService=Lab2020user"
/>
The user.mapping property is composed of:
- the
artifact i
d of your core module: “Lab2020.core” in my case - the
subservice-name
: a custom name, e.g. “lab2020ReadWriteService” - the user-id: the system user id created previously
Let’s go now to the Java code.
Create for istance an Utils class like this:
package com.adobe.training.core.utils;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
/**
* Lab2020CommonMethods Class.
*
* @author riccardo.teruzzi
*/
public class Lab2020CommonMethods {
/**
* Constant for Read Write Service.
*/
private static final String LAB_2020_READ_WRITE_SERVICE = "lab2020ReadWriteService";
/**
* Constant for Logger.
*/
private static final Logger LOG = LoggerFactory.getLogger(Lab2020CommonMethods.class);
/**
* Gets resource resolver.
*
* @param rFactory the r factory
* @return resource resolver This method is used to get the resource resolver by providing the resource resolver factory.
*/
public static ResourceResolver getResourceResolver(final ResourceResolverFactory rFactory) {
ResourceResolver resolver = null;
Map<String, Object> param = getServiceParams();
try {
resolver = rFactory.getServiceResourceResolver(param);
} catch (LoginException e) {
LOG.error(e.getMessage(), e);
}
return resolver;
}
/**
* @return params
*/
private static Map<String, Object> getServiceParams() {
Map<String, Object> param = new HashMap<>();
param.put(ResourceResolverFactory.SUBSERVICE, LAB_2020_READ_WRITE_SERVICE);
return param;
}
}
Inject the resourceFactory properly (it should be an OSGi service so use @Reference) and pass it as parameter to the method getResourceResolver to get your resource resolver.
That’s all! If you have more system users, you could extend your method and have the subservice name as an additional argument for instance.
Cheers! 🍻