OSGI httpservice에 등록 된 서블릿에서 OSGI 서비스 참조를 얻는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1002813

문제

OSGI 환경에서 실행되는 httpservlet (즉, OSGI에 등록 된 것은 당연한 것 같습니다. httpservice) 일부 OSGI 서비스를 호출하여 작업을 수행하고 싶을 것입니다. 문제는 서블릿 내에서 이러한 OSGI 서비스에 대한 참조를 얻는 방법입니다.

한 가지 방법은 다음과 같이 OSGI httpservice에 등록되는 httpservlet 인스턴스에 종속성을 주입하는 것입니다.

MyServlet servlet = new MyServlet();
servlet.setFooService(fooService);

httpService.registerServlet("/myservlet", servlet, initparams, context);

비 OSGI 환경에서 Servlet 수명주기는 웹 컨테이너에 의해 관리되므로 나중에 생성 된 서블릿 인스턴스에 대해 서비스 참조가 주입되지 않기 때문에 이것이 유효한 접근법인지 확실하지 않습니다.

사용할 때 이것을 해결하는 또 다른 방법이 있습니다 PAX 웹 OSGI httpservice의 구현으로. PAX 웹은 OSGI BundleContext를 ServletContext로 내보내며 "OSGI-BUNDLECONTEXT"로 특수한 속성으로 내 보냅니다. 그런 다음 BundleContext를 사용하여 필요한 서비스 참조를 얻을 수 있습니다.

public void init(ServletConfig servletConfig) throws ServletException {

    ServletContext context = servletConfig.getServletContext()
    BundleContext bundleContext = 
        (BundleContext) context.getAttribute("osgi-bundlecontext");

    ServiceReference serviceRef =
         bundleContext.getServiceReference("com.foo.FooService")
}

그러나이 접근법은 다소 추악하고 OSGI httpservice의 구체적인 구현과 연결됩니다. 이 문제에 대한 다른 (그리고 아마도 더 나은) 솔루션을 알고 있습니까?

도움이 되었습니까?

해결책

보여준 것처럼 서비스에 대한 의존성을 위해 세터를 사용하는 경우 OSGI 외부에서도 작동 할 수 있습니다. 다른 종속성 주입 메커니즘을 사용하면됩니다. 없으면 JNDI 조회 또는 서블릿 컨텍스트를 사용하여 서블릿을 초기화하는 서브 클래스를 제공 할 수 있습니다.

public class MyServlet_AdapterForMissingDI extends MyServlet{

    public void init(ServletConfig config){
        setFooService(getItFromSomewhere());
    }

}

요점은 주입 할 수있는 DI 기능이 있다면 setFooService, 당신은 OSGI와 다른 곳에서 동일한 서블릿을 사용할 수 있습니다.이 경우를지지하지 않으려면 어댑터를 제공합니다.

관련 메모에서 Felix SCR을 확인하여 객체의 종속성을 구성하고 httpservice와 함께 서블릿을 연결하는 것을 관리하는 Pax Web Extender Whiteboard를 확인하십시오.

구체적으로, SCR과 화이트 보드가 없으면 나중에 fooservice를 사용할 수 없거나 서블릿 후에 httpservice가 시작되는 경우에 대해 생각해야합니다. 이 경우 서플릿은 번들이 쓰레기 수집되는 것을 방지하는 죽은 서비스에 대한 참조를 가지거나 서블릿이 httpservice에 등록되지 않습니다.

업데이트: 다음은 서블릿 중 하나에 사용하는 SCR 디스크립터입니다. SCR은 서블릿 인스턴스화, 수명주기, 등록 (화이트 보드를 통해) 및 종속성을 처리합니다. 서블릿에는 OSGI 별 코드가 없습니다. 더 이상 BundleActivator가 필요하지 않습니다 (SCR은 모든 서비스 등록) :

<component name="oracle.statusServlet" >
<implementation class="mypackage.DataSourceStatusServlet"/>
<property name="service.description" value="Oracle DataSource status servlet" />
<property name="alias" value="/OracleDataSourceStatus" />
<property name="servlet-name" value="Oracle DataSource status servlet" />
<service>
    <provide interface="javax.servlet.Servlet" />
</service>
    <reference name="DATASOURCES" 
            interface="javax.sql.DataSource"
            cardinality="0..n" policy="dynamic" 
            bind="bindDataSource" unbind="unbindDataSource"/>

</component>

서블릿의 종속성은 reference 꼬리표. SCR은 서비스 조회 및 바인딩을 수행합니다.

다른 팁

오래된 게시물 일 수도 있고 이미 답을 얻었을 것입니다. Felix 또는 OSGI 컨테이너 직접 시작하고 있습니까? 이 경우 번들 컨텍스트를 서블릿 컨텍스트의 속성으로 설정할 수 있습니다.

PAX의 HTTP 서비스를 사용하는 데 무엇이 잘못 되었습니까? 궁극적으로 스레드 관리 및 기타 측면은이 HTTP 서비스를 실행하는 서블릿 컨테이너에 의해 처리됩니다.

서비스를 일부 객체에 주입 할 수 있으며, 그런 다음 서블릿에 의해 쿼리됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top