Archive

Archive for the ‘Architecture’ Category

Google AppEngine for Java Announced

April 9, 2009 (Thursday) 1 comment

Today is a great day while Google announced the Java version of AppEngine.

The first thing to keep in mind is the security sandbox on the AppEngine server. And obviously it would be the challenge for many Java frameworks to run on AppEngine server out-of-the-box.

After having a brief run, here are something I found:

  • SiteMesh cannot work since it called javax.naming.InitialContext somewhere.
  • Stripes cannot startup by default because the DefaultMultipartWrapperFactory delegate to somewhere called System.getProperty(“java.io.tmpdir”). By providing a empty implementation of MultipartWrapperFactory, this could be solved easily. (Without considering the multipart function really works, since the AppEngine sandbox locked the file writing).
  • Freemarker works fine except there is an error on using JSP tags.
  • Spring framework seems fine as far as I go.

Looks like most of the issues can be solved. But the local environment does not work as the sandbox on AppEngine server. This makes the debug harder and the cycle longer.

Advertisements

Google App Engine – 新時代來臨的震撼

April 28, 2008 (Monday) 4 comments

Google App Engine (GAE) 月初在公開發表,announce 的那幾天每天都佔據了各大技術網站的版面。一個全世界都在看,全世界都在玩的產品,一定有它獨到之處,當然一定要來研究研究。Download 了 SDK,試著開發了一個簡單的程式,其實我對 python 並不熟,加上對 Django 一無所知,但卻不會覺得開發很困難,反而覺得比開發 Java 還要快還要順。雖然使用 GAE 的經驗很淺,不過 GAE 給人一種新時代來臨的感受。

在 Business model 方面,其實有太多太多的討論跟介紹了,一定很容易找到。會覺得是一個新時來的來臨,不是因為這是一個可以跟 Amazon S3 / EC2 對抗的 service,而是在開發技術上面 GAE 也做了一些突破。

跟 Java web development 比較起來,GAE 在開發上讓人覺得最驚艷的地方就是修改 code 的 feedback 速度。一般的 Java web development 在修改 code 之後,需要 compile -> deploy -> restart web container 才能看到修改,但使用 GAE,基本上你的修改馬上可以 apply,沒有 compile、沒有 restart server。這個說法也許有點落伍,很多人馬上就會想到 Ruby on Rails (RoR);也有人會想到這不是本來 Python + Django 就有的能力?就算是 Java 界,Groovy / GrailsJRuby 等也可以做到同樣的事情,何必大驚小怪呢?

GAE 當然不是只是拿 Python 跟 Django 出來騙騙小孩的玩意,真正強大的就在 Big Table 的部份。不要問我 Big Table 是什麼,我答不出個所以來,但站在 GAE developer 的角度而言,沒有 DB 這個東西。使用 GAE 在開發時,你的 code 中的 domain model 就是唯一的 model,沒有 DB,也沒有 DB schema、版本等問題。修改 domain model 的 code 馬上反應在下一次執行裡。GAE 的 domain model code 建立在 Django data model 之上,用起來很方便,類似 RoR 的 Active Record,但是少了 DB 的麻煩。

即使使用 RoR,在 domain model 上還是有得頭痛,因為 DB 的 schema 如何跟 code 裡的 domain model 保持同步就是一個大問題,一般 DB Migration 可以應付這個問題,在 domain model 改變的同時,準備一段 migration 的 code / description 就可以讓開發架構幫你把 DB 改到同一個版本。在 Java 也有 liquibase 可以做到這件事。但免不了要下去改東西,更嚴重的是,這個修改很可能沒有辦法即時反應 (至少在 Java 應該還是免不了要 compile -> db migration -> restart),所以又掉回了比較慢的 development lifecycle。

那麼用 Big Table 有什麼 trade off 嗎?有的,就是大家熟悉的 SQL / relational model 等等武功全廢。雖然 GAE 提供了一個叫 GQL 的東西,語法類似 SQL,但沒有 join 等等在 SQL 裡威力最強大的功能,思考也不宜使用 relational model 去想你的 data,因為這樣會完全想不通要怎麼辦。會不會有什麼事變成做不到了?我想有可能,但絕對不會太嚴重,因為絕大部份講究 OO 的 code 本來就很少直接運用 relational model 在操作,所以才有 OR mapping 的出現。如今 GAE 一不做二不休使用了 Big Table,除了宣示它在 scalability 上舉世無雙以外,也帶領 GAE 的 developer 進入一個新的時代,一個不去用 relation model 思考的年代。

我不是花了很多的時間在 GAE 上,寫進階的系統會不會出問題我沒有辦法知道,但以基本 web 常見的功能而言,很容易開發。Big Table 完全不會影響到我的思考,反而在 development lifecycle 上給了很大的進步,幾乎所有修改都能馬上看到 feedback。Agile development 中,fast feedback 佔了很重要的一個地位,愈快有 feedback 代表了開發的速度愈快。拿 Java 作比較,在 code 的修改上 Python + Django 的 feedback speed 就已經快了一大段,再加上 Big Table 又勝過了所有使用 DB 的 solution (包括 RoR、Django、Grails and JRuby 等等)。這個開發速度上的震撼讓我一直在想,用 Java 開發 web 是不是已經過時了呢?在 GAE 的範圍以外又如何去趕上這個突破,跨入這個新的時代呢?我想世界上有其他更多的人已經在想這個問題,新的工具、機制我想很快就會出現,open source big table 的技術也慢慢的浮上來了,新時代也許會靜靜的到來。至於這個新的突破跟誰會有關?是不是只有如 Google 般大的公司才適合用 Big Table?這個就留待日後驗證好了。

當 Spring 2.5 遇上 Hibernate Annotations – 自動搜尋 classpath 內的 entity

November 24, 2007 (Saturday) Leave a comment

最近推出的 Spring 2.5 提倡使用 annotation 的方式取代 xml 的設定,這個部份幾乎完全取代了 Spring Annotations 的功能,看來這個 project 應該已經沒有什麼生存空間。但 spring annotations 的 hibernate module 所提供的 AutomaticAnnotationSessionFactoryBean 一直是我很喜歡的功能。以往使用 Hibernate Annotations 時我們只能以 fully qualified class name 或 fully qualified 的 package name 來指定 entity class。透過 AutomaticAnnotationSessionFactoryBean 我們可以自動找到所有標示為 @javax.persistence.Entity 的 classes 自動加入到 hibernate 的 mapping classes。Spring 2.5 既然本身就可以自動的搜尋到 @Component 以及相關的 bean class,那我們應該也可以做到 @Entity 的搜尋囉。

我按照 spring annotations 的做法,提供一個自製的 session factory bean:


import org.hibernate.HibernateException;
import org.hibernate.cfg.AnnotationConfiguration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean;
import org.springframework.util.ClassUtils;

import javax.persistence.Entity;
import java.io.IOException;

/**
 * Created on: 2007/11/24
 *
 * @author Alan She
 */
public class ClasspathScanningAnnotationSessionFactoryBean extends AnnotationSessionFactoryBean {

    private static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";
    private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
    private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);
    private final TypeFilter entityFilter = new AnnotationTypeFilter(Entity.class);
    private String resourcePattern = DEFAULT_RESOURCE_PATTERN;
    private String[] basePackages;

    public void setBasePackages(String... basePackages) {
        this.basePackages = basePackages;
    }

    protected void postProcessAnnotationConfiguration(AnnotationConfiguration config) throws HibernateException {
        for (String basePackage : basePackages) {
            try {
                String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                        ClassUtils.convertClassNameToResourcePath(basePackage) + "/" + this.resourcePattern;
                Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
                for (int i = 0; i < resources.length; i++) {
                    Resource resource = resources[i];
                    MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
                    if (isEntity(metadataReader)) {
                        String classFileFullPath = resource.getURL().getPath();
                        String basePackageResourcePath = ClassUtils.convertClassNameToResourcePath(basePackage);
                        int startIndex = classFileFullPath.indexOf(basePackageResourcePath);
                        final String classFilePath = classFileFullPath.substring(startIndex,
                                classFileFullPath.length() - ClassUtils.CLASS_FILE_SUFFIX.length());
                        Class entityClass = null;
                        try {
                            entityClass = ClassUtils.forName(ClassUtils.convertResourcePathToClassName(classFilePath));
                        } catch (ClassNotFoundException e) {
                            throw new HibernateException("Entity class not found during classpath scanning", e);
                        }
                        config.addAnnotatedClass(entityClass);
                    }
                }
            }
            catch (IOException ex) {
                throw new HibernateException("I/O failure during classpath scanning", ex);
            }
        }
    }

    private boolean isEntity(MetadataReader metadataReader) throws IOException {
        if (entityFilter.match(metadataReader, this.metadataReaderFactory)) {
            return true;
        }
        return false;
    }
}

這個 class 的內容是以 Spring 2.5 的 ClassPathBeanDefinitionScanner 為骨幹而來的。原理很簡單,以 PathMatchingResourcePatternResolver 去找到所以 basePackage 下的 classes,一一比對是否有 annotate 了 @javax.persistence.Entity,如果有就加入到 session factory 的 annotationClass。


<bean id="sessionFactory" class="package.ClasspathScanningAnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="hibernateProperties">
    <props>
        <prop key="hibernate.dialect">${hibernate.dialect}</prop>
    </props>
    </property>
    <property name="basePackages">
        <list>
            <value>package.model</value>
        </list>
    </property>
</bean>

使用上也非常簡單,跟一般 spring 宣告 session factory 一樣,只需指定 basePackage 作為搜尋的範圍即可。

自動搜尋當然有優點也有缺點,但我個人討厭一一去設定 entity。有人可能會覺得萬一如果我有在 classpath 裡的 entity 又不想加入那不就只能全都用手動設定?其實如果想要有些彈性可以加入 include / exclude pattern 等東西,讓設定更活。畢竟設定檔時代已經慢慢過去,在 convention over configuration 的大趨勢之下,想辦法制定規則以及將規則以自動化落實才是長久之計。

The Role of the Enterprise Service Bus

October 27, 2006 (Friday) 2 comments

InfoQ: Presentation: The Role of the Enterprise Service Bus

這是一個很讚的 ESB (Enterprise Service Bus) Presentation,演講者 Mark Richards 對 ESB 有非常深入的研究。演講回答了一個很多人會問的問題,為什麼要用 ESB?

根據 Mark 所說的,ESB 能夠把 business service 跟 implementation service 分開來,business service 是指該 domain 的一些服務,例如下單等等專業的語言;而 implementation service 只是一些 CRUD 一類的程式操作,來實作出像下單樣的功能。把這兩個部份分開完全合符了 SOA 的架構跟概念,也把 business process 跟 technical 切開。ESB 其中兩個重要的能力,process choreography 負責 business process 的管理;而 service orchestration 處理 implementation service 的串接。這是一個很重要的觀念。

演講最後提到了 open source 的 ESB,包括了 MuleServiceMix。比較之下,Mule 比較像是一個 lightweight 的框架,讓你以 POJO 實作任何型式的 service。而 ServiceMix 則是已經把該有的都整合好,能以各種各樣的方式去實作出 ESB 的 end point。

ESB 雖然仍很少在實際上看到運用的機會,但它建基於 XML、Web Services、BPEL 以及 SOA 等等的概念與技術之上,成為一個實現學術界論文描繪的 Web Services 烏托邦不可或缺的架構。也是至今真正能把 BPEL 等技術串接起來比較讓人信服的方式。ESB 會不會就是以後資訊系統的樣子,則還要慢慢去觀察。

technorati tags:, , ,

Blogged with Flock

Full Stack Framework 的流行 – 從單點變套餐

October 11, 2006 (Wednesday) 5 comments

我們去餐廳的時候,很常會點套餐。套餐省略了一一挑選的麻煩;對不了解菜色的人而言,套餐會從前菜到點心配好好的;通常也有一些折扣或是附餐。雖然失去了單點的自由度,但還是有很多人都會選用套餐。

Java,尤其是用在 web development 上,有各式各樣的 framework 跟技術。如果要一一選用跟搭配起來,往往是一種痛苦。畢竟能享受從挑選零件再組出一台跑車的人是極少數的人。每個元件都要弄懂也是一種很大的學習負擔。自從 Ruby on Rails 問世以來,很多人都喜歡上它的簡化跟整套 full stack 的 framework。或許是接受到 Ruby on Rails 的刺激,Java community 有很多類似的想法出現,如果你覺得慢慢把 Struts、Spring、Hibernate 等等全都學會再組裝起來很難的話,或許選用一個 full stack framework 也可以達到類似的效果。

以下點名一部份的 full stack framework,有些其實在 Ruby on Rails 之前已經出現了:

AppFuse:或許他不該叫 framework,它是一個把 Struts, Spring, Hibernate 等等 framework 預先組裝好的環境。其組裝的方式可以作為學習對象。Presentation Tier 可以選用 Struts/WebWork/JSF/Tapestry/SpringMVC;Persistence Tier 可以選用 Hibernate/iBATIS。AppFuse 已經在蠻成熟的一個階段了,我本身也在實際的 project 上運用過它,節省了不少開發時間。缺點是所用的 framework 也許不是在最新的版本。

JBoss Seam:這是 Hibernate 的作者 Gavin King 的力作。我個人非常喜歡這個 framework,原因不在它使用了 JSF+EJB3 這些 JCP 的標準,說真的如果不好用標準早是華而不實的東西。我喜歡它是因為大量運用了 annotation 減少了要開發的 code,而且那些 annotation 看得出來是在多次的經驗中提煉出來的,非常切合開發者真正的需求。而 JSF 跟 EJB3 的無間結合讓所要開發的 number of class 大量減少。如果沒有任何負擔的情況之下,我覺得 JBoss Seam 是最佳選擇。只是它目前還有些許的不成熟。

RIFE:一個很成熟的 framework,不過它的概念有點特立獨行,也沒有用到一些主流的 framework。看過它的 demo 我覺得它的想法有達到目的,但因為離主流有點差距,能得到的資源較少。它也可以跟 Spring 等等做整合。

Grails:由 groovy 為主軸的 full stack framework,目前還在很早期的階段。不過 groovy 這種 scripting language 的簡便,讓 Java 也有機會跟 Ruby on Rails 一拼。後端是以 Spring+Hibernate 為基礎。我覺得這個 framework 潛力很大。

其他如 TrailsProject Able 等等因為我沒有太多的研究,不一一詳列,事實上一定還有很多我沒看過或是已經忘記名字的 framework 存在。所能看到的是 full stack framework 的興起,如果是你要追求快速開發,也許要改為注意 full stack framework 的動向,而不單單是個別 framework。在以上的 framework 裡,幾乎都用到了 Spring,也就是說 Spring 這種 middle tier 的 framework 佔有重要的角色。當然 JBoss Seam 是用了 EJB3,不過功能上類似。而 middle tier 的能力就決定了 full stack framework 整合的能力。所以未來 Spring 或是 EJB3 的角色會更重要而使用更廣泛。

如果你還在煩惱用哪些 framework 作為你的 baseline,在學習怎麼把不用 tier 的 framework 組裝在一起的話,那麼何不看看以上幾個 full stack framework 呢?或許你單點的菜色其實跟套餐差不多,而套餐還送你附餐飲料呢!

technorati tags:, , , , , , , , , ,

Blogged with Flock

Ajax4jsf – JSF 的一支強心針

August 6, 2006 (Sunday) Leave a comment

Ajax4jsf Open Source Project for Adding AJAX to JSF Applications without JavaScript: Downloads Articles, Examples, Tutorials

之前一直對 JSF 在 Ajax 上的 support 非常不以為然,因為都是一些 JSF 的 implementation 提供了有 ajax support 的 component。這樣聽起來是沒有什麼問題,但仔細一想會發現如果遇到沒有合用的元件,或是一些跨元件的問題時,麻煩就大了。當然一些 commercial 的 JSF implementation 應該夠強大去解決這些問題。但 open source 的 JSF 就沒辦法在 Ajax 上發揮自如了。

Ajax4jsf 在 Server side 放入一層比 JSF 更前面的 Front controller,等於是 hack JSF component 的 lifecycle。另外,Ajax4jsf 提供了一些 support 的 jsf taglib,在 JSF page 中使用可以針對不同的時機 (Javascript event) 去發動 Ajax4jsf 的 request,並進行 reRender component 等動作。後端方面因為跟 JSF lifecycle 整合在一起,所以也不用擔心 client/server inconsistence 或 refresh 的問題。

整體看來,Ajax4jsf 沒特定針對哪一種 JSF component,解決了 JSF 在 Ajax support 上的一大問題。使用 Ajax4jsf 是不需要寫 Javascript 的,雖然這點對 JSF developer 應該算是理所當然的了。基本上只要 Ajax4jsf 支援針對 JSF component 操作的事件足夠的話,對 JSF developer 來說已經足以建出一個 Ajax application 了。要是 JSR 把 Ajax4jsf 列入 JSF 的 spec 的話,那麼 JSF 大可號稱是一個 Ajax inside 的 Web MVC framework。看到 Ajax4jsf,對 JSF 又回復了一點興趣了,有了 Ajax4jsf,我大可以不要管什麼 post only 的問題了。真不知道是技術環境的反覆還是我自己三心兩意?

technorati tags:,

Blogged with Flock

XML/SWF Charts – 新一代的網站圖表工具

July 26, 2006 (Wednesday) 16 comments

在 Web 上常常需要顯示圖表,而圖表如果是由動態資料產生的,就必需要有繪圖的 API 來幫忙製圖。以 Java 來說,大家熟知的是 JFreeChart。JFreeChart 提供的繪圖 API,在 web 環境的話,就要在 server 先把圖產生,再由 client 端顯示。這樣對 server 也是一個負擔,當很多人想要看各種不同的圖表時,系統的回應時間變慢、暫存檔的量大增,都是可以預見的。

XML/SWF Charts 是一個由 SWF (Flash) 在 client 端繪圖的 API。Server 只要準備 XML 格式的資料,圖的部份由 Flash 幫你在 client 端繪畫起來。省了 server 的 loading,也沒有暫存檔的產生,而且因為是 flash 做的,還可以有動畫特效,簡單、好用又美觀,絕對是 web 產生動態圖表的不二之選!

大家在這個連結可以看到很多範例,我不用貼圖的方式是因為貼圖沒有動畫的效果。事實上 W3Counter WUFOO 裡的圖似乎也都是用這個 API 做的,看來這個 API 已經得到 AJAX 界的肯定。

使用上其實也蠻簡單的,首先 下載 XML/SWF Charts 的 library,解開後有一個 charts.swf 和 charts_library 的資料夾。把它們放到 web 可以 access 得到的地方。在 html 或是動態網頁檔加入以下的 flash object:

<OBJECT classid=”clsid:D27CDB6E-AE6D-11cf-96B8-444553540000″ codebase=”http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0&#8243; WIDTH=”400″ HEIGHT=”250″ id=”charts” ALIGN=””> <PARAM NAME=movie VALUE=”charts.swf?library_path=charts_library&xml_source=sample.xml”> <PARAM NAME=quality VALUE=high> <PARAM NAME=bgcolor VALUE=#666666> <EMBED src=”charts.swf?library_path=charts_library&xml_source=sample.xml” quality=high bgcolor=#666666 WIDTH=”400″ HEIGHT=”250″ NAME=”charts” ALIGN=”” swLiveConnect=”true” TYPE=”application/x-shockwave-flash” PLUGINSPAGE=”http://www.macromedia.com/go/getflashplayer”&gt; </EMBED> </OBJECT>

其中 src 的部份要指向 charts.swf 的所在位置。而後面的 sample.xml 就是圖表的資料來源囉。Sample.xml 由一個固定的 xml 格式表示圖表的原始資料。以下列的圖表為列:

2001 2002 2003 2004
Region A 5 10 30 63
Region B 100 20 65 55
Region C 56 21 5 90

那麼 Data 的格式就要如下:

<chart>
    <chart_type>column</chart_type>
    <chart_data>
      <row>
         <null/>
         <string>2001</string>
         <string>2002</string>
         <string>2003</string>
         <string>2004</string>
      </row>
      <row>
         <string>Region A</string>
         <number>5</number>
         <number>10</number>
         <number>30</number>
         <number>63</number>
      </row>
      <row>
         <string>Region B</string>
         <number>100</number>
         <number>20</number>
         <number>65</number>
         <number>55</number>
      </row>
      <row>
         <string>Region C</string>
         <number>56</number>
         <number>21</number>
         <number>5</number>
         <number>90</number>
      </row>
   </chart_data>
</chart>
而產生出的圖表就是這個樣子囉:

補充一下,圖表的一些格式、設定參數,是由 chart attributes 來設定,上面的 <chart_type> 就決定了系統要畫出什麼圖表。而 chart 的資料來源也可以帶有參數,讓 server 依參數動態產生 xml data。以上就大觀念作了簡單的解釋,詳細的部份請參閱 TutorialReference,畢竟參數太多了,很難一一解說。

這樣的 web 圖表架構,其實本身就是一種 AJAX。而 XML/SWF Charts 是可以免費使用的,只是圖會是可以點的,而點選就跳到 XML/SWF Charts 的 site。如果選擇付費的話,其實也不會很貴,USD $45 就可以買到一個 domain + any subdomain。我覺得 XML/SWF Charts 很有潛力成為知名圖表工具,甚至變成 Web 的圖表標準。而它的 host,maani.us 還提供了很多有趣跟有用的工具,像有一個是 flash 做成的汽車儀表板,實在太讚了。強力推介!

technorati tags:, , , ,

Blogged with Flock