Expand my Community achievements bar.

SOLVED

Error: getting system user account in Sling Model using @inject ResourceResolverFactory

Avatar

Community Advisor

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.

1 Accepted Solution

Avatar

Correct answer by
Employee Advisor

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

View solution in original post

2 Replies

Avatar

Correct answer by
Employee Advisor

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

Avatar

Level 10

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.