Archive for the 'technical' Category

converting tiff to jpeg - the java way

yes I thought it should be easy, at least typical.
but I was not able to find a clean and easy way to do so.

I started looking into javax.imageio,
realizing that it only support basic formats like gif, jpeg, bmp.
Anything beyond that will need custom plugin.

I searched through forums and heard of stuffs called JAI -
the Java Advanced Imaging library,
however i couldnt find the plugin I needed for tiff.
Screwed up for two hours I finally found out that there is a separate package called JAI-imageio,
which is not included in JAI. Yea…..what a great confusion.

Once I got that all the rest is straight forward.


public static void convertToJpg(String path) throws IOException {
    ImageReader reader = ImageIO.getImageReadersByFormatName("tiff").next();
    ImageInputStream iis = ImageIO.createImageInputStream(new File(path));
    reader.setInput(iis, false);
    ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
    String filename = path.substring(path.lastIndexOf("\\")+1, path.lastIndexOf("."));
    for (int i=0; i<reader.getNumImages(true);  i++) {
        BufferedImage image = reader.read(i);
        String outputFileName = filename+"_"+(i+1)+".jpg";
        ImageOutputStream ios = ImageIO.createImageOutputStream(new File(outputFileName));
        writer.setOutput(ios);
        writer.write(image); // (*)
    }
}

If you need to have control over the output quality,
you will have to add these line:


ImageWriteParam writeParams = (ImageWriteParam) writer.getDefaultWriteParam();
writeParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
// value ranged from 0.0 to 1.0 for minimum file size, worst quality to maximum file size, best quality
writeParams.setCompressionQuality(0);

and replace the line marked by (*) with :


writer.write(null, new IIOImage(image, null, null), writeParams);

Concerning performance,
it costs about 28s to convert a 7-page tiff (383kb in file size) with dimension 5100 x 6122,
to 7 jpeg files with the same dimension (4.27mb totally(!), with highest compression).
Changing the compression ratio seems to have very little effect on the time.

All other type of conversion can be done in similar way,
as long as you’ve got the required plugin.

Let’s spread Firefox!

萬眾期待的Firefox 3 將會於6月17日正式推出,
官方為隆重其事特別舉行了Firefox Download Day 2008
希望於推出當天打破一天內最多下載量的健力史紀錄,
大家現在可以到上述網站登記你的email和地區,
到時就會有reminder提醒你去下載。

目前登記人數已經超過一百萬,
當中人數最多的自然是美國,
其次就是歐美,中國日本等,
而香港也有4千多人。

Firefox是對上網比較有要求的進階用戶才會使用的,
看到這些數據,其實也一定程度地反映出當地的IT水平,
因此歐美中國日本印度等IT產業比較發達的國家的登記人數是較高的,
而非洲和中東大部份國家裡面,
人口過百萬的國家登記人數也相當少。

出乎意料的是,我一直認為IT水平不高的巴西,
也有不少人登記,算百分率比中國還要高。

我登記了,大家會去登記嗎?

GWT-Ext 2.0.4 推出

GWT-Ext 2.0.4 剛在日前推出了。

新特性包括對GWT 1.5 和Firefox 3的支援,
一個新的pagebus組件,
與及大量bugfix。

其中最有趣的莫過於pagebus,
是一個可以讓同一個畫面上不同的ui組件,
透過subscribe/publish的messaging概念去交換資料的內建模組,
可以大大簡化介面層內controller/mediator的logic。

有興趣可以去showcase入面看看Miscellaneous -> Publish Subscribe的例子。

另一個讓人頗為振奮的消息來自GWT-Ext forum內,
GWT-Ext的團隊好像已經重組完畢並承諾在日內公佈發展方向,
看來Sanjiv Jivan (GWT-Ext的前project lead)的離去沒有影響GWT-Ext的發展,
作為GWT界最為成熟的UI framework,
很期待它繼續成長。

The Hockey Stick Function

摘自SOA in Practice,
中到應一應,
我覺得呢幅圖可以apply落近年大部份既新IT產品,
尤其是oracle o個d。

Prefactoring

這是一本有關軟件設計的書,
”Refactoring” 大家很清楚是什麼意思,
也是書名”Prefactoring”的靈感來源。
”pre”者,前期也,就是說有一些設計原則,
如果能夠在未動手coding之前已經套用在系統上,
就可以減少日後refactoring的需要。

本書也嘗試模仿Refactoring一書的寫法,
透過一個商店的電子系統設計和實施過程的真實例子
去講解各種原則的運用和好處。

我喜歡這種寫法,書寫得很易讀,
所以也很快就讀完。
設計原則嘛,不是太過老生常談,
就是太虛無縹緲,基本上得著不大。
個人最大感悟就是那種agile的態度,
像我這樣有嚴重偏執狂的病態developer,
是時候好好改變下。

接下來應該要開始看SOA 和GWT的書...

好hurt

今日oracle website 既頭版tagline:

每次見到oracle 收購bea 既新聞都覺得有d 唔舒服,
o係bea 香港office 工作左一段時間,
同埋用左weblogic 做幾個development project,
不其然咁對bea 有一定既感情。

bea o係我眼中係一間好照顧developer 既企業軟件生產商,
本身產品既技術亦都好創新,
XMLBeans, Beehive 等技術都比同期J2EE 標準優秀,
而最重要既係唔會強迫用weblogic 既developer一定要用佢地既framework,
bea 一直對opensource既產品保持開放態度同技術支持,
o係weblogic 8既年代已經提供spring既support,
上面講既XMLBeans 同Beehive而家已經捐左俾Apache,
對opensource既貢獻有目共睹。

而oracle 就係一間「金手指」無限金錢,
本住人有我有既態度不斷吞食各種層面既企業軟件。
獨市之下產品發展大幅減慢,
自家既技術創新只限於老本行database,
其他觀乎什麼OC4JApplication Express,甚至BPEL Process Manager
用落都會令人禁不住大嘆「點x樣呀家陣」...

見到上面什麼Oracle Developer Community Welcomes BEA Users真係汗顏,
唔知點解感覺上係一句風涼說話。
bea 本身既community 非常健康,
用opensource同用bea 自家framework既developer都融洽討論,
想搵d 野亦都好快搵到或者有人出手相助。
我o係oracle既community就未有過好愉快既經驗喇。

試問俾oracle 收購左bea 叫人點安樂...
收到幾可靠既消息oracle 會棄OC4J 取weblogic,
ALBPM取BPEL Process Manager,棄WorkshopJDeveloper
weblogic係正路既選擇...而後兩者就...唉。
我唔奢望bea可以改變oracle,但作為一個ISV 既developer,
我唔想見到bea 死o係oracle手上。

GWT1.5快將推出

今日各大技術網站都聲稱收到可靠消息,
指google將會在5月28, 29兩日舉行的技術大會出發佈GWT 1.5。

1.5 被譽為GWT問世以來最重要的一次更新,
本次推出將全面支援Java 5 的功能,
包括generics, annotations 等。
1.5 的另一個重點就是大幅度改進javascript 的效能,
配合同樣是快將推出的Firefox 3,
相信以GWT開發的ajax 軟件運行速度會翻一翻。

Hong Kong Java User Group Meeting May 2008

Tonight at the HKPC building we have a senior consultant from SpringSource,
presenting about the new stuffs from their leading stacks.
Annotations for spring configuration is discussed and for the second half,
we have looked at some features of the Application Management Suite,
and the well anticipated SpringSource Application Platform.

Although nothing particular amazing,
I’ve got some idea to try implementing the GWT-RPC with Spring’s MultiActionController.
(But only if I have got some time to look into it…)
The second half is much more like a commercial showcase of the SpringSource company,
yea….I know there is no free lunch.
The Application Management Suite is like a turbo jet for my bicycle,
I love tomcat because it is lightweight.
Instrumenting JMX-like stuffs into tomcat turns it into another bulky stone, I don’t know,
at least I have to taste it sometime.

And for the organization of the event, HKJUG provided very limited support.
There is no sharing, no communication among fellows at all.
Feel like I was going to a theater and leave after the show ends.

Handling file upload with gwt-ext and spring mvc

Finally i managed to get file upload works using a gwt-ext client against spring mvc.
In GWT application file upload is something different,
you cannot do so through GWT-RPC due to the browser implementation.
File upload is only achievable through multipart form post.

On the client side you have to set up a form:


final FormPanel formPanel = new FormPanel();
// setFileUpload(true) is important because it sets the
// <form>'s content type to multipart
// so that your server knows what to do
formPanel.setFileUpload(true);

final TextField file = new TextField("File", "file");
file.setInputType("file");
formPanel.add(file);

formPanel.addButton(new Button("Upload", new ButtonListenerAdapter() {
    public void onClick(Button button, EventObject e) {
        formPanel.getForm().submit(url, null, Connection.POST, "loading...", false);
    }
}));

in the spring servlet config,
you will have to map the url you are POST-ing against to a controller that is responsible for handling file upload.


<!-- specify the java bean to bind the file upload as a byte array in the property 'commandClass" -->
<bean id="fileUploadController" class="example.server.FileUploadController">
	<property name="commandClass" value="example.web.bean.FileUploadBean"/>
</bean>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <value>
            /**/fileupload.smvc=fileUploadController
        </value>
    </property>
</bean>
<!-- this bean is how spring mvc detects multipart form post -->
<!-- commons-fileupload jar is required for this bean to work -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<property name="maxUploadSize" value="100000"/>
</bean>

finally the controller code is easy,
at first I tried to subclass SimpleFormController,
but it involves specifying a formView and successView,
which, for a GWT client you are not going to need “view”.
so I simply extend the AbstractCommandController.
It binds the request parameters of a POST request to a commandClass,
this serves my purpose nicely.


public class FileUploadController extends AbstractCommandController {

    protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception {
        // you will need to cast the command back to your commandClass
        FileUploadBean fileUploadBean = (FileUploadBean) command;
        byte[] file = fileUploadBean.getFile();

        // do whatever logic you needed
        // because we are not going to return a "view"
        // we simply have to give out some response to the GWT client and return a null view.
        response.getWriter().println("File upload succeeded!");

        return null;
    }

    // this method is overriding, and specify how spring convert multipart into a byte array that binds to our command class
    protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
	    binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor());
	    super.initBinder(request, binder);
    }
}

Integrating with spring mvc provides you free infrastructure of data binding, dependency injection on the controller,
and validation with spring’s Validator.

Hope this helps.

RESTful Web Services

剛讀完這本RESTful Web Services

其實本書不用寫那麼長,
概念上簡單不過,
REST 是一種網絡數據的設計方式,
簡化了傳統Web Service透過HTTP POST 作SOAP RPC請求的方法,
重新重視HTTP的設計原則。
換句話說就是純粹運用GET, PUT, DELETE等的HTTP方法完成一般對資料CRUD的操作。
本書一直重複這種方式的好處,
未免有點喋喋不休。

透過這種設計方式可以使網路系統更加簡單,
整合也更加容易。
市面上一些巨頭已經提供不少RESTful的Web Service,
如Google 的gmail, GData;Amazon的S3等,
証明了它本身的技術價值。

我是很欣賞這種設計風格,
不過呢...
目前Java 圈子內主流的application framework對REST的支持還不足,
例如根據Spring非正式的roadmap
對REST的支持大約要到3.0才會開始,
相信要到08年尾才會看到些端倪(還不知支持到什麼程度)。
平民化的開源framework RESTlet 似乎還沒有完整的整合到其他application framework,
JCP311(就是Java REST標準)還在緩慢進行中...

目前REST在Java界不算很成熟,
似乎要用在企業級開發還是言之尚早,
至於internet website,
Ruby on Rails, Django輕量化的平台看來有不錯的支持,
寫起來會更方便。

Next Page »