Hi,
I am trying to get a system user session in Sling Model by using @inject ResourceResolverFactory .I am getting below error
org.apache.sling.api.resource.LoginException: Cannot derive user name for bundle org.apache.sling.models.impl [322] and sub service
But i am able to get the session if i add the same session logic to a @Component class and inject this component into my sling bundle. So there is no issue with System user account setup.Issue is with injection.
Below is my code for sling model to get system user:
package com.adobe.db.core.models;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import javax.jcr.Session;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.models.annotations.Default;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.settings.SlingSettingsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.sling.api.resource.Resource;
@Model(adaptables=Resource.class)
public class HelloWorldModel {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Inject
private SlingSettingsService settings;
@Inject @Named("sling:resourceType") @Default(values="No resourceType")
protected String resourceType;
@Inject
private ResourceResolverFactory rrFactory;
private ResourceResolver resourceResolverWriter;
@Inject
private HelloService HelloService;
private static Session adminSession;
private String message;
@PostConstruct
protected void init() {
message = "\tHello World! "+HelloService.getRepositoryName()+"\n";
message += "\tThis is instance: " + settings.getSlingId() + "\n";
message += "\tResource type is: " + resourceType + "\n";
}
public String getMessage() {
log.info("inside getmessage====>");
try {
Map<String, Object> param = new HashMap<String, Object>();
param.put(ResourceResolverFactory.SUBSERVICE, "training36");
//Invoke the getServiceResourceResolver method to create a Session instance
resourceResolverWriter = rrFactory.getServiceResourceResolver(param);
adminSession = resourceResolverWriter.adaptTo(Session.class);
log.info("####### session ######### : " + adminSession.getUserID());
} catch (Exception e) {
e.printStackTrace();
}
return message;
}
}
If i use the same class with a component reference which process the session its working fine as shown below.
Sling Model Class
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import javax.jcr.Session;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Default;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Optional;
import org.apache.sling.settings.SlingSettingsService;
import com.adobe.training36.core.HelloService;
@Model(adaptables=Resource.class)
public class HelloWorldModel {
@Inject
private SlingSettingsService settings;
@Inject @Named("sling:resourceType") @Default(values="No resourceType")
protected String resourceType;
@Inject
private HelloService HelloService;
private static Session adminSession;
private String message;
@PostConstruct
protected void init() {
message = "\tHello World! "+HelloService.getSessionName()+"\n";
message += "\tThis is instance: " + settings.getSlingId() + "\n";
message += "\tResource type is: " + resourceType + "\n";
}
public String getMessage() {
return message;
}
}
Component Class
import java.util.HashMap;
import java.util.Map;
import javax.jcr.Repository;
import javax.jcr.Session;
//import javax.jcr.Repository;
//import javax.sql.DataSource;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.jcr.api.SlingRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(immediate=true)
@Service
public class HelloServiceImpl implements HelloService{
private static Session adminSession;
protected static final Logger log = LoggerFactory.getLogger( HelloServiceImpl.class);
@Reference
private SlingRepository repository;
@Reference
private ResourceResolverFactory rrFactory;
private ResourceResolver resourceResolverWriter;
@Override
public String getSessionName() {
try {
Map<String, Object> param = new HashMap<String, Object>();
param.put(ResourceResolverFactory.SUBSERVICE, "training36");
resourceResolverWriter = rrFactory.getServiceResourceResolver(param);
adminSession = resourceResolverWriter.adaptTo(Session.class);
log.info("####### session ######### : " + adminSession.getUserID());
} catch (Exception e) {
e.printStackTrace();
}
return adminSession.getUserID();
}
}
I suspect in my sling model injector status http://localhost:4502/system/console/status-slingmodels its not showin Resource Resolver injection.
Not sure is it because of that.
Please suggest.
Solved! Go to Solution.
Views
Replies
Total Likes
Hi,
your problem is that a sling model runs in the scope of the sling scripting bundle (at least in the context of the determination of service users), and the sling scripting bundle does not provide a system user for your case.
A OSGI component always runs in the context of the bundle it is part of, and in that case the lookup of the system user works.
So you don't see a bug but intended behavior.
Anyways, in my point of view a Sling model should not contain too much logic; in the end it's a model for a frontend component, and therefor the session you have at hand should be sufficient. If you need to use a system user session to perform activities which are not possible to do with the permissions of the user executing the request, you should move this into an OSGI service/component.
regards,
Jörg
Hi,
your problem is that a sling model runs in the scope of the sling scripting bundle (at least in the context of the determination of service users), and the sling scripting bundle does not provide a system user for your case.
A OSGI component always runs in the context of the bundle it is part of, and in that case the lookup of the system user works.
So you don't see a bug but intended behavior.
Anyways, in my point of view a Sling model should not contain too much logic; in the end it's a model for a frontend component, and therefor the session you have at hand should be sufficient. If you need to use a system user session to perform activities which are not possible to do with the permissions of the user executing the request, you should move this into an OSGI service/component.
regards,
Jörg
Break your logic into two classes. If you need to get a System user - keep it within a @Component. Then you can get the instance of the component class rfom a Sling Model using @Inject.