2009-06-16 6 views
4

OSGi 환경에서 실행되는 HttpServlet (즉, OSGi HttpService에 등록 됨)은 작업을 수행하기 위해 일부 OSGi 서비스를 호출하기를 원할 것입니다. 문제는 서블릿 내부에서 이러한 OSGi 서비스에 대한 참조를 얻는 방법입니다.OSGi HttpService에 등록 된 서블릿에서 OSGi 서비스 참조를 얻는 방법은 무엇입니까?

한 가지 방법은 OSGi HttpService를이 같은 등록되고있는 HttpServlet을 인스턴스에 종속성을 주입하는 것입니다 :이 비은 OSGi 환경에서부터 유효한 방법 인 경우

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

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

잘 모르겠어요 서블릿 라이프 사이클은 웹 컨테이너에 의해 관리되므로 나중에 작성된 서블릿 인스턴스에 서비스 참조가 삽입되지 않습니다.

PAX Web을 OSGi HttpService의 구현으로 사용할 때이를 해결할 수있는 또 다른 방법이 있습니다. PAX Web은 OSGi BundleContext를 특수 속성 "osgi-bundlecontext"로 ServletContext로 내 보냅니다. 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를의 구체적인 구현을 묶는다. 이 문제에 대한 다른 (그리고 아마도 더 좋은) 해결책을 알고 있습니까?

답변

2

만약 당신이 보여준 것처럼 서비스에 대한 의존성에 대한 세터를 사용한다면, OSGi 밖에서도 작동 할 수 있습니다. 다른 의존성 주입 메커니즘을 사용해야합니다. 아무 것도 없으면 JNDI 조회 또는 서블릿 컨텍스트를 사용하여 서블릿을 초기화하는 서브 클래스를 제공 할 수 있습니다.

public class MyServlet_AdapterForMissingDI extends MyServlet{ 

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

} 

점은 setFooService을 삽입 할 수 DI 기능이있는 경우 그렇지 (여전히이 사건을 지원하려는) 경우, 당신은 단지 다른 곳은 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은 서비스 조회 및 바인딩을 수행합니다.

+0

Pax Web Extender 화이트 보드는 서블릿 등록을위한 훌륭한 솔루션입니다. 감사. 그러나 주된 문제는 OSGi 환경에서 서블릿 내에서 서비스 참조를 얻는 방법입니다. JNDI 조회를 언급했지만 OSGi 서비스 레지스트리에 액세스하는 올바른 방법이라고 생각하지 않습니다. 그런 다음 서블릿 컨텍스트에 대해서도 언급했지만 OSGi HttpService 인터페이스를 사용하여 서블릿 컨텍스트에 객체를 배치하는 방법은 없습니다. 내가 틀렸다면 나를 바로 잡아주세요. –

+0

SCR을 사용하여 OSGi 내부에서 종속성을 확보 할 수 있습니다. 핵심은 종속성을 주입하는 데 사용하는 setter (setFooService 등)가 있다는 것입니다. 이 설정 도구는 BundleActivator (예를 들어 사용자가 보여준 것과 같은), SCR, iPojo, Spring 등에서 수동으로 호출 할 수 있습니다. 이러한 서비스는 서비스 추적을 처리합니다. – Thilo

+0

다시 말하면, 서블릿 자체가 의존성을 찾지 않는다는 점입니다. 그것들을 어디 론가 주사하게하는 세터가 있습니다. OSGi 내부에서는 JNDI를 사용하지 않을 것입니다. 이것은 다른 DI 메커니즘이없는 경우 동일한 서블릿을 OSGi 외부에서 작동시키는 방법의 예입니다. – Thilo

-1

서비스를 몇 가지 객체에 삽입 할 수 있습니다.이 객체는 서블릿에 의해 질의됩니다.

+0

문제가 한 단계 만 이동합니다. 서블릿 내에서이 객체에 대한 참조를 얻는 방법은 무엇입니까? –

2

예전 게시물 일 수 있고 이미 답변을 얻었을 수도 있습니다 .. 펠릭스 또는 OSGi 컨테이너를 시작하고 있습니까?이 경우 번들 컨텍스트를 서블릿 컨텍스트의 특성으로 설정할 수 있습니다.

PAX에서 http 서비스를 사용하는 데있어 잘못된 점이 무엇입니까? 궁극적으로 스레드 관리 및 기타 측면은이 http 서비스를 실행하는 서블릿 컨테이너에서 처리됩니다.