II有一个servlet(例如,“ localhost:4502 / bin / my-servlet-here”),在这里我需要访问OSGI服务。
我已经尝试了一些在线上看到的东西,但是我无法从servlet获得对OSGI服务的访问/引用。
关于如何实现的任何想法?
在下面的代码servlet类中,我在IDE(IntelliJ)中进行调试,并且它在“ ServiceReference reference”开头的行中挂起/未响应。
谢谢
我的servlet类
package com.myhost.core.servlets;
import com.myhost.core.services.MyService;
import javax.annotation.Resource;
import javax.inject.Inject;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import org.apache.felix.scr.annotations.sling.SlingServlet;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
@SlingServlet(paths = "/bin/myservlet", methods = "GET", metatype = true)
public class MyServlet extends SlingAllMethodsServlet {
@Resource(name="BundleContext")
private BundleContext context;
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
ServiceReference reference = context.getServiceReference(MyService.class.getName());
MyService service = (MyService)context.getService(reference);
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=UTF-8");
// the code the populates the JSON variable has been taken out
printWriter.write(jsonObject.toString());
}
我的服务等级
package com.myhost.core.services;
public interface MyService {
String getPassword(String type);
}
我的服务类实现
package com.myhost.core.services.impl;
import com.myhost.core.services.MyService;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.commons.osgi.PropertiesUtil;
import java.util.Map;
@Service
@Component(metatype = true, label = "My Service Implementation")
public class MyServiceImpl implements MyService {
@Property(label = "property1")
private static final String Property1 = "com.myhost.core.services.MyService.property1";
private String property1;
@Property(label = "property2")
private static final String Property2 = "com.myhost.core.services.MyService.property2";
private String property2;
@Activate
protected void activate(Map<String, Object> properties) {
this.property1 = PropertiesUtil.toString(properties.get(Property1), null);
this.property2 = PropertiesUtil.toString(properties.get(Property2), null);
}
@Override
public String getProperty(int temp) {
switch (temp) {
case 1:
return property1;
case 2:
return property2;
default:
return "";
}
}
}
答案 0 :(得分:2)
答案 1 :(得分:2)
如果您使用的是AEM 6.3或更高版本,我建议您使用OSGI声明式服务。如果少于,则为SCR注释。 以下是使用声明性服务的代码段,我在6.3及更高版本中使用了
//My sevlet Practice Servlet
@Component(service=Servlet.class,
property={
Constants.SERVICE_DESCRIPTION + "=Practice Servlet",
"sling.servlet.methods=" + HttpConstants.METHOD_GET,
"sling.servlet.paths="+ "/bin/practice"
})
public class PracticeServlet extends SlingSafeMethodsServlet{
private Logger log = LoggerFactory.getLogger(this.getClass());
@Reference
private PracticeService pracService;
我在上面的servlet中使用的服务类:PracticeService.java
public interface PracticeService {
public void printLogs(String Name);
}
我的服务实现类:PracticeServiceImpl.java,它实现上述服务类。
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import aemdemo.core.service.PracticeService;
@Component(service=PracticeService.class)
public class PracticeServiceImpl implements PracticeService{
private Logger log = LoggerFactory.getLogger(this.getClass());
@Override
public void printLogs(String name) {
log.debug("Inside service!!!!!"+name);
}
}
答案 2 :(得分:0)
您应该使用@Reference,但不能使用Felix SCR。改用本机OSGi注释。
import org.osgi.service.component.annotations.*;
@Reference
private ResourceResolverFactory factory;
felix注释现在处于维护模式...理想情况下,整个项目将在没有felix scr的情况下运行。 有关更多说明,请参见http://www.nateyolles.com/blog/2017/05/osgi-declarative-services-annotations-in-aem。
答案 3 :(得分:0)
由于您使用的是AEM 6.4.x,因此建议您使用OSGi declarative service annotations而不是其他社区成员建议的Felix SCR注释。
要使用这些注释,我已经通过替换Felix SCR注释将您的代码转换为使用OSGi注释。
MyService.java
package org.redquark.aem.extensions.core.services;
public interface MyService {
/**
* This method returns the entered password into a hash equivalent with some
* properties passed by the user
*
* @param type
* @return {@link String}
*/
String getPassword(String type);
}
MyServiceImpl.java
package org.redquark.aem.extensions.core.services.impl;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.metatype.annotations.Designate;
import org.redquark.aem.extensions.core.config.MyConfiguration;
import org.redquark.aem.extensions.core.services.MyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(service = MyService.class,
property = {
"label=My Service Implementation"
}
)
@Designate(ocd = MyConfiguration.class)
public class MyServiceImpl implements MyService {
private final Logger log = LoggerFactory.getLogger(this.getClass());
// Two properties to be read
private String propertyOne;
private String propertyTwo;
@Activate
protected void activate(MyConfiguration config) {
// Reading properties from the configuration
propertyOne = config.getPropertyOne();
propertyTwo = config.getPropertyTwo();
}
@Override
public String getPassword(String type) {
// MD5 equivalent of password string
String passwordHash = null;
try {
type = type + propertyOne + propertyTwo;
log.info("Resulant password: " + type);
// Convert string to bytes - this is for the sample implementation (for show casing)
byte[] passwordByte = type.getBytes("UTF-8");
// Getting instance of MessageDigest
MessageDigest md = MessageDigest.getInstance("MD5");
// Convert bytes array to hash using MD5 algorithm
byte[] digest = md.digest(passwordByte);
passwordHash = new String(digest);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return passwordHash;
}
}
我们正在通过服务实现的Activate方法读取自定义属性。
SCR属性注释为您提供了很大的自由度。您可以在类顶部进行注释(使用 @Properties 注释作为带有嵌套的 @Property 注释的容器),也可以将各个常量值注释为属性。您可以在OSGI Web控制台中使它们可见(从技术上讲,您正在为它们创建一个元类型),也可以将它们标记为私有(未创建元类型)。
对于OSGI注释,这是不同的。
元类型属性在标记为 @ObjectClassDefinition 的专用配置类中处理。他们不能是私人的。 视为私有的属性将附加到 @Component 批注。它们无法再更改。
因此,要处理这些属性,我们将使用@ObjectClassDesfinition注释创建一个单独的接口,并且每个属性均使用@AttributeType注释进行注释。
MyConfiguration.java
package org.redquark.aem.extensions.core.config;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.AttributeType;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
@ObjectClassDefinition(name = "My Configuration",
description = "This configuration will be used to read the value of properties.")
public @interface MyConfiguration {
@AttributeDefinition(name = "Property One", description = "Read property one", type = AttributeType.STRING)
public String getPropertyOne() default "Property One";
@AttributeDefinition(name = "Property Two", description = "Read property two", type = AttributeType.STRING)
public String getPropertyTwo() default "Property Two";
}
现在,终于有了您的servlet-
MyServlet.java
package org.redquark.aem.extensions.core.servlets;
import java.io.IOException;
import javax.servlet.Servlet;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.redquark.aem.extensions.core.services.MyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(service = Servlet.class, property = { "sling.servlet.methods=" + HttpConstants.METHOD_GET,
"sling.servlet.paths=" + "/bin/myservlet" })
public class MyServlet extends SlingAllMethodsServlet {
// Generated serialVersionUID
private static final long serialVersionUID = -8720724011172847122L;
private final Logger log = LoggerFactory.getLogger(this.getClass());
// Injecting reference of your service - No need to use BundleContext
@Reference
private MyService myService;
@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) {
try {
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=UTF-8");
// Calling the method implementation from your service
String password = myService.getPassword("Sample Type");
log.info("Writing password to the browser...");
response.getWriter().write(password);
} catch (IOException e) {
e.printStackTrace();
}
}
}
出于演示目的,我自由创建了等效于密码的MD5哈希,该密码也取决于自定义属性(propertyOne和propertyTwo)。您可以在此处编写JSON实现。
您可以在此处使用Scheduler服务检查另一个示例-https://aem.redquark.org/2018/10/day-13-schedulers-in-aem.html
我希望这有助于解决您的问题。 编码愉快!干杯!