1)我试图在SlingModel类中注入ResourceResolverFactory,如下所示:
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()。我创建了如下所示的系统用户:
我还配置了Mapper服务修正案,如下所示:
捆绑包的符号名称如下所示:
ResourceResolverFactor注入在Sling Model类中抛出LoginException,这是错误:
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时,它会抛出空指针异常。
下面给出了有问题的类,方法checkTemperatureProperty()第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(第一类)中使用。但它既没有效果。
我已经完成了各种教程以及在stackoverflow上提出的类似问题。其中一些人在这里:
ResourceResolverFactory getServiceResourceResolver throws Exception in AEM 6.1
ResourceResolverFactory and SlingRepository null in Service class
ResourceResolverFactory is NULL (Adobe Experience Manager AEM)
并完全遵循它但无法找到解决方案。任何帮助表示赞赏。
提前致谢。
答案 0 :(得分:1)
我看到您正在使用OSGI声明性服务(DS)
一些事情:
maven-bundle-plugin
依赖项必须是3.2.0
或更高版本org.osgi.service.component.annotations
中使用注释,不包org.apache.felix.scr.annotations.Reference
中的SCR注释在你的气象服务中,我发现你使用的是SCR @Reference
而不是OSGI的@Reference
在吊索模型中
您应该使用OSGI服务注入器来获取服务:@OSGiService
尽管使用@Inject
工作得很好,但是特定的注入器对于可读性和性能更好,尽管不显着,因为我们只使用特定的注射器
以下是使用您的部分代码的服务示例:
气象服务界面:
package com.aem.sites.services;
public interface WeatherService
{
public String checkApps();
}
天气服务impl:
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
应该在服务中而不在模型本身中。
这是我个人的观点,这里没有对错:
您始终可以通过注入资源或请求,然后从资源/请求中获取解析程序来获取sling模型中的resourceResolver。在任何一种情况下,您都将获得与请求用户具有相同权限的resourceResolver,这是组件的首选。例如,如果您需要从同一页面上的/或内容中的其他组件获取资源,这是可行的方法。
如果您有需要执行操作的用例,请求用户或匿名用户没有足够的权限来执行操作,也不想授予他们权限,您可以通过具有足够权限的系统用户获取resourceResolver 。例如,你想从/ apps中读取一些属性,或者你想开始工作流......等等。在这种情况下,将这些代码保存在服务中而不是模型本身更有条理,并且可能会推广这样你就可以在其他模型中重复使用它。