>

II에는 OSGI 서비스에 액세스해야하는 서블릿 (예 : localhost : 4502/bin/my-servlet-here)이 있습니다.

온라인에서 본 몇 가지를 시도했지만 서블릿에서 OSGI 서비스에 대한 액세스/참조를 얻을 수 없습니다.

어떻게 할 수 있는지에 대한 아이디어가 있습니까?

아래의 코드 서블릿 클래스에서 IDE (IntelliJ)에서 디버깅 중이고 "ServiceReference reference"로 시작하는 행에서 응답하지 않거나 응답하지 않습니다

감사합니다

<시간>

서블릿 클래스

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 "";
        }
    }
}

  • 답변 # 1

    @Reference 를 사용할 수 있습니다  주석과 felix가 귀하를 위해 주석을 삽입합니다.

    //MyServlet.class
    .
    .
    @Reference
    MyService service;
    .
    .
    
    

    다음은 참고 용 예제입니다.

  • 답변 # 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;
    
    

    서비스 클래스 : 위에서 서블릿에서 사용한 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);
            }
        }
    
    

  • 답변 # 3

    @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을 참조하십시오.

  • 답변 # 4

    AEM 6.4.x, 다른 커뮤니티 회원이 제안한대로 Felix SCR 주석 대신 OSGi 선언적 서비스 주석을 사용하는 것이 좋습니다.

    해당 주석을 사용하기 위해 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;
        }
    }
    
    

    서비스 구현 활성화 방법에서 사용자 정의 속성을 읽고 있습니다.

    SCR 속성 주석은 많은 자유를줍니다.@Property주석이있는 컨테이너로@Properties주석을 사용하여 클래스 위에 주석을 달 수 있으며 개별 상수 값에 주석을 달 수 있습니다. OSGI 웹 콘솔 (기술적으로 메타 타입을 생성하는 중)에서 볼 수있게하거나 메타 타입이 생성되지 않은 개인으로 표시 할 수 있습니다.

    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";
    }
    
    

    이제 서블릿이 온다-

    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();
            }
        }
    }
    
    

    데모 목적으로, 사용자 정의 속성 (propertyOne 및 propertyTwo)에 따라 암호와 동등한 MD5 해시를 생성 할 수있는 자유를 얻었습니다. 여기에 JSON 구현을 작성할 수 있습니다.

    스케줄러 서비스를 통해 다른 예를 확인할 수 있습니다-https://aem.redquark.org/2018/10/day-13-schedulers-in-aem.html

    이 문제를 해결하는 데 도움이되기를 바랍니다. 행복한 코딩! 건배!

관련 자료

  • 이전 python - 2D 및 3D 행렬의 dotproduct를 만드는 방법 (각 차원마다 따로 따로 가져옴)
  • 다음 Laravel Eloquent Query Where IN 문