<?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: Category eclipse</title>
    <link>http://blog.extremepattern.com/articles/category/eclipse</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>enjoy</description>
    <item>
      <title>xmarsh 0.1.3 release</title>
      <description>&lt;p&gt;新增 ssl 服務支援。&lt;/p&gt;


	&lt;p&gt;細節參閱&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://xmarsh.openfoundry.org/"&gt;xmarsh@openfoundry&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://extremepattern.com/XMARSH"&gt;extremepattern.com/XMARSH&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sat, 10 Feb 2007 19:12:00 -0800</pubDate>
      <guid isPermaLink="false">urn:uuid:80aa3d20-1aa0-42be-9b28-04bf2ac282e1</guid>
      <author>LIN</author>
      <link>http://blog.extremepattern.com/articles/2007/02/10/xmarsh-0-1-3-release</link>
      <category>eclipse</category>
      <category>java</category>
    </item>
    <item>
      <title>xmarsh 0.1.0 release</title>
      <description>&lt;p&gt;xmarsh 提供 eclipse 平台的附加工具 plugins，0.1.0
版提供建立憑證中心測試功能。&lt;/p&gt;


	&lt;p&gt;細節參閱&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://xmarsh.openfoundry.org/"&gt;xmarsh@openfoundry&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://extremepattern.com/XMARSH"&gt;extremepattern.com/XMARSH&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Tue, 30 Jan 2007 03:30:00 -0800</pubDate>
      <guid isPermaLink="false">urn:uuid:b86918a6-b497-428c-a09f-feb59b2ca154</guid>
      <author>LIN</author>
      <link>http://blog.extremepattern.com/articles/2007/01/30/xmarsh-0-1-0-release</link>
      <category>eclipse</category>
    </item>
    <item>
      <title>Show Me the OSGi Bundles </title>
      <description>&lt;h3&gt;源起&lt;/h3&gt;


	&lt;p&gt;想要從 web/http 介面看到 OSGi 平台的 bundle 狀態，進一步也可以做 start/stop/update 控制。&lt;/p&gt;


	&lt;h3&gt;&lt;span class="caps"&gt;JMX&lt;/span&gt; ?&lt;/h3&gt;


	&lt;p&gt;一開始想到 &lt;span class="caps"&gt;JMX&lt;/span&gt; 轉 Http 的實做，既然用 equinox 就考慮 Resource Monitoring 專案看看，
該案目前還在孕育階段，牽涉的包非常多，請參閱下面連結。&lt;/p&gt;


	&lt;p&gt;http://www.eclipse.org/equinox/incubator/monitoring/index.php&lt;/p&gt;


	&lt;p&gt;目前只有小小意圖，簡單的秀出狀態的話，要調整並安裝這些包似乎太麻煩。於是自己來個小包，用 spring-osgi/spring-mvc 支援，實做一個 controller ，支援注入 BundleContext 的 BundleContextAware 介面，然後簡單秀出來看。&lt;/p&gt;


	&lt;p&gt;為了重複使用方便，將之前練習的 haha.hello.jetty 改為 haha.osgi.jetty。&lt;/p&gt;


	&lt;h3&gt;haha.osgi.webconsole&lt;/h3&gt;


	&lt;p&gt;使用之前做的 haha.osgi.jetty.HttpService ，只要設定根目錄，會自行找到 
&lt;span class="caps"&gt;WEN&lt;/span&gt;-INF/web.xml 並啟動需要的 controller，所以這裡不寫註冊 Servlet 的程式，
改回原來習慣的 web.xml 方式。&lt;/p&gt;


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


&lt;pre&gt;
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: haha.osgi.webconsole
Bundle-SymbolicName: haha.osgi.webconsole
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" 
Require-Bundle: haha.remix.spring,
 haha.osgi.jetty
&lt;/pre&gt;

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


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

&amp;lt;bean id="register" 
  class="haha.osgi.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="webapp" /&amp;gt;
  &amp;lt;property name="contextPath" value="/osgi" /&amp;gt;
&amp;lt;/bean&amp;gt;
&lt;/pre&gt;

webapp/WEB-INF/web.xml
&lt;pre&gt;
&amp;lt;servlet&amp;gt;
&amp;lt;servlet-name&amp;gt;status&amp;lt;/servlet-name&amp;gt;
&amp;lt;servlet-class&amp;gt;
  org.springframework.web.servlet.DispatcherServlet
&amp;lt;/servlet-class&amp;gt;
&amp;lt;init-param&amp;gt;
  &amp;lt;param-name&amp;gt;contextClass&amp;lt;/param-name&amp;gt;
  &amp;lt;param-value&amp;gt;
  org.springframework.osgi.context.support.OsgiWebApplicationContext
  &amp;lt;/param-value&amp;gt;
&amp;lt;/init-param&amp;gt;
&amp;lt;load-on-startup&amp;gt;1&amp;lt;/load-on-startup&amp;gt;
&amp;lt;/servlet&amp;gt;

&amp;lt;servlet-mapping&amp;gt;
&amp;lt;servlet-name&amp;gt;status&amp;lt;/servlet-name&amp;gt;
&amp;lt;url-pattern&amp;gt;/status&amp;lt;/url-pattern&amp;gt;
&amp;lt;/servlet-mapping&amp;gt;
&lt;/pre&gt;

	&lt;p&gt;webapp/WEB-INF/status-servlet.xml&lt;/p&gt;


&lt;pre&gt;
&amp;lt;bean
  class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"&amp;gt;
&amp;lt;property name="mappings"&amp;gt;
  &amp;lt;value&amp;gt;/*=statusController&amp;lt;/value&amp;gt;
&amp;lt;/property&amp;gt;
&amp;lt;/bean&amp;gt;
&amp;lt;bean id="statusController" 
  class="haha.osgi.webconsole.StatusController"&amp;gt;
&amp;lt;/bean&amp;gt;
&lt;/pre&gt;

	&lt;p&gt;haha.osgi.webconsole.StatusController&lt;/p&gt;


&lt;pre&gt;
public class StatusController extends AbstractController 
  implements BundleContextAware {

  @Override
  protected ModelAndView handleRequestInternal(HttpServletRequest req,
    HttpServletResponse res) throws Exception {

  res.setContentType("text/plain; charset=UTF-8");
  PrintWriter out = res.getWriter();
  Bundle[] bundles = bundleContext.getBundles();
  for (Bundle bundle : bundles) {
    int state = bundle.getState();
    String status = "ACTIVE";
    switch (state) {
      case Bundle.INSTALLED:
        status = "INSTALLED";
        break;
    [SKIP]
&lt;/pre&gt;

	&lt;h3&gt;結果&lt;/h3&gt;


	&lt;p&gt;http://127.0.0.1/osgi/status&lt;/p&gt;


&lt;pre&gt;
Bundle 0 / system.bundle / ACTIVE
Bundle 1 / haha.remix.jetty / ACTIVE
Bundle 2 / haha.remix.spring / ACTIVE
Bundle 5 / org.apache.commons.logging / ACTIVE
Bundle 6 / org.eclipse.equinox.common / ACTIVE
Bundle 7 / org.eclipse.osgi.services / ACTIVE
Bundle 14 / haha.osgi.webconsole / ACTIVE
Bundle 16 / org.eclipse.equinox.log / ACTIVE
Bundle 18 / haha.osgi.jetty / ACTIVE
&lt;/pre&gt;

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


	&lt;ol&gt;
	&lt;li&gt;簡單使用 BundleContext 秀狀態，可以進一步做控制的實做&lt;/li&gt;
		&lt;li&gt;這類應用要設定三個 &lt;span class="caps"&gt;XML&lt;/span&gt; 似乎過於複雜，沒用到 spring-mvc 的功能，只是簡單 controller 其實可以用 servlet 代替。&lt;/li&gt;
		&lt;li&gt;轉換成 &lt;span class="caps"&gt;JSTL&lt;/span&gt; view 發生找不到 tld 的問題，變成要自帶 &lt;span class="caps"&gt;WEB&lt;/span&gt;-INF/c.tld 並改 uri 的做法，採用 eclipse buddy 機制也許也有用。主要是找不到放在別的包中的 &lt;span class="caps"&gt;META&lt;/span&gt;-INF 目錄下的 c.tld 等檔案。&lt;/li&gt;
	&lt;/ol&gt;</description>
      <pubDate>Thu, 23 Nov 2006 23:27:00 -0800</pubDate>
      <guid isPermaLink="false">urn:uuid:c93a989f-8918-4614-8d8c-f69acd017b4a</guid>
      <author>LIN</author>
      <link>http://blog.extremepattern.com/articles/2006/11/23/show-me-the-osgi-bundles</link>
      <category>eclipse</category>
      <category>java</category>
    </item>
    <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>
    <item>
      <title>Hello Xfire Web Services and OSGi</title>
      <description>&lt;h3&gt;源起&lt;/h3&gt;


	&lt;p&gt;除了直接接到 spring &lt;span class="caps"&gt;MVC&lt;/span&gt; 來展現網頁之外，對於外部的程式也需要連結，這裡測試
XFire 掛 Spring 的模式來做。&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://docs.codehaus.org/display/XFIRE/Home"&gt;XFire&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://static.springframework.org/spring/docs/2.0.x/reference/remoting.html"&gt;Chapter 17.5. Web Services&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://docs.codehaus.org/display/XFIRE/Spring"&gt;XFire Spring support&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://docs.codehaus.org/display/XFIRE/JSR+181+Annotations"&gt;XFire &lt;span class="caps"&gt;JSR 181&lt;/span&gt; Annotations&lt;/a&gt;&lt;/p&gt;


	&lt;h3&gt;做法&lt;/h3&gt;


	&lt;p&gt;xfire 有支援  spring ，他將一些預設定義放在 classpath:org/codehaus/xfire/spring/xfire.xml，
不過它是 spring 1.x 版本，即使設定 eclipse buddy 機制取得這個檔，也需要修改，索性直接將這個
檔放到需要的包中。&lt;/p&gt;


	&lt;p&gt;主要實做下面幾包 bundle 來用。&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;haha.remix.xfire&lt;/li&gt;
		&lt;li&gt;haha.hello.ws.userdao&lt;/li&gt;
		&lt;li&gt;haha.hello.ws.client&lt;/li&gt;
	&lt;/ol&gt;


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


	&lt;p&gt;這是個大轉包，沒有加程式，只是改 &lt;span class="caps"&gt;MANIFEST&lt;/span&gt;.MF 來協助。&lt;/p&gt;


&lt;pre&gt;
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: haha.remix.xfire
Bundle-SymbolicName: haha.remix.xfire
Bundle-Version: 1.0.0
Bundle-Activator: haha.remix.xfire.Activator
Bundle-Localization: plugin
Import-Package: javax.servlet;version="2.4.0",
 javax.servlet.http;version="2.4.0",
 org.apache.commons.logging,
 org.osgi.framework;version="1.3.0" 
Bundle-ClassPath: lib/wstx-asl-3.1.0.jar,
 lib/stax-api-1.0.1.jar,
 lib/wsdl4j-1.5.2.jar,
 lib/xfire-all-1.2.2.jar,
 lib/xfire-jsr181-api-1.0-M1.jar,
 .,
 lib/activation-1.1.jar,
 lib/jdom-1.0.jar,
 lib/XmlSchema-1.1.jar
Export-Package: com.ctc.wstx.stax,
 javax.jws,
 javax.xml.stream,
 org.apache.ws.commons.schema,
 org.codehaus.stax2,
........[skip]
Require-Bundle: org.apache.commons.httpclient;resolution:=optional,
 org.apache.commons.codec;resolution:=optional,
 haha.remix.spring;resolution:=optional
&lt;/pre&gt;

	&lt;p&gt;這裡需注意 require bundle 都是選擇性的，那是因為有些特定需求要到客端包要求的時候，才會需要，
也不一定會有這些客端包，所以一直掛著讓他一定要這個附屬包也說不過去，所以用選擇性掛上。&lt;/p&gt;


	&lt;h3&gt; haha.hello.ws.userdao&lt;/h3&gt;


	&lt;p&gt;&lt;span class="caps"&gt;META&lt;/span&gt;-INF/spring/bean.xml&lt;/p&gt;


&lt;pre&gt;
&amp;lt;osgi:reference id="httpService" 
  interface="org.osgi.service.http.HttpService"/&amp;gt;

&amp;lt;bean name="servletRegister" 
   class="haha.hello.ws.userdao.ServletRegister" init-method="init"&amp;gt;
      &amp;lt;property name="httpService" ref="httpService"/&amp;gt;
&amp;lt;/bean&amp;gt;
&lt;/pre&gt;

	&lt;p&gt;haha.hello.ws.userdao.ServletRegister 負責啟動 &lt;span class="caps"&gt;WEB&lt;/span&gt;-INF/xx.xml 與註冊服務到 
osgi:reference 的 org.osgi.service.http.HttpService&lt;/p&gt;


&lt;pre&gt;
System.setProperty("javax.xml.stream.XMLInputFactory",
  "com.ctc.wstx.stax.WstxInputFactory");
System.setProperty("javax.xml.stream.XMLOutputFactory",
  "com.ctc.wstx.stax.WstxOutputFactory");
System.setProperty("javax.xml.stream.XMLEventFactory",
  "com.ctc.wstx.stax.WstxEventFactory");

DispatcherServlet servlet = new DispatcherServlet();
servlet.setNamespace("hello-servlet");

OsgiWebApplicationContext owac = new OsgiWebApplicationContext();
servlet.setContextClass(owac.getClass());
httpService.registerServlet("/services", servlet, null ,null);
&lt;/pre&gt;

	&lt;p&gt;&lt;span class="caps"&gt;WEB&lt;/span&gt;-INF/hello-servlet.xml&lt;/p&gt;


&lt;pre&gt;
&amp;lt;import resource="xfire.xml"/&amp;gt;
&amp;lt;osgi:reference id="userDao" 
     interface="haha.hello.jpa.userdao.UserDao"/&amp;gt;

&amp;lt;bean name="helloImpl" class="haha.hello.ws.userdao.HelloImpl"&amp;gt;     
   &amp;lt;property name="userDao" ref="userDao"/&amp;gt;
&amp;lt;/bean&amp;gt;

&amp;lt;bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"&amp;gt;
   &amp;lt;property name="mappings"&amp;gt;
            &amp;lt;value&amp;gt;/hello=wsController&amp;lt;/value&amp;gt;
   &amp;lt;/property&amp;gt;
&amp;lt;/bean&amp;gt;

&amp;lt;bean id="wsController" 
      class="org.codehaus.xfire.spring.remoting.XFireExporter"&amp;gt;
        &amp;lt;property name="serviceFactory"&amp;gt;
            &amp;lt;ref bean="xfire.annotationServiceFactory"/&amp;gt;
        &amp;lt;/property&amp;gt;
        &amp;lt;property name="xfire"&amp;gt;
            &amp;lt;ref bean="xfire"/&amp;gt;
        &amp;lt;/property&amp;gt;
        &amp;lt;property name="serviceBean"&amp;gt;
            &amp;lt;ref bean="helloImpl"/&amp;gt;
        &amp;lt;/property&amp;gt;
&amp;lt;/bean&amp;gt;
&lt;/pre&gt;

	&lt;p&gt;&lt;span class="caps"&gt;WEB&lt;/span&gt;-INF/xfire.xml 取自 xfire classpath:org/codehaus/xfire/spring/xfire.xml
修改一下 singleton 設定而已。&lt;/p&gt;


	&lt;p&gt;這一包主要將 haha.hello.ws.userdao.Hello 放到 WebServic 去。&lt;/p&gt;


	&lt;p&gt;haha.hello.ws.userdao.Hello&lt;/p&gt;


&lt;pre&gt;
package haha.hello.ws.userdao;

import javax.jws.WebMethod;
import javax.jws.WebResult;
import javax.jws.WebService;

@WebService(name = "HelloService",  targetNamespace = "http://www.openuri.org/2004/04/HelloWorld")
public interface Hello {
  @WebMethod
  @WebResult
  String getName();
}
&lt;/pre&gt;

	&lt;p&gt;haha.hello.ws.userdao.HelloImpl 會注入 osgi:reference 的 haha.hello.jpa.userdao.UserDao 來用。&lt;/p&gt;


&lt;pre&gt;
package haha.hello.ws.userdao;

import haha.hello.jpa.userdao.UserDao;
import javax.jws.WebService;

@WebService(endpointInterface = "haha.hello.ws.userdao.Hello")
public class HelloImpl implements Hello {

 private UserDao userDao;

 private String name = "foo";

 public String getName() {
   return name + userDao.loadUsers().size();
 }
....[SKIP].....
&lt;/pre&gt;

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


&lt;pre&gt;
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: haha.hello.ws.userdao
Bundle-SymbolicName: haha.hello.ws.userdao
Bundle-Version: 1.0.0
Bundle-Activator: haha.hello.ws.userdao.Activator
Bundle-Localization: plugin
Import-Package: com.ctc.wstx.stax,
 javax.jws,
 javax.servlet;version="2.4.0",
 javax.servlet.http;version="2.4.0",
 org.osgi.framework;version="1.3.0",
 org.osgi.service.http;version="1.2.0",
 org.springframework.osgi.context.support
Require-Bundle: haha.remix.spring,
 org.eclipse.equinox.http.jetty,
 haha.hello.jpa.userdao,
 haha.remix.xfire
Export-Package: haha.hello.ws.userdao
&lt;/pre&gt;

	&lt;p&gt;啟動後可以直接開瀏覽器到 http://127.0.0.1/services/hello?wsdl 觀察 &lt;span class="caps"&gt;WSDL&lt;/span&gt;。&lt;/p&gt;


	&lt;h3&gt; haha.hello.ws.client&lt;/h3&gt;


	&lt;p&gt;陽春型客戶端，只是取用 getName 輸出看看而已，沒有用到 &lt;span class="caps"&gt;WSDL2JAVA&lt;/span&gt; 來轉成 java。&lt;/p&gt;


&lt;pre&gt;
package haha.hello.ws.client;

import java.net.URL;
import org.codehaus.xfire.client.Client;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class Activator implements BundleActivator {

 public void start(BundleContext context) throws Exception {
    Client client = new Client(
            new URL("http://127.0.0.1/services/hello?wsdl"));
        Object[] results = client.invoke("getName",null);
        System.out.println(results[0]);
 }
...[SKIP]....
&lt;/pre&gt;

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


&lt;pre&gt;
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: haha.hello.ws.client
Bundle-SymbolicName: haha.hello.ws.client
Bundle-Version: 1.0.0
Bundle-Activator: haha.hello.ws.client.Activator
Bundle-Localization: plugin
Import-Package: org.apache.commons.logging,
 org.codehaus.xfire.client,
 org.osgi.framework;version="1.3.0" 
Bundle-ClassPath: .
Require-Bundle: org.apache.commons.httpclient,
 org.apache.commons.codec,
 haha.hello.ws.userdao,
 haha.remix.xfire
&lt;/pre&gt;

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


	&lt;ol&gt;
	&lt;li&gt;越深入企業層面的應用，越發覺既有程式套件之間的相依性很高，之前用一個 classpath 可以找到，
現在轉 OSGi 變成要考慮匯出匯入問題，變的更為複雜，有時現有套件無法滿足，只好直接轉 remix 大包
來實現或是用 eclipse buddy 機制。&lt;/li&gt;
		&lt;li&gt;如果使用 import-package 方式，似乎無法保證某些服務會先啟動，於是將 ws.client 
中設定 Require-Bundle 來讓某些服務先滿足。&lt;/li&gt;
	&lt;/ol&gt;</description>
      <pubDate>Thu, 09 Nov 2006 20:43:00 -0800</pubDate>
      <guid isPermaLink="false">urn:uuid:a1cb7161-113a-4b40-8e5a-cebf27f169fd</guid>
      <author>LIN</author>
      <link>http://blog.extremepattern.com/articles/2006/11/09/hello-xfire-web-services-and-osgi</link>
      <category>eclipse</category>
      <category>java</category>
    </item>
  </channel>
</rss>
