<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Extreme Pattern: Spring-driven or OSGi-standard HttpService </title>
    <link>http://blog.extremepattern.com/articles/2006/11/21/spring-driven-or-osgi-standard-httpservice</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>enjoy</description>
    <item>
      <title>Spring-driven or OSGi-standard HttpService </title>
      <description>&lt;h3&gt;源起&lt;/h3&gt;


	&lt;p&gt;原來的 OSGi HtppService 是個相當簡潔的介面，不提供太多細部的設定考量，也就是說整個 HttpService 的某些特質取決於底層的實做預設值，並不能在註冊時加以調整。&lt;/p&gt;


	&lt;p&gt;舉 welcome file 的例子來說，不同實做，出現的行為是 404/500 都不確定，太粗的介面提供小型裝置的容易實現性，但是對習慣開發 server-side 的開發者而言，實在不方便。&lt;/p&gt;


	&lt;p&gt;&lt;img src="/files/spring_osgi.png" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;equinox 用 jetty 當 servlet 2.4 實做，jetty 5 是個成熟的實做，許多企業級應用都可找到，equinox 採用 ProxyServlet 轉接方式，來轉出符合 OSGi HttpService 的介面。&lt;/p&gt;


	&lt;p&gt;這裡不去修改這個 ProxyServlet 機制，而是動手另外實做類似 org.eclipse.equinox.http.jetty 的 Spring-driven HttpService
功能，同時轉用 jetty 6.1 來測試，這裡用 haha.remix.jetty 來包一大包，另外用 haha.hello.jetty 來啟動 jetty server，用 haha.hello.httpdoc 來註冊 http://localhost/。&lt;/p&gt;


	&lt;h3&gt;haha.remix.jetty&lt;/h3&gt;


	&lt;p&gt;不需啟動，基本上是個 lib 為主的 bundle。&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;META&lt;/span&gt;-IMF/MANIFEST.MF&lt;/p&gt;


&lt;pre&gt;
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Jetty Plug-in
Bundle-SymbolicName: haha.remix.jetty
Bundle-Version: 6.1.0
Bundle-Localization: plugin
Import-Package: org.osgi.framework;version="1.3.0" 
Bundle-ClassPath: .,
 lib/jetty-6.1.0pre2.jar,
 lib/jetty-util-6.1.0pre2.jar,
 lib/servlet-api-2.5-6.1.0pre2.jar
Export-Package: javax.servlet;version="2.5.0",
 javax.servlet.http;version="2.5.0",
 javax.servlet.resources;version="2.5.0",
 org.mortbay.component,
 org.mortbay.io,
 org.mortbay.io.bio,....[SKIP]
&lt;/pre&gt;

	&lt;h3&gt; haha.hello.jetty&lt;/h3&gt;


	&lt;p&gt;&lt;span class="caps"&gt;META&lt;/span&gt;-IMF/MANIFEST.MF&lt;/p&gt;


&lt;pre&gt;
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: haha.hello.jetty
Bundle-SymbolicName: haha.hello.jetty
Bundle-Version: 1.0.0
Bundle-Localization: plugin
Import-Package: org.osgi.framework;version="1.3.0" 
Require-Bundle: haha.remix.spring,
 haha.remix.jetty
Bundle-ClassPath: .
Export-Package: haha.hello.jetty
&lt;/pre&gt;

	&lt;p&gt;將 jetty 用 osgi-service 註冊到 OSGi 環境去。&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;MEAT&lt;/span&gt;-INF/spring/jetty-beans.xml&lt;/p&gt;


&lt;pre&gt;
&amp;lt;bean id="httpServiceImpl" 
  class="haha.hello.jetty.HttpServiceImpl" 
 init-method="init" destroy-method="destroy"&amp;gt;
  &amp;lt;property name="port" value="80" /&amp;gt;
  &amp;lt;property name="debugEnable" value="true" /&amp;gt;
&amp;lt;/bean&amp;gt;
&amp;lt;osgi:service ref="httpServiceImpl" interface="haha.hello.jetty.HttpService"/&amp;gt;
&lt;/pre&gt;

	&lt;p&gt;haha.hello.jetty.HttpService&lt;/p&gt;


&lt;pre&gt;
public interface HttpService {
  void addWebApp(URL fileURL, String contextPath);
}
&lt;/pre&gt;

	&lt;h3&gt;haha.hello.httpdoc&lt;/h3&gt;


	&lt;p&gt;這是比較麻煩的地方，主要是轉換檔案位置的問題，這裡用到 org.eclipse.equinox.common 的支援，
使用 org.eclipse.core.runtime.FileLocator 來轉檔案的位置給 haha.hello.jetty 知道。&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;META&lt;/span&gt;-IMF/MANIFEST.MF&lt;/p&gt;


&lt;pre&gt;
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: haha.hello.httpdoc
Bundle-SymbolicName: haha.hello.httpdoc
Bundle-Version: 1.0.0
Bundle-Localization: plugin
Import-Package: javax.servlet;version="2.4.0",
 javax.servlet.http;version="2.4.0",
 org.osgi.framework;version="1.3.0",
 org.osgi.service.component;version="1.0.0",
 org.osgi.service.log;version="1.3.0",
 org.springframework.osgi.context
Require-Bundle: org.eclipse.equinox.common,
 haha.hello.jetty
&lt;/pre&gt;

	&lt;p&gt;將目錄所在用 osgi-reference 註冊到 jetty 環境去。&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;MEAT&lt;/span&gt;-INF/spring/httpdoc-beans.xml&lt;/p&gt;


&lt;pre&gt;
&amp;lt;osgi:reference id="httpService" 
  interface="haha.hello.jetty.HttpService" /&amp;gt;

&amp;lt;bean id="register" 
  class="haha.hello.httpdoc.Register" init-method="init" 
  destroy-method="destroy"&amp;gt;
  &amp;lt;property name="httpService" ref="httpService" /&amp;gt;
&amp;lt;/bean&amp;gt;
&lt;/pre&gt;

	&lt;p&gt;haha.hello.httpdoc.Register 須實做 BundleContextAware 讓 Spring-OSGi
注入 BundleContext 來用。&lt;/p&gt;


&lt;pre&gt;
public class Register implements BundleContextAware{

 private HttpService httpService;
 private BundleContext bundleContext;

 public void init() throws IOException{
  Bundle bundle = bundleContext.getBundle();
  URL entry = bundle.getEntry("htdoc");
  URL dir = FileLocator.toFileURL(entry);
  httpService.addWebApp(dir, "/");
 }
&lt;/pre&gt;

	&lt;p&gt;結果可以在 http://localhost/ 看到 haha.hello.httpdoc bundle 中的 htdoc 目錄。&lt;/p&gt;


	&lt;h3&gt;Refactoring&lt;/h3&gt;


	&lt;p&gt;為了減少重複寫這些註冊 Register 以及依賴  org.eclipse.equinox.common 與 org.springframework.osgi.context.BundleContextAware，將這個責任移到 haha.hello.jetty 去，客端只要負責實體化並注入 HttpService 即可，如下面情形。&lt;/p&gt;


&lt;pre&gt;
&amp;lt;bean id="register" 
    class="haha.hello.jetty.Register" init-method="init" destroy-method="destroy"&amp;gt;
    &amp;lt;property name="httpService" ref="httpService" /&amp;gt;
    &amp;lt;property name="webappDir" value="htdoc" /&amp;gt;
    &amp;lt;property name="contextPath" value="/project" /&amp;gt;
&amp;lt;/bean&amp;gt;    
&lt;/pre&gt;

	&lt;h3&gt;觀察&lt;/h3&gt;


	&lt;ol&gt;
	&lt;li&gt;簡單測試目錄註冊方式與整個 Spring-driven HttpService 的可用性，如果 htdoc 包成 jar 的話，還需要再進一步修改與考量。&lt;/li&gt;
		&lt;li&gt;spring-driven jetty 也可以支援 osgi-standard http service interface，不過這裡沒有實做。&lt;/li&gt;
		&lt;li&gt;目前只有實做簡單的註冊，接下來可以考慮測看看 jsp/servlet/spring-mvc 等機制。&lt;/li&gt;
		&lt;li&gt;目前註冊端需要依賴 org.eclipse.equinox.common 與 org.springframework.osgi.context.BundleContextAware [參照 Refactoring 一節，移該責任到 jetty 啟動包去]&lt;/li&gt;
		&lt;li&gt;捨棄 OSGi 的 HttpService 代表已偏離標準的約定，這樣一來就需考量與其他 HttpService 實做相容議題。&lt;/li&gt;
		&lt;li&gt;大量採用 remix 的做法會形成大者恆大的現象，幾個巨大 bundle 會讓更新下載時間拉長，
只是部份更新卻需要下載數 MB，這點副作用要考慮。&lt;/li&gt;
	&lt;/ol&gt;</description>
      <pubDate>Tue, 21 Nov 2006 20:01:00 -0800</pubDate>
      <guid isPermaLink="false">urn:uuid:b9569c1a-6b45-4a99-9616-6ab27a54f884</guid>
      <author>LIN</author>
      <link>http://blog.extremepattern.com/articles/2006/11/21/spring-driven-or-osgi-standard-httpservice</link>
      <category>eclipse</category>
      <category>java</category>
    </item>
  </channel>
</rss>
