jBrick 開發平台

星期一, 3月 13, 2006

使用者註冊的範例

在此再舉一個使用者註冊的完整範例,由於登入的範例是由UI說明至Server端的程式碼,在這個例子中,將由Server端先說明,最後再說明UI的程式,在此一範例中將會介紹到Server端要如何設計,使得Server端的程式可以再被重覆使用(由不同的流程設定,重覆使用Server程式)。

  • Operation Flow
    使用者輸入個人資料後,系統會先檢查帳號是否重覆,若重覆則傳回重覆的錯誤訊息;否則系統新增使用者帳號與群組的關係,最後新增使用者基本資料至使用者的表格內。
  • Table Schema

    • mbr_user

    • mbr_usergrp

  • Server Command

    • 查詢使用者資訊
      原始碼:

      package com.hclife.brm;

      import java.sql.Connection;
      import com.ecity.cmd.QueryCommand;
      import com.ecity.model.Model;
      import com.hclife.cfg.HCLIFE;

      public class QueryUserInfo extends QueryCommand
      {
      public QueryUserInfo()
      {
      super("HCLIFE");
      }

      public QueryUserInfo(Connection con)
      {
      super(con);
      setAutoCloseConnection(false);
      }

      public void generateSQL(Model model)
      {
      String strSQL = "";

      strSQL= "SELECT '' AS chk, userid, usertype, username, password, " +
      " mobilephone, tel1, tel1ext, tel2, " +
      " tel2ext, email, fax, addr, " +
      " activeflg, cmt, ref1, ref2, " +
      " ref3, ref4, ref5, createdtm " +
      " FROM " + HCLIFE.MBR_USER +
      " WHERE userid = ':USERID'" +
      " AND username = ':USERNAME'" +
      " AND username LIKE '%:USERNAME%'" +
      " AND activeflg = ':STATUS'" +
      " AND usertype = ':USERTYPE'";

      addSQL(getTarget(model,"USER_INFO"),
      strSQL,
      DATA_MODEL);
      }
      }

      說明:
      • 此程式為查詢使用者資訊的程式,所以需要繼承QueryCommand這個類別,使得開發者所以的SQL語法執行後可以傳回查詢結果。
      • 在Constructor有二個型式(Overloding),一個不傳值,另一個是傳入一個java.sql.Connection的類別,當不傳值時,會依據Constructor中的資料庫設定(在此一例子中,會使用HCLIFE這個資料庫的設定),以這種方式來產生的Command在執行完之後就會自動Commit或Rollback。當使用Workflow來作Flow Control時,因Workflow Engine會有Transaction的管理,故會用到第二個Constructor,使用的Connection會由Workfloe Engine傳入。
      • 為了能使此Command可以讓其他的程式共用,所以我們在SELECT的欄位列中會寫入所有的欄位名稱,故只要是查詢mbr_user這個表格的程式,均可共用此一Command。
      • 在FROM之後我並不直接寫Table的名稱,而是利用HCLIFE這個Class中所定義的常數,此種做法是日後系統如果移植到其他環境(例如不同的Schema或不用的Table命名)時,不需將所有的Command重新改寫,只要修改 HCLIFE這個Class即可。
      • 在設定SQL的查詢條件(即WHERE的條件)中,是以":" + 變數的方式來表示所要取得Model中的變數,在本例子中userid = ':USERID' 即會取後Model中的USERID來置換變數內容,假設Model中的USERID為ecity則此一段的SQL會被取代為userid = 'ecity',其餘的寫法均與一般的SQL的寫法一樣,字串會在變數前後加'來表示。
      • 在組完所要執行的SQL Statement之後,需要透過addSQL這個method來將此一SQL加入此一Command中的執行佇列,一個Command可以依序執行多個SQL Statement,但為了能提高共用程度,我並不建議使用多個SQL Statement,而是利用Workflow來設定所要執行的Command流程。因執行結果會被放入Model中,所以在addSQL時需要指定要放入Model中時所要存放的Key值,在此我們用了getTarget(model, "USER_INFO")這個method,當前台(Client)的程式有指定所要放置的Key值時,會使用前台所設定的,若無則用USER_INFO這個Key值來當成預設值。


    • 新增使用者與群組對應
      原始碼:

      package com.hclife.brm;

      import java.sql.Connection;

      import com.ecity.cmd.UpdateCommand;

      import com.ecity.model.Model;
      import com.hclife.cfg.*;


      public class InsertUserGroup extends UpdateCommand
      {
      public InsertUserGroup()
      {
      super("HCLIFE");
      }

      public InsertUserGroup (Connection con)
      {
      super(con);
      setAutoCloseConnection(false);
      }

      public void generateSQL(Model model)
      {
      String strSQL = "";

      strSQL = "INSERT INTO " + HCLIFE.MBR_USERGRP + "(usergid, userid) " +
      " VALUES(':USERGID', ':USERID')";

      addSQL(strSQL);
      }
      }

      說明:
      • 此範例為新增一筆使用者與使用者群組關係的程式,因為異動到資料庫中的資料,所以需要繼承UpdateCommand這個類別,只要是需要異動到資料(例如:Insert / Update / Delete)均需繼承這一個類別。
      • 在異動資料庫的程式並不會傳回結果集(ResultSet),我們不需指定所要存放的Key值,在範例中與Query不同處是在addSQL這個method,在UpdateCommand中只需傳入所要執行的SQL Statement即可。


    • 新增使用者
      原始碼:

      package com.hclife.brm;

      import java.sql.*;

      import com.ecity.cmd.*;
      import com.ecity.model.*;

      import com.hclife.cfg.*;

      public class InsertUser extends UpdateCommand
      {
      public InsertUser()
      {
      super("HCLIFE");
      }

      public InsertUser(Connection con)
      {
      super(con);
      setAutoCloseConnection(false);
      }

      public void generateSQL(Model model)
      {
      String strSQL = "";

      strSQL = "INSERT INTO mbr_user(userid, usertype, username, password, " +
      " nickname, mobilephone, tel1, " +
      " tel1ext, tel2, tel2ext, email, " +
      " fax, addr, activeflg, cmt, " +
      " ref1, ref2, ref3, ref4, " +
      " ref5, createdtm) " +
      " VALUES(':USERID', :USERTYPE, ':USERNAME', ':PASSWORD', " +
      " ':NICKNAME', ':MOBILEPHONE', ':TEL1', " +
      " ':TEL1EXT', ':TEL2', ':TEL2EXT', ':EMAIL', " +
      " ':FAX', ':ADDR', :'ACTIVEFLG', ':CMT', " +
      " ':REF1', ':REF2', ':REF3', ':REF4', " +
      " ':REF5', :CREATEDTM)";

      addSQL(strSQL);
      }
      }

      說明:
      • 此一範例程式為新增一筆使用者資料到mbr_user這個表格中。

  • UI Form

  • Workflow Config

星期三, 2月 08, 2006

JSP版本系統開發流程



我們現在舉一個登入系統的畫面及其開發流程來做為一個簡單的範例說明,使用者輸入使用者名稱及密碼後,按下登入的按鈕,在Client端將會先檢查使用者帳號和密碼是否有輸入,若否則顯示錯誤訊息,並要使用者重新輸入。檢查之後會將內容送往Server,執行LOGIN這個流程的設定,若登入成功,則畫面將轉入系統的操作畫面,否則仍停留在登入畫面,並顯示錯誤訊息。

在範例內讀者將會學會下列幾項能力:

  • 運用jBrick所提供的Taglib及JavaScript來設計畫面。

  • 編輯流程所要執行的程序。

  • 編寫程序中存取資料庫的程式碼。

  • 處理查詢資料後的結果。

  • 依處理後的結果做頁面的轉換。


1. JSP畫面的開發
由於整個JSP原始檔還包含元件排列位置及美工圖片,在以下說明僅節錄部份程式碼說明,完整程式碼請讀者自行下載。
  • 宣告所要使用的JavaScript

    <ecity:script function="validator"/>

    在jbrick有提供基本的Validator或Event,當要引用這些Function時要透過Script的Tag來引用,function所傳的參數就是所要引用的JavaScript的檔名,這些檔案都會放在function這個目錄下。


  • 放置一個Form的Tag

    <ecity:Form id="MAIN"
    name="MAIN"
    sourcefilename="/login/login.jsp"
    targetcomponent=""
    executecommand="LOGIN_CHECK">

    </ecity:Form>

    在HTML中當UI的資料要傳至Server去時,要用form的tag來將所要傳送的資料欄位包起來,在jbrick中因為需要額外再傳送一些資訊,所以提供了Form的tag lib來替代原本HTML中所提供的form。
    • name與id:設定這個Form Tag的name和id以使JavaScript可以取得這個Form的Object。

    • executeCommand:設定當使用者按下submit按鈕時,在Application Server上所要執行的流程名稱。

    • targetComponent:如果此一執行的流程會將查詢結果往Client送時,設定送回來後所要承接資料的元件名稱(可以是一個Group)。

    • sourceFileName:設定此一jsp檔案所在的路徑及檔名。


  • 放置輸入的元件(TextField和Password)
    首先放置一個TextField來供使用者輸入使用者帳號,其程式碼如下:


    <ecity:TextFieldX name="USERID"
    datafield="USERID"
    styleclass="input"
    required="true"
    datatype="Require"
    errormessage="Please Input UserName"/>

    以下為屬性說明:
    • name:設定這個欄位傳至Application Server時,要將值放至那個名稱內。

    • dataField:當這個欄位會接收Application Server回傳回來的結果時,所要讀取的值的名稱。

    • styleClass:當使用CSS來設定畫面上元件的Style時,可用這個參數來設定所要讀取的CSS設定的class。

    • required:設定此一元件是否必須輸入(不可為空白)。

    • dataType:設定一資料的種類,可有datatime、email、phone…等種類,Validator會依據這?的設定來檢查資料的格式。

    • errorMessage:當Validator檢查資料有錯誤時,所要顯示的錯誤訊息。


    再來放置一個Password的元件來供使用者輸入密碼,其程式碼如下:

    <ecity:PasswordX name="PASSWORD"
    datafield="PASSWORD"
    styleclass="input"
    required="true"
    datatype="Require"
    errormessage="Please Input Password"/>

    屬性設定說明如TextField之說明。


  • 放置按鈕
    放置一個按鈕,顯示的標題為”登入”,當使用者按下時會執行Submit。

    <ecity:ButtonX name="submit"
    title="登入"
    styleClass="button"
    inputType="submit"
    onClick="Validator.Validate('MAIN',1,0);"/>

    以下為屬性設定的說明:
    • name:設定這個欄位傳至Application Server時,要將值放至那個名稱內。

    • title:這個按鈕所要顯示的標題內容。

    • styleClass:當使用CSS來設定畫面上元件的Style時,可用這個參數來設定所要讀取的CSS設定的class。

    • inputType設定按鈕的類別,可有button、submit、reset。

    • onClick:當使用者按下按鈕時所要執行的Function(JavaScript的Function名稱)。


    放置一個按鈕,顯示的標題為”取消”,當使用者按下時會將輸入欄位清空。

    <ecity:ButtonX name="reset"
    title="取消"
    styleClass="button"
    inputType="reset"/>

    其屬性說明如"登入"之按鈕。

  • 放置顯示錯誤訊息的元件
    當Server執行登入的程序有問題時,將會回傳錯誤訊息,而這個元件將會把錯誤訊息顯示在畫面上。

    <ecity:LabelX dataField="ERROR_MSG"
    styleClass="error_message"/>

    以上為屬性設定之說明:
    • dataField:當這個欄位會接收Application Server回傳回來的結果時,所要讀取的值的名稱。

    • styleClass:當使用CSS來設定畫面上元件的Style時,可用這個參數來設定所要讀取的CSS設定的class。




2. Workflow Configure的編寫


我們就以上圖的Flow來做為一個登入流程的範例。在流程的第一個節點我們做帳號和密碼的檢查,檢查帳號是否存在,若不存在則回傳"使用者不存在"的錯誤訊息,再來檢查密碼是否正確,若不正確則回傳"密碼錯誤"的錯誤訊息。當這些檢查都通過時,則以使用者所能使用的功能來做使用者選單的初使化。

以下是LOGIN_CHECK.xml的內容

<workflow>
<start-node>LOGIN_CHECK</start-node>
<end-node>DISPATCH_PAGE</end-node>
<resource-bundle>com.hclife</resource-bundle>
<database>HCLIFE</database>

<node>
<name>LOGIN_CHECK</name>
<type>com.jbrick.workflow.DecisionNode</type>
<command>com.hclife.login.LoginCheck</command>
<contain-node>OK~INIT_MENU;NG~DISPATCH_PAGE</contain-node>
</node>

<node>
<name>INIT_MENU</name>
<type>com.jbrick.workflow.ProcessNode</type>
<command>com.hclife.login.InitMenu</command>
<child>DISPATCH_PAGE</child>
</node>

<node>
<name>DISPATCH_PAGE</name>
<type>com.jbrick.workflow.ProcessNode</type>
<command>com.ecity.workflow.PageDispatcher</command>
<child></child>
</node>

<dispatch-page>
<value>OK</value>
<page>/module/mainform.jsp</page>
</dispatch-page>

<dispatch-page>
<value>NG</value>
<page>/login/login.jsp</page>
</dispatch-page>

<session-variable>
<name>USERID</name>
<name>PASSWORD</name>
</session-variable>
</workflow>

以下就設定的內容說明(更詳細之說明會於Workflow的說明中詳述)

  • 流程資訊設定
    設定內容:

    <start-node>LOGIN_CHECK</start-node>
    <end-node>DISPATCH_PAGE</end-node>
    <resource-bundle>com.hclife</resource-bundle>
    <database>HCLIFE</database>

    以下為本段設定之說明:
    • start-node
      設定整個流程的起始節點,此為節點名稱

    • end-node
      設定流程的結束節點,當整個流程有做Transaction Managememt時,當中間節點執行錯誤時,會跳至此節點,然後將整個Transaction Rollback。

    • resource-bundle
      設定Resource所在的目錄(如Database.properties, CommandMapping.properties...等)

    • database
      本流程所要使用的資料庫的資源設定(包含資料庫名稱,使用者帳號,使用者名稱,連接方式...等)


  • 決策節點設定
    節點內容:

    <node>
    <name>LOGIN_CHECK</name>
    <type>com.jbrick.workflow.DecisionNode</type>
    <command>com.hclife.login.LoginCheck</command>
    <contain-node>OK~INIT_MENU;NG~DISPATCH_PAGE</contain-node>
    </node>

    以下為屬性說明:
    • name
      節點名稱,整個流程執行時會由此一名稱取得所要執行的命令

    • type
      節點的類別,有決策節點(DecisionNode),執行節點(ProcessNode),平行執行節點(ParallelNode)。

    • command
      此一節點所要執行的命令(符合ServerCommand介面的Class均可被加入)

    • contain-node
      當此節點為決策節點時,則設定執行的結果之後所要執行的節點,在這個例子中,如果回傳值為OK時則執行INIT_MENU這個節點,如果為NG時,則執行DISPATCH_PAGE這個節點


  • 執行節點設定
    節點內容:

    <node>
    <name>INIT_MENU</name>
    <type>com.jbrick.workflow.ProcessNode</type>
    <command>com.hclife.login.InitMenu</command>
    <child>DISPATCH_PAGE</child>
    </node>

    以下為屬性說明:
    • name
      節點名稱,整個流程執行時會由此一名稱取得所要執行的命令

    • type
      節點的類別,有決策節點(DecisionNode),執行節點(ProcessNode),平行執行節點(ParallelNode)。

    • command
      此一節點所要執行的命令(符合ServerCommand介面的Class均可被加入)

    • child
      此節點執行完後,下一個所要執行的節點名稱


  • 頁面重導設定
    節點內容:

    <dispatch-page>
    <value>OK</value>
    <page>/module/mainform.jsp</page>
    </dispatch-page>

    <dispatch-page>
    <value>NG</value>
    <page>/login/login.jsp</page>
    </dispatch-page>

    以下為屬性說明:
    • value
      檢查執行後的回傳值是否符合這一個節點的設定值,若符合則將頁面導向page所設定的頁面。
      在本範例中,若回傳值為OK時則會導向/module/mainform.jsp

    • page
      所要導向的頁面(包含路徑及檔名)


  • 變數保存設定
    當此一流程執行之後,有某些變數是要被保存下來以供其他頁面使用時,則在此做設定,若無則可忽略此一部份
    節點內容:

    <session-variable>
    <name>USERID</name>
    <name>PASSWORD</name>
    </session-variable>

    說明:
    在本範例中,會將USERID及PASSWORD保存在Session中,以供其他頁面使用。


3.Server Command的編寫
在此舉LoginCheck這個命令為範例(為說明此一介面的Method,將一些流程的內容寫入此一程式碼,在更具彈性的寫法應將判斷使用者存不存在及密碼正不正確編寫在Workflow Configure內)。DatabaseCommand為一個套用Templete Pattern(GoF Design Pattern)的一個類別,在execute的方法中會依續執行beforeExecute, generateSQL, executeSQL, afterExecute四個方法。

package com.hclife.login;

import java.sql.Connection;
import com.hclife.cfg.HCLIFE;
import com.ecity.cmd.QueryCommand;
import com.ecity.model.Model;

public class LoginCheck extends QueryCommand
{
/* 當不使用Workflow Engine所提供的Transaction Management時,
會套用此一建構式 */
public LoginCheck()
{
super("HCLIFE");
}
/* 當使用Workflow Engine所提供的Transaction Management時,
會套用此一建構式,並且將自動結束Connection設定為false,
Workflow Engine會在流程結束時結束Connection */
public LoginCheck(Connection con)
{
super(con);
setAutoCloseConnection(false);
}

/* 檢查使用者帳號是否為空白或空值, 若是則返回此一命令並不往下執行 */
public int beforeExecute(Model model)
{
if(model.getValue("USERID") == null ||
model.getValue("USERID").equals(""))
return RETURN_TO_CLIENT;
return CONTINUE_PROCESS;
}

/* 將所要執行的SQL Statement寫在這一個方法內,
SQL Statement寫法與一邊資料庫的寫法相同, 只是變數名稱會以冒號開頭
DatabaseCommand會將:Variable所對應至model內的值,
來組合SQL Statement, 有加單引號表示為字串類別, 否則為數字 */
public void generateSQL(Model model)
{
String strSQL;

strSQL = "SELECT userid, password FROM " + HCLIFE.MBR_USER +
" WHERE userid = ':USERID'" +
" AND activeflg = 'Y'";

addSQL(getTarget(model,"USER"),
strSQL,
DATA_MODEL);
}

public int afterExecute(Model model)
{
/* 首先檢查執行結果所回傳的資料筆數, 若為0筆則代表使用者並不存在,
此時將回傳錯誤訊息, 並將使用者帳號和密碼清空,
並將回傳值設為NG */
if(model.getRowCount("USER.USERID") == 0)
{
model.setValue("ERROR_MSG","User Name not Exist");
model.setValue("USERID","");
model.setValue("PASSWORD","");
model.setReturnValue("NG");
return CONTINUE_PROCESS;
}
/* 檢查執行結果所回傳的密碼是否與使用者輸入的一致,
若否則代表密碼錯誤,
此時將回傳錯誤訊息, 並將使用者帳號和密碼清空,
並將回傳值設為NG */
if(!model.getValue("USER[0].PASSWORD").toString().equals(model.getValue("PASSWORD").toString()))
{
model.setValue("ERROR_MSG","Password Error");
model.setValue("PASSWORD","");
model.setReturnValue("NG");
return CONTINUE_PROCESS;
}
/* 檢查均無問題, 則將回傳值設定為OK */
model.setReturnValue("OK");
return CONTINUE_PROCESS;
}
}

星期二, 1月 17, 2006

系統架構

架構圖

在上圖中,共分為Client、Application Server和Data Source三層來說明
1.Client:顯示使用者介面作為使用者輸入資料或是顯示資料供使用者瀏覽,另外提供與使用者互動的動作及輸入驗證流程。
2.Application Server:將Client所傳過來的資料經由Controller處理,產生Data Model後建立Server端的處理流程,並由Server Command做存取資料的動作或是處理程序,最後再將資料傳回Client端呈現資料。
3.Data Source:資料保存層,可以用資料庫或是文件的方式呈現。

JSP系統架構

0.在以JavaScript來控制使用者輸入的流程,包含了資料的驗證、資料互動、過瀘…等動作。
1.當使用者按下submit的動作之後,資料會經由HTTP的協定(Post/Get)的方式將Client的資料送到Web Controller。
2.Web Controller將Request中的各個參數值解析後,將值放入Data Model內,以供jBrick運作之用。
3.Web Controller在產生Data Model後,會再依前Client所傳過來之Flow的名稱傳給Workflow Engine來建立整個Flow的節點。
4.Flow從開始節點開始執行,每個節點會產生相對應的Server Command,由Server Command來執行所所要執行的程式碼。
5.在Server Command可以存取資料來源(Database或Document)後加以處理。
6.每個Server Command執行後會將結果傳遞給Workflow Engine來決定下一個要執行的節點。
7.Server Command會將執行結果放至(或更新)Data Model內的數值。
8.Web Controller會將Data Model的內容放至Session中,以利Tag Library可以取得這些結果值。Web Controller會依據整個Flow執行的結果來決定所要導向的頁面,而重導至新的JSP頁面(亦可能是更新原畫面的內容)。

Swing系統架構

0.以Event Listener的方式來控制使用者輸入的流程,包含了資料的驗證、資料互動、過濾…等動作。
1.當使用者所按下的按鈕(或是元件互動),需要與Server互動時,會經由UI Controller來讀取送往Server的參數。
2.UI Controller會將UI上面的UI Component解析,將值放入Data Model內,以供jBrick運作之用。
3.UI Controller在讀取參數設定及產生Data Model之後,會依據設定的參數決定送往Server的Flow Controller。
4.Flow Controller會依Client所傳過來之Flow的名稱傳給Workflow Engine來建立整個Flow的節點。
5.Flow從開始節點開始執行,每個節點會產生相對應的Server Command,由Server Command來執行所所要執行的程式碼。
6.在Server Command可以存取資料來源(Database或Document)後加以處理。
7.每個Server Command執行後會將結果傳遞給Workflow Engine來決定下一個要執行的節點。
8.Server Command會將執行結果放至(或更新)Data Model內的數值。
9.Flow Controller會取後執行後的Data Model。
10.Flow Controller將Data Model經由Stream的方式傳給Client的UI Controller後,由UI Contorller來更新畫面上元件所顯示的值。

星期一, 1月 16, 2006

簡介

前言
目前幾乎所有的Java開發平台都是以MVC的架構為基礎而發展出各種平台,這些平台大都以網頁的應用程式為開發對象,但在企業內部的應用程式除了應用網頁技術來開發外還必須具備著高度的互動性、大量資料的展現、快速的執行效能、具彈性的畫面操作…等特性,jBrick就是在這個前提下所產生的開發平台,然而與目前所有的開發平台最大的不同點是,同時具有Swing和JSP的畫面呈現,透過一個轉換的Channel使得這些畫面可以使用同一份的Server端的程式,可以提高Server端程式的共用性,以節省系統開發及維護的人力資源。

在jBrick的平台中包含了UI元件、資料存取、Workflow Engine…等幾個部份,讓使用者可以如同堆積木一般,將這些元件以組合方式快速開發出應用程式,另外一個特色就是整個平台的設計均是以介面(Interface)在運作,讓開發者除了利用平台所提供的預設元件外,還可以輕易地加入自己的套件,增加系統的擴充性及應用性。

在此舉一個日常生活中的例子來說明jBrick的架構,我們可以將整個jBrick想像成一個人體構造,當我們的手(Tag Library)遇到熱水壺時,感覺神經元(Java Script)會將”燙”的感覺傳導到大腦(Workflow Engine)後,大腦會產生訊息(Server Command),並傳入脊髓神經(Model)後,告訴手(Tag Library)的骨骼肌要作收縮的動作。

開發動機與目的
jBrick是為了要能夠快速開發以Java為平台的應用程式而發展出來的一套框架(Framework)。
以下為jBrick所訂定的目標:
1.完全符合MVC架構的jBrick,以使得UI / Business Logic / Data Developer可以完全分開獨立工作,且各個角色可以分開開發,不會有相互影響到專案的進度。在元件的部份也是完全符合MVC的架構,所以整個系統可以分為二大MVC,一個是View/UI Controller/Data Model另一個就是由UI / Workflow / Database。

2.將整個系統開發中最繁鎖也最易出錯的給值/取值(如同Java Class Set / Get Method)的動作由jBrick來自動完成,以增快專案的開發速度及系的穩定度。

3.在一般的專案開發中,如果設定為網頁程式,若日後要改為一般應用程式(即微軟所稱的Win Form)時將作許多的修改(基至整個重新開發),所以我們在設計此jBrick時,將設計一個統一的介面以使用後在Web Form和Win Form之間切換時,只需重新設計畫面,而Business Flow和Server Code的部份均可延用即有的程式。

4.Business Flow的部份運用了Workflow Engine的架構,使開發者可以配合企業內部流程的改變而快速修改流程以符合企業的需求。

5.由於企業內部常會存在著許多的系統,因為會有異質資料庫存在(除非有透過EAI或是DataMart來將資料整合在同一資料庫),而系統往往會存取到不同的資料庫,因此我們會利用Data Model來同時間存取異質資料庫。

平台運用範例
1.Swing的範例畫面







2.JSP的範例畫面