DWR service bundle
Oct
源起
前日將 dwr 2.0 與 domain object 兩種東西包在一起成為 HelloDwr bundle 來測試,這樣做當然非常方便,完全不用擔心 classloader 的問題,不過延展性就差一點,這次希望可以分離一個 DWR 2.0 service bundle 出來用,一來讓需要這個服務的 domain object bundle 方便取用,二來也可以不用每個 domain object bundle 都帶上自己的 dwr.jar。
之前的做法可以參考 HelloDwr bundle

dwr 自己載入 domain object 的方式與 OSGi 的期望的方式有所不同,為求支援這種 ContextClassLoader 機制,這裡 採取尚未成為 OSGi 標準的 Eclipse-BuddyPolicy 與 Eclipse-RegisterBuddy 做法,這種做法可以解決這類問題,後遺症是 這意味著這種 bundle 只能在 org.eclipse.osgi.jar 下執行,其他 OSGi 環境將不會支援。
http://eclipsezone.com/articles/eclipse-vms/
equinox osig 執行環境可以到下面連結下載,最好是 equinox osgi 3.3M3 或是比較新的 Integration Builds 來用,這樣才可以支援到 servlet 2.4。
http://download.eclipse.org/eclipse/equinox/
haha.dwrds
src/haha/dwrds/DwrDservice.java
輸出的服務介面,讓客端註冊那些物件要遠端存取。
package haha.dwrds;
public interface DwrDservice {
public void register(String[] classNameArray);
}
MANIFEST.MF
除了輸出服務之外,還要表明 Eclipse-BuddyPolicy 說願意交朋友。
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: haha.dwrds Bundle-SymbolicName: haha.dwrds 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.service.component;version="1.0.0", org.osgi.service.http;version="1.2.0", org.osgi.service.log;version="1.3.0" Bundle-ClassPath: lib/dwr.jar,. Service-Component: OSGI-INF/service.xml Export-Package: haha.dwrds, org.directwebremoting, org.directwebremoting.annotations Eclipse-BuddyPolicy: registered
OSGI-INF/service.xml
這裡除了輸出服務之外,還綁上一些服務。
<?xml version="1.0" encoding="UTF-8"?>
<component name="dwrDserviceBind">
<implementation class="haha.dwrds.DwrDserviceImpl"/>
<service>
<provide interface="haha.dwrds.DwrDservice"/>
</service>
<reference name="LOG" interface="org.osgi.service.log.LogService"
cardinality="1..1" bind="setLog" unbind="unsetLog" policy="static"/>
<reference name="HTTP" interface="org.osgi.service.http.HttpService"
cardinality="1..1" policy="dynamic" bind="setHttp" unbind="unsetHttp"/>
</component>
src/haha/dwrds/DwrDserviceImpl.java 除了實做註冊之外,主要提供綁定的功能, 至於動態註冊物件到 dwr 的方式是採用修改 init-param 的土法,然後在將這個 DwrServlet 註冊到 HttpService 去。
為了測試方便,這個 bundle 自己內建兩個物件,會先在注入到 dwr 中使用。
haha.hello
src/haha/FooBean.java
package haha.hello;
import org.directwebremoting.annotations.RemoteMethod;
import org.directwebremoting.annotations.RemoteProxy;
@RemoteProxy
public class FooBean {
@RemoteMethod
public int getFoo(){
return 999;
}
}
MANIFEST.MF
除了匯入 haha.dwrds 服務之外,還要表明 Eclipse-RegisterBuddy 說和 haha.dwrds 是麻吉。
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: haha.hello Bundle-SymbolicName: haha.hello Bundle-Version: 1.0.0 Bundle-Localization: plugin Import-Package: haha.dwrds, org.directwebremoting.annotations, org.osgi.service.component;version="1.0.0", org.osgi.service.log;version="1.3.0" Service-Component: OSGI-INF/reference.xml Eclipse-RegisterBuddy: haha.dwrds
OSGI-INF/reference.xml
<?xml version="1.0" encoding="UTF-8"?>
<component name="haha.hello.Component">
<implementation class="haha.hello.Component"/>
<reference name="LOG" interface="org.osgi.service.log.LogService"
cardinality="1..1" bind="setLog" unbind="unsetLog" policy="static"/>
<reference name="DWR" interface="haha.dwrds.DwrDservice"
cardinality="1..1" policy="static" bind="setDwr" unbind="unsetDwr" />
</component>
src/haha/hello/Component.java
protected void activate(ComponentContext context) {
log.log(LogService.LOG_INFO, "### active hello dwr");
dwrDservice.register(
new String[]{ FooBean.class.getCanonicalName(),
FooBean2.class.getCanonicalName()});
}
測試 test
開瀏覽器到 http://localhost/dwr 應該可以看到四個物件,試著在 haha.hello 專案中對遠端輸出物件新增,刪除或是改名看看。
下載 download
dwrservice_bundle_20061031.zip
觀察
- 這些牽涉到 ContextClassLoader 議題的現有 lib 要轉包 bundle,做法到底是分開還是合在一起客有利弊,如果很單純的應用,也許直接包還比較方便。
- 也許過不久會有類似的 bundle 出來,就不用自己包。
- eclipse 為了實際應用,開發出很多 OSGi 還沒定義到的功能,會不會轉 R5 規格,有待觀察,問題是規格過之前,這類問題還是需要解決方案,eclipse 這方面已有不錯的應用。