2009年11月26日 星期四

Ext JEE Bridge 使用方式備忘-Ext.Direct事件處理

使用Ext JEE Bridge 時, Server端可以透過DirectEventPublisher, 來觸發Browser端Ext.Direct的事件.
觸發事件的方法如下:
  1. DirectEventPublisher.publish('事件名稱',參數1,參數2,....);//發佈事件給自己這個session的Browser端
  2. DirectEventPublisher.publishToAll('事件名稱',參數1,參數2,....);//發佈事件給所有事件接收者的Browser端
  3. DirectEventPublisher.publishToGroup('群組名稱','事件名稱',參數1,參數2,....)//發佈事件給特定群組事件接收者的Browser端
  4. DirectEventPublisher.publishToGroups(new String[]{'群組名稱1','群組名稱2',...},'事件名稱',參數1,參數2,....)//發佈事件給特定群組事件接收者的Browser端
那麼怎樣才能成為接收者端呢?
基本上只要載入DirectProvider時, 撰寫URL如下

src="{Router對應的URL}?event={是否接收Ext.Direct}&eventGroup={事件群組名稱(多個群組則以逗點隔開)}"

中的event參數為 on | true | yes | y ,就會成為Ext.Direct事件的接收者.
會收到的事件則是依照evantGroup來區分, 若是沒有指定evantGroup, 就只能收到publish與publishToAll的事件

2009年11月25日 星期三

Ext JEE Bridge 開發日記4

開發完 remoting 與 form post兩個部分後,
就只剩下polling的部分.
但是看過官網的範例並參考其他實作的作法後, 感想如下:
  1. 官網的作法感覺太過原始, 簡單到只是Browser端不斷送出Request到一個URL, 直接寫一個JSP/Servlet就解決了, 感覺不出像remoting與form post那樣的好處.
  2. DirectJNgine的做法又只不過是不斷呼叫action類別中的method. 跟用一個timer不斷的用Ext.Direct的rpc呼叫有啥不同?
總之我覺得實作polling的基本server-side功能根本是多餘的.
反而用polling來實作一些更高階的功能, 如從Server端fireEvent給特定的Browser端之類的, 還比較實用.
因此我就在Ext JEE Bridge中加入了DirectEventPublisher功能.
開發者可以透過DirectEventPublisher觸發目前Browser端或是所有的Browser端的Ext.Direct事件.
基本概念很簡單, Browser端的GET Request可以取得PollingAPI並訂閱DirectEventPublisher的事件. 然後用POST Request對DirectEventPublisher進行Polling取得DirectEventPublisher publish給Browser端的事件.
最後Server內的程式只要DirectEventPublisher.publish('eventName',arg1,arg2,arg3,...);
目前ejeeb-1.0已具備此功能.

2009年11月19日 星期四

Ext JEE Bridge 使用方式備忘-複雜結構回傳值

在Ext JEE Bridge中要使用複雜結構的回傳值
有三種基本方式:
  1. 使用JavaBean 或 List當回傳值
  2. 使用Map或List當回傳值
  3. 使用ejeeb.util.JSONBridge
第一種做法必須要先定義好回傳用的JavaBean類別, 並且在該類別上加上@JsonSerialize的Annotation, 這樣一來回傳的JavaBean會自動被轉成對應的Javascript物件. 複數個JavaBean也可以直接裝在java.util.List中回傳即可, 也支援多層的巢狀結構.
第二種作法跟第一種類似只是把JavaBean用java.util.Map來代替.
第三種作法必須先使Action類別繼承ejeeb.util.JSONBridge類別, 然後就可以使用下面的方式回傳:

public Object test(){

    return obj(
        attr("testId",1),
        attr("testName","JsonBridgeTest"),
        attr("testData",arr(
            1,
            2,
            "haha",
            obj(
                attr("name","par"),
                attr("isTest",true)
            )
    );
}

Browser端的JS則會取得
{
    "testId":1,
    "testName":"JsonBridgeTest",
    "testData":[
        1,
        2,
        "haha",
        {"name":"par","isTest":true}
    ]
}

三種方式都可以混用, 也都可以用來作多層巢狀的複雜結構回傳值.
雖然可以在一個回傳值中用三種寫法組裝回傳物件, 但是我只推薦第一種作法, 這樣在設計階段比較完整描述出元件.
後面兩種比較適合用來製作雛形或快速開發小型應用系統.

2009年11月18日 星期三

使用DirectJNigne時遇到的問題

然知道Java Open Source有DWR可以使用, 但是Ext.Direct發佈的消息還是讓我相當興奮.
竟DWR只是讓Browser端JS透過RPC的方式與Server端的Java物件互動, 並沒有與ExtJS做到完整的整合.
於當時我時間都花在寫直接整合Hibernate的應用元件池框架(aop, ioc 容器)的Framework, 就只好到官網論壇看看有沒有閒人寫了Java based的Ext.Direct實作, 正好看到這篇文章.
用了上面所列的Java based implementation 後, 選了DirectJNigne1.0(DJN)作為首次使用Ext.Direct正式開發的框架.
經過完整的開發Cycle後, 我覺得DJN有很多問題
  1. 設定過於繁複 : 這點其實還好, 雖然設定不算簡明, 但是文件上的描述至少夠完整.
  2. Batch Request的多執行緒處理有很大的瑕疵 : 這點就很讓人不爽, 用多執行緒來執行Batch Request可能會造成程式執行的順序性錯亂問題, 原本在Ext.Direct的Batch Request可以解決remote function呼叫因為網路關係可能造成的順序性錯亂在這裡就被破壞(雖然常規作法應該是callback後才執行下個指令). 除了順序性外, 也無法利用ThreadLocal方式取得目前的Request, Session, Application等物件內的資訊, 所以每次都不得不把多執行緒的功能都關閉.
  3. 與其他Framework間整合問題 : 由於只支援Non-managed POJO, 所以要整合別的Framework的code變成要寫在Action類別裡面, 而不能直接將其他Framework內的managed component視為Action. (至少我在使用者指引裡面沒看到解決方式)
  4. 性能問題? : 我在開發實蠻常看到OutOfMemory的問題似乎跟YUICompressor有關?關於DJN使用的gson.jar在我看了這篇文章後, 覺得有點失望.
  5. Generic Type使用的問題 : 這點跟gson脫不了關係, 由於gson在處理 Generic Type需要額外的動作, 導致DJN無法支援Generic Type的Json傳遞. (至少1.0版是如此, 之後就不知道了)

Ext JEE Bridge 使用方式備忘-取得request, session, application

在某些狀況下 Server端Action類別可能會需要JSP上的request, session, application物件, 來實現某些目的.
在使用Ext JEE Bridge的狀態下Server端Action類別只會獲得Client端傳來的參數.
如果要取得request, session, application可以透過
  1. ejeeb.router.Router的getRequest()取得request
  2. ejeeb.router.DefaultRouter的getRequest(), getSession()與getApplication來取得request, session, application.
  3. 在類別(介面)中提供標記為ejeeb.router.info.annotation.RequestInfoSetter, ejeeb.router.info.annotation.SessionInfoSetter或 ejeeb.router.info.annotation.ApplicationInfoSetter的方法, 由Router主動注入給action物件(方法的傳入參數型態必須是HttpServletRequest, HttpSession, ServletContext 或是實作ejeeb.router.info.RequestInfoProvider, ejeeb.router.info.SessionInfoProvider, 或ejeeb.router.info.ApplicationInfoProvider的任何類別)

Ext JEE Bridge 使用方式備忘-基本設定

Ext JEE Bridge 下載位置

環境需求 : Java 1.5
  1. 將ejeeb.jar與相依的Jackson, Apache的IO與FileUpload都複製到網站lib目錄下.
  2. 在web.xml加入ejeeb.router.DefaultRouter(或自訂的Router類別)的Servlet Configuration, 之後以DefaultRouter為例. 為此之外, 尚需要在Configuration中加入actions與encoding(optional)兩個init-parameter. 參數actions的值為需要成為DirectAction的non-managed POJO class 或 ejb interface 的全名, 有多個類別(介面)時, 以逗點隔開. 參數encoding則是輸出入編碼, 預設為utf-8.
  3. 在需要成為DirectAction的non-managed POJO class 或 ejb interface 上加上DirectAction與DirectMethod的Annotation.
  4. 打開要使用Ext.Direct的網頁, 並在extjs library include之後, 加入

    or

  5. 大功告成, 現在可以直在網頁上呼叫Server端的Action.

2009年11月17日 星期二

Ext JEE Bridge 開發日記3

經過一番努力, Ext.Direct的功能都完成了

下載 : ejeeb-0.92.zip
  1. RPC功能(可支援複雜結構參數, 與複雜結構回傳值, 當然也有支援batch)
  2. 支援non-managed java class
  3. 支援ejb
  4. 可繼承Router類別, override initApi(...)來支援其他Framework
  5. Form Post & FileUpload的處理
  6. 透過Router或DefaultRouter類別取得目前的request, session, application
剩下的就是ExtJS 3.0額外支援的功能:
  1. Direct Style JsonWriter對應處理
  2. REST Style JsonWriter對應處理