AEM 6.3-Service中的ResourceResolverFactory为null,并在Sling Model类中抛出LoginException [英] AEM 6.3 - ResourceResolverFactory is null in Service and throwing LoginException in Sling Model class

查看:114
本文介绍了AEM 6.3-Service中的ResourceResolverFactory为null,并在Sling Model类中抛出LoginException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

1)我正在尝试在SlingModel类中注入ResourceResolverFactory:

1) I am trying to inject ResourceResolverFactory in SlingModel class like this:

package com.aem.sites.models;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;

import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aem.sites.services.WeatherService;


@Model(adaptables=Resource.class)
public class Banner {

    final static Logger logger = LoggerFactory.getLogger(Banner.class);

    @Inject
    private WeatherService weatherService;

    private String serviceEndpoint;

    private String apiKey;

    private String temperature;

    @Inject
    @Optional
    @Named("bannerText")
    private String bannerText;

    @Inject
    @Optional
    @Named("button1Text")
    private String button1Text;

    @Inject
    @Optional
    @Named("button2Text")
    private String button2Text;

     @Inject
    private ResourceResolverFactory resourceResolverFactory;

        @PostConstruct
        public void init() {
            serviceEndpoint = weatherService.getServiceEndpoint();
            apiKey = weatherService.getApiKey();
            temperature = weatherService.getTemperatureValue()+" "+weatherService.getUnit();
            checkTemperatureProperty();
        }


        public String getServiceEndpoint() {
            return serviceEndpoint;
        }

        public String getApiKey() {
            return apiKey;
        }


        public String getTemperature() {
            return temperature;
        }


        public String getBannerText() {
            return bannerText;
        }


        public String getButton1Text() {
            return button1Text;
        }


        public String getButton2Text() {
            return button2Text;
        }

        private void checkTemperatureProperty() {
            logger.info("**********************checkTemperatureProperty****************");
            Map<String, Object> param = new HashMap<String, Object>();
            param.put(ResourceResolverFactory.SUBSERVICE,"getResourceResolver");
            ResourceResolver resourceResolver = null;
            try {
                if(resourceResolverFactory == null) {
                    logger.info("***********************resourceResolverFactory is null******************************");
                }
                else {
                    resourceResolver = resourceResolverFactory.getServiceResourceResolver(param);
                    logger.info("**********************resource resolver id****************"+resourceResolver.getUserID());
                    //Resource resource = resourceResolver.getResource("/content/aemsite/en/jcr:content/root/responsivegrid/banner");
                    //ValueMap readMap = resource.getValueMap();
                    //logger.info(readMap.get("temperature", ""));
                }
            }
            catch (LoginException e) {
                logger.error("LoginException",e);
            } finally{
                if(resourceResolver != null && resourceResolver.isLive()){
                    resourceResolver.close();
                }
            }
        }

}

这里讨论的方法是checkTemperatureProperty()。我创建了看起来像这样的系统用户:

The method in question here is checkTemperatureProperty(). I have created system user that looks like this :

我还已经这样配置了Mapper服务修正案:

I have also configured the Mapper Service Amendment like this:

捆绑商品的符号名称如下:

The symbolic name of the bundle looks like this :

ResourceResolverFactor注入在Sling Model类中引发LoginException,这是错误:

The ResourceResolverFactor injection is throwing LoginException in the Sling Model class and here is the error:

com.aem.sites.models.Banner LoginException
org.apache.sling.api.resource.LoginException: Cannot derive user name for bundle org.apache.sling.models.impl [489] and sub service getResourceResolver
    at org.apache.sling.resourceresolver.impl.ResourceResolverFactoryImpl.getServiceResourceResolver(ResourceResolverFactoryImpl.java:86)

当我尝试使用@Reference在Service中使用ResourceResolverFactory时,它会抛出空指针异常。

While when I am trying to use the ResourceResolverFactory in Service using @Reference, it is throwing a null pointer exception.

有关类如下,方法checkTemperatureProperty()行号195:

The class in question is given below, method checkTemperatureProperty() line number 195:

package com.aem.sites.services.impl;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Reference;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.metatype.annotations.Designate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aem.sites.interfaces.Configuration;
import com.aem.sites.pojos.CurrentConditions;
import com.aem.sites.services.WeatherService;
import com.google.gson.Gson;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.resource.LoginException;


// TODO: Auto-generated Javadoc
/**
 * The Class WeatherServiceImpl.
 */
@Component(service = WeatherService.class,
immediate = true,
configurationPid = "com.aem.sites.services.impl.WeatherServiceImpl")
@Designate(ocd = Configuration.class)
public class WeatherServiceImpl implements WeatherService {

    /** The Constant logger. */
    final static Logger logger = LoggerFactory.getLogger(WeatherServiceImpl.class);

    /** The service endpoint. */
    private String serviceEndpoint;

    /** The api key. */
    private String apiKey;

    /** The response body. */
    private String responseBody;

    /** The temperature value. */
    private String temperatureValue;

    /** The unit. */
    private String unit;

    /** The resource resolver factory. */
    @Reference
    private ResourceResolverFactory resourceResolverFactory;

    /* (non-Javadoc)
     * @see com.aem.sites.services.WeatherService#getServiceEndpoint()
     */
    @Override
    public String getServiceEndpoint() {
        return serviceEndpoint;
    }

    /* (non-Javadoc)
     * @see com.aem.sites.services.WeatherService#getApiKey()
     */
    @Override
    public String getApiKey() {
        return apiKey;
    }

    /**
     * Activate.
     *
     * @param config the config
     */
    @Activate
    @Modified
    protected final void activate(Configuration config) {
        logger.info("**********************************************activate********************************************");
        serviceEndpoint = config.getServiceURL();
        apiKey = config.getApiKey();
        String serviceURL = createRequestURL();
        logger.info("**************************The serviceURL is*******************************************"+serviceURL);
        callWebService(serviceURL);
        String responseString = getResponseBody();
        logger.info("**************************The response body is*******************************************"+responseString);
        convertStringToPojos(responseString);
        checkTemperatureProperty();
        //saveTemperatureInTheNode();

    }

    /**
     * Creates the request URL.
     *
     * @return the string
     */
    private String createRequestURL() {
        StringBuilder sb = new StringBuilder(); ;
        if(!StringUtils.isEmpty(serviceEndpoint)) {
            sb.append(serviceEndpoint);
            sb.append("/currentconditions/v1/33785");
            sb.append("?apikey=");
            sb.append(apiKey);
        }
        return sb.toString();
    }

    /**
     * Call web service.
     *
     * @param serviceURL the service URL
     */
    private void callWebService(String serviceURL) {
        if(!StringUtils.isEmpty(serviceURL))  {
            CloseableHttpClient httpclient = HttpClients.createDefault();
            HttpGet httpget = new HttpGet(serviceURL);
            CloseableHttpResponse response = null;
            try {
                response = httpclient.execute(httpget);
                HttpEntity entity = response.getEntity();
                int status = response.getStatusLine().getStatusCode();
                if (status >= 200 && status < 300) {
                    if (entity != null) {
                        String responseString = EntityUtils.toString(entity);
                        setResponseBody(responseString);
                    }
                }
                else {
                    logger.info("*********************Unexpected response status: " + status);
                }
            } catch (IOException | UnsupportedOperationException e) {
                // TODO Auto-generated catch block
                logger.info("***********************************inside catch block****************IOException"+e.getMessage());
            }
            finally {
                if(null != response){
                    try {
                        response.close();
                        httpclient.close();
                    } catch (IOException e) {
                        logger.info("***********************************inside finally block****************IOException"+e.getMessage());
                    }
                }
            }
        }
    }

    /**
     * Convert string to pojos.
     *
     * @param jsonString the json string
     */
    private void convertStringToPojos(String jsonString) {
        if(!StringUtils.isEmpty(jsonString))  {
            jsonString = jsonString.substring(1);
            if(!StringUtils.isEmpty(jsonString))  {
                int ind = jsonString.lastIndexOf("]");
                if(ind >= 0) {
                    jsonString = jsonString.substring(0,jsonString.length()-1);
                }
                Gson gson = new Gson();
                if(!StringUtils.isEmpty(jsonString))  {
                    CurrentConditions conditions = gson.fromJson(jsonString, CurrentConditions.class);
                    logger.info("***************current temperature is*****************"+conditions.getTemperature().getImperial().getValue());
                    temperatureValue = conditions.getTemperature().getImperial().getValue();
                    unit = conditions.getTemperature().getImperial().getUnit();
                }
            }
        }
    }


    /**
     * Save temperature in the node.
     */
    private void checkTemperatureProperty() {
        logger.info("**********************checkTemperatureProperty****************");
        Map<String, Object> param = new HashMap<String, Object>();
        param.put(ResourceResolverFactory.SUBSERVICE,"getResourceResolver");
        ResourceResolver resourceResolver = null;
        try {
            resourceResolver = resourceResolverFactory.getServiceResourceResolver(param);
            logger.info("**********************resource resolver id****************"+resourceResolver.getUserID());
            Resource resource = resourceResolver.getResource("/content/aemsite/en/jcr:content/root/responsivegrid/banner");
            ValueMap readMap = resource.getValueMap();
            logger.info(readMap.get("temperature", ""));
        }
        catch (LoginException e) {
            logger.error("LoginException",e);
        } finally{
            if(resourceResolver != null && resourceResolver.isLive()){
                resourceResolver.close();
            }
        }
    }

    private void saveTemperatureProperty() {

    }

    /**
     * Gets the response body.
     *
     * @return the response body
     */
    public String getResponseBody() {
        return responseBody;
    }

    /**
     * Sets the response body.
     *
     * @param responseBody the new response body
     */
    public void setResponseBody(String responseBody) {
        this.responseBody = responseBody;
    }

    /* (non-Javadoc)
     * @see com.aem.sites.services.WeatherService#getTemperatureValue()
     */
    @Override
    public String getTemperatureValue() {
        // TODO Auto-generated method stub
        return temperatureValue;
    }

    /* (non-Javadoc)
     * @see com.aem.sites.services.WeatherService#getUnit()
     */
    @Override
    public String getUnit() {
        // TODO Auto-generated method stub
        return unit;
    }

    /**
     * Deactivate.
     */
    @Deactivate
    protected void deactivate() {
    }
}

我首先尝试在服务类(第二类)中使用ResourceResolverFactory,然后在Banner.java(第一类)中使用。

I first tried using the ResourceResolverFactory in the service class(second class) and then in the Banner.java(first class). But it worked in neither.

我遍历了各种教程,并对stackoverflow提出了类似的问题。其中一些在这里:

I have gone through various tutorials and also similar questions raised here on stackoverflow. Some of them are here:

ResourceResolverFactory getServiceResourceResolver在AEM 6.1中引发异常

服务类中的ResourceResolverFactory和SlingRepository为空

ResourceResolverFactory为NULL(Adobe Experience Manager AEM)

并完全遵循它,但是找不到分辨率。谢谢您的帮助。

and followed it completely but couldn't find the resolution. Any help is appreciated.

谢谢。

推荐答案


我看到您正在使用OSGI声明式服务(DS)

I see You are using OSGI declarative services (DS)

一些事情:


  1. 如果您使用SCR注释,则应从POM中删除SCR依赖性,以免造成混淆。

  2. 如果仅使用OSGI DS,则必须具有以下内容:


    • 阅读此优秀的帖子作者Nate Yolles

    • 您的 maven-bundle-plugin 依赖项必须是版本 3.2.0 或更高版本

    • 您必须在软件包 org.osgi.service.component.annotations 中使用批注,而在软件包<$ c中不使用SCR批注。 $ c> org.apache.felix.scr.annotations.Reference

  1. If you are not using SCR annotations, you should remove SCR dependencies from your POM/s to eliminate confusion.
  2. If you are using OSGI DS only, you have to have the following:
    • Read this excellent post by Nate Yolles
    • Your maven-bundle-plugin dependency has to be version 3.2.0 or greater
    • You have to use annotations in package org.osgi.service.component.annotations and not the SCR annotations in package org.apache.felix.scr.annotations.Reference

在您的气象服务中,我看到您使用的是SCR的 @Reference ,而不是OSGI的 @参考

in your weather service, I see you are using SCR's @Reference and not OSGI's @Reference

在吊带模型中:
您应该使用OSGI服务用于服务的注入器: @OSGiService
尽管使用 @Inject 效果很好,但特定的注入器更适合可读性和性能,尽管无关紧要,因为我们仅使用特定的注入器

In your sling model: You should use OSGI service injector for services: @OSGiService Though using @Inject works just fine, a specific injector is better for readability and performance, albeit insignificant, since we only use a specific injector

以下是使用您的某些代码的服务示例:

天气服务界面:

package com.aem.sites.services;

public interface WeatherService
{
  public String checkApps();

}

天气服务显示:

package com.aem.sites.services.impl;

import java.util.HashMap;
import java.util.Map;

import org.apache.felix.scr.annotations.Reference;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.metatype.annotations.Designate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aem.sites.services.Configuration;
import com.aem.sites.services.WeatherService;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.LoginException;



/**
 * The Class WeatherServiceImpl.
 */
@Component(service = WeatherService.class,
        immediate = true,
        configurationPid = "com.aem.sites.services.impl.WeatherServiceImpl")
@Designate(ocd = Configuration.class)
public class WeatherServiceImpl implements WeatherService {

  /** The Constant logger. */
  final static Logger logger = LoggerFactory.getLogger(WeatherServiceImpl.class);


  /** The resource resolver factory. */
  @Reference
  private ResourceResolverFactory resourceResolverFactory;

  private ResourceResolver resolver;


  /**
   * Activate.
   *
   * @param config the config
   */
  @Activate
  @Modified
  protected final void activate(Configuration config) {}



  /**
   * check if we can get /apps resource, print weather it's null or not
   */
  public String checkApps() {
    logger.info("*************** checkApps");
    Map<String, Object> param = new HashMap<String, Object>();
    param.put(ResourceResolverFactory.SUBSERVICE,"getResourceResolver");
    ResourceResolver resourceResolver = null;
    try
    {
      resourceResolver = resourceResolverFactory.getServiceResourceResolver(param);
      logger.info("*************** resource resolver user id: "+resourceResolver.getUserID());
      Resource appsResource = resourceResolver.getResource("/apps");

      // return appropriate msg
      return appsResource == null
             ? "apps resource is null"
             : "apps resource is NOT null";

    }
    catch (LoginException e)
    {
      logger.error("LoginException",e);
      return e.toString();
    }
    finally
    {
      if(resourceResolver != null && resourceResolver.isLive()){
        resourceResolver.close();
      }
    }

  }
  /**
   * Deactivate.
   */
  @Deactivate
  protected void deactivate() {
  }
}

横幅模型:

package com.aem.sites.models;

import javax.annotation.PostConstruct;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.OSGiService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aem.sites.services.WeatherService;


@Model(adaptables=Resource.class)
public class Banner {

  final static Logger logger = LoggerFactory.getLogger(Banner.class);

  @OSGiService
  private WeatherService weatherService;

  private String msg;

  @PostConstruct
  public void init() {
    msg = weatherService.checkApps();
  }

  public String getMsg() {
    return msg;
  }

}

显示的简单组件消息:

< h1 data-sly-use.banner = com.aem.sites.models.Banner > $ {banner.msg}< / h1>

更新:关于在吊索模型中使用resourceResolver:


最好在单独的服务中保留不使用模型的resource / resourceResolver的逻辑。在您的代码中, Banner#checkTemperatureProperty 应该在服务中,而不是模型本身。

It's better to keep logic, that does no use the model's resource/resourceResolver, in a separate service. In your code, Banner#checkTemperatureProperty should be in a service and not in the model itself.

这是我个人的观点,在这里没有对与错:

This my personal opinion and there is no right or wrong here:

您总是可以通过在吊索模型中注入resourceResolver或通过注入a资源或请求,然后从资源/请求中获取解析器。无论哪种情况,您都将获得与请求用户具有相同权限的resourceResolver,这是组件的首选。例如,如果您需要从同一页面上的不同组件或通常从/ content中获取资源,这就是方法。

You can always get a resourceResolver in a sling model by injecting it OR by injecting a resource or a request then getting the resolver from the resource/request. In either case, you'll get a resourceResolver that has the same permissions as the requesting user, which is preferred for components. for example, if you need to get a resource from a different component on the same page or in /content in general, this is the way to go.

如果在您需要执行操作的用例中,请求用户或匿名用户没有足够的权限来执行操作,也不希望为其授予权限,则可以通过具有足够权限的系统用户来获得resourceResolver。例如,您想从/ apps读取一些属性,或者您想启动工作流程...等等。在这种情况下,将代码保留在服务中而不是模型本身要更有条理,并且可以概括化它,以便您可以在其他模型中重复使用它。

If you have a use case where you need perform actions the requesting user or an anonymous user does not have sufficient permissions to do nor do you want to give them permissions for, you can get a resourceResolver via system user that has sufficient permissions. for example, you want to read some property from /apps or you want to kick off a workflow... etc. In this case, it's a bit more organized to keep this code in a service rather than the model itself, and maybe generalize it so that you can reuse it in other models.

这篇关于AEM 6.3-Service中的ResourceResolverFactory为null,并在Sling Model类中抛出LoginException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆