作者簡介: Michael Yuan,技術專家,《JBoss
Seam: Simplicity and Power Beyond Java EE》、《Lightweight Java Web
Application Development》等書的作者,軟體顧問,目前就職於JBoss。
摘要: 本文介紹了JBoss Seam如何整合商務程序、使用iText和任務調度,並且總結了Seam編程模型中的關鍵要素。
本文是《JBoss Seam:一個深度整合架構》一文的最後一部分。
在Web應用中整合商務程序
大部分企業級應用存在許多商務程序和規則。例如,在一個簡單的電子商務網站(以”線上購物”為例)中,客戶登入後進行購物流程,商店管理員登入後
進行審批次程序,倉庫職員登入後進行發貨流程。不同的人員站在不同的角度,去執行不同的任務,然而,他們又同時合作完成同一個業務情境。
在企業級應用中,業務分析人員通常定義商務程序和規則。他們使用專業的商務程序軟體繪製這些流程和規則,然後應用開發人員實現這些設計。
然而,由於大部分Web應用程式框架沒有整合流行的商務程序和規則引擎,開發人員只能通過自己的方式進行商務程序的整合。這樣勢必會造成開發人員和業務分析人員工作的脫節,使得業務分析人員很難去審核和驗證。
Seam通過jBPM和JBoss Rules(以前的Drools)對商務程序和規則的整合提供了極好的支援。
在Seam應用中,你可以指定UI動作(例如按鈕點擊)來觸發商務程序。你只需要通過@CreateProcess註解來標記UI事件處理方法。業
務流程是不同的使用者以相應順序來完成的一系列任務。你可以用@BeginTask和@EndTask標註任務的開始和結束。當前任務結束時,jBPM引擎
將自動把進程前移,進行下一個任務。
@Name(”ticketSystem”)
public class TicketSystemAction {
@CreateProcess(definition=”TicketProcess”)
public String newTicket() {
return “home”;
}
@BeginTask
public String reply() {
return “reply”;
}
@EndTask
public String sendAnswer() {
System.out.println(”Answered”);
return “home”;
}
}
Seam讓每個使用者可以查看他/她的當前工作清單以及完成任務的下一個動作。這些工作清單是基於當前登入的使用者角色產生的,並且通過使用者認證和授權的方式緊密地整合到Seam安全架構中。
<h1>Assigned Tickets - #{login.user.username}</h1>
<h:dataTable value=”#{taskInstanceList}” var=”task”>
<h:column>#{task.description}</h:column>
<h:column>Title: #{ticket.title}</h:column>
<h:column>
<h:commandLink action=”#{ticketSystem.reply}”>
<h:commandButton value=”Reply”/>
<f:param name=”taskId” value=”#{task.id}”/>
</h:commandLink>
</h:column>
</h:dataTable>
在整合jBPM/JBoss Rules的Seam應用中,開發人員可以直接使用Seam註解和組件驅動商務程序和規則引擎,而不需要單獨掌握特定的jBPM和JBoss Rules的Java APIs。
使用iText產生不同的視圖
iText庫是一套被廣泛用於產生PDF文檔的開源Java庫。然而,使用iText API建立PDF文檔是十分耗時的(想想用DOM建立XML文檔或者用Swing寫UI的經曆)。
Seam整潔地整合了iText、JSF和Facelets,開發人員可以通過和產生JSF頁面一樣簡單的方式,將動態內容產生PDF頁面,你甚至可以在PDF頁面中使用模板。
Seam為PDF元素建立了特殊的XHTML標記庫,然後在產生頁面的時候透明地調用iText。下面的樣本顯示了如何在Seam應用中,產生有數位簽章支援的PDF頁面。
<p:document … title=”Why Seam” keywords=”mykeyword”
subject=”seam” author=”Seam Team” creator=”Seam PDF example app”>
<p:image alignment=”right” wrap=”true” value=”/jboss.jpg” />
<p:font size=”24″><p:paragraph spacingBefore=”16″ spacingAfter=”40″>
Order #{currentOrder.orderId}
</p:paragraph></p:font>
<p:paragraph>Dear #{currentOrder.customerName},</p:paragraph>
<p:paragraph>… </p:paragraph>
<p:barCode type=”code128″ code=”My BarCode” />
<p:signature field=”My Signature” size=”200 200 400 400″ />
</p:document>
通過代碼,我們可以看到整合是無縫的,頁面不依賴於iText。實際上,將iText替換成其他的商業PDF庫,頁面仍然可以工作,這就是Seam整合的魅力。
進階任務發送器
在許多企業級應用中,對自動重複任務的支援是相當重要的。在標準的EJB中,你可以使用EJB Timer API在固定的時間間隔內調度重複的事件。然而,在實際的應用中,我們需要比固定的時間間隔觸發更進階的調度服務。
目前流行的開源Java調度庫是Quartz庫。但是如果要使用Quartz的話,開發人員仍需要自己寫”膠水”代碼來整合Quartz特定的APIs和物件模型。
Seam整合了Quartz,用於調度非同步重複任務。你只需要在重複工作的方法上添加@Asynchronous註解。你可以傳入任務的開始/結束
時間、間隔或者克龍運算式(cron
string)的字串作為參數,也可以在方法定義中註解這些特定目的的參數。指定的方法將返回QuartzTriggerHandler對象,你可以稍
後使用這個QuartzTriggerHandler對象暫停或取消任務,你也可以將這個QuartzTriggerHandler對象儲存到資料庫,以
供稍後使用。
@Asynchronous
public QuartzTriggerHandle schedulePayment(
@Expiration Date when,
@IntervalCron String cron,
@FinalExpiration Date stoptime
… any other call parameters …) {
// do the repeating or long running task
}
下面的例子中,schedulePayment()方法設定在下午2點10分和三月每個星期三的下午2點44分運行。你可以在Web UI事件處理方法中加入這段調用的代碼,這樣當按鈕按下時,重複事件將被安排到發送器中。
QuartzTriggerHandle handle =
processor.schedulePayment(payment.getPaymentDate(),
“0 10,44 14 ? 3 WED”,
payment.getPaymentEndDate(),
payment);
payment.setQuartzTriggerHandle( handle );
// Save payment to DB
// later …
// Retrieve payment from DB
// Cancel the remaining scheduled tasks
payment.getQuartzTriggerHandle().cancel();
從例子可以看出,開發人員不需要手動啟動Quartz發送器、建立Quartz觸發器和任務,而只需要使用Seam註解POJOs就可以了。
統一的編程模型
目前為止,我們已經介紹了很多Seam通過一致的編程模型整合不同架構的例子。除了上面介紹的這些,還有許多其他的架構。但是限於篇幅,我們不可能介紹所有的架構。下面我們將總結一下Seam整合這些架構的方法。Seam編程模型中關鍵的三要素是:
註解POJOs:Seam應用中所有的Java組件都是註解的POJO類。Seam通過雙向依賴注入管理它們之間的互動。除此之外,Seam中沒有其他的組件模型。
XHTML顯示頁面:所有視圖(UI)頁面都是通過XHTML檔案顯示出來,除去標準JSF標籤,Seam還定義了許多自己的UI標籤,包括PDF UI標籤等。Seam同時也加入了Ajax JSF庫,比如Ajax4jsf、RichFaces和IceFaces。
運算式語言:XHTML頁面通過JSF運算式語言(EL)引用Seam中的Java組件。Seam增強了標準的EL文法,使它支援方法參數等,並且使EL可以用於所有的XML設定檔和測試指令碼。
有了這些Cool的特性,Seam的編程模型將變成異常簡便。只要有一些JSF基礎,你的學習曲線將非常平坦。
下載Seam,看看執行個體,快樂地編寫Seam代碼,一切就這樣簡單!
轉自:http://www.dojochina.com/index.php?q=blog/8377