Total Pageviews

2016/08/05

[Java Mail] Encoding problem

Problem
I am using Java Mail API to sent test mail.
Assume I write email content with Traditional Chinese, all characters are broken.


How-To
We need to set default encoding to 'UTF-8' before send.
Here has the sample code:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import java.io.File;
import java.util.Properties;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;

public class MailTest {

    public static void main(String[] args) {

        Properties props = new Properties();
        props.put("mail.smtp.starttls.enable", "true");

        String host = "smtp.gmail.com";
        int port = 587;
        String userName = "xxx";
        String password = "xxx";

        String mailTo = "xxx@gmail.com";
        String subject = "Hello my friend~";

        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        sender.setJavaMailProperties(props);
        sender.setHost(host);
        sender.setPort(port);
        sender.setUsername(userName);
        sender.setPassword(password);

        // set email default encoding
        sender.setDefaultEncoding("UTF-8");

        String content = "<p>親愛的客戶您好:</p>";
        content += "<p>您的網路申請驗證碼為<font color='red'>12345</font>,僅限會員申請使用,請於收到e-mail <font color='red'>10分鐘內完成驗證,10分鐘後將自動失效</font></p>";
        content += "<p>XXXX敬上</p>";

        MimeMessage message = sender.createMimeMessage();
        try {

            MimeMessageHelper helper;
            helper = new MimeMessageHelper(message, true);
            helper.setTo(mailTo);
            helper.setSubject(subject);

            // true means it is a html format email
            helper.setText(content, true);

     // attachment1
            FileSystemResource panda01 = new FileSystemResource(new File(
                    "D://dropbox//picture//201602011033331.png"));
            helper.addInline("pand01", panda01);

     // attachment2
            FileSystemResource panda02 = new FileSystemResource(new File(
                    "D://dropbox//picture//panda.png"));
            helper.addInline("panda02", panda02);

        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }

 //sent mail
        sender.send(message);
    }
}

Check the mail:

Reference
[1] http://stackoverflow.com/questions/5636255/unicode-chars-and-spring-javamailsenderimpl-no-unicode-chars-under-linux

2016/08/04

[JavaMail] Attachment name does not show correctly in Email

Problem
I am using JavaMail API to send email. But the attachment name does not show correctly.
The name should be 退匯明細表.pdf‎, but I got ATT97145.pdf‎.

The incorrect email looks like:


The expected email looks like:


Here is the code snippet to add attachment in email:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
private void attachFiles(MimeMessageHelper messageHelper, List<File> attachFiles)
        throws MessagingException {
    for (File attachFile : attachFiles) {
        FileSystemResource file = new FileSystemResource(attachFile);
        log.info("attachFile.getName():" + attachFile.getName());

        try {
            messageHelper.addAttachment(attachFile.getName(), file);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
}


Solution
You can utilize MimeUtility.encodeText to handle the file name.
Here is the updated code snippet:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
private void attachFiles(MimeMessageHelper messageHelper, List<File> attachFiles)
        throws MessagingException {
    for (File attachFile : attachFiles) {
        FileSystemResource file = new FileSystemResource(attachFile);
        log.info("attachFile.getName():" + attachFile.getName());

        try {
            messageHelper.addAttachment(
                    MimeUtility.encodeText(attachFile.getName(), "UTF-8", null), file);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
}


Reference
[1] http://docs.oracle.com/javaee/6/api/javax/mail/internet/MimeUtility.html#encodeText(java.lang.String, java.lang.String, java.lang.String)

2016/08/03

[Java Mail] How to check Exchange Server status?

Problem
If I would like to write a Java code to check the status of SMTP server, how to do it?

How-to
The sample code is as bellows:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package albert.practice.mail;

import java.util.Properties;

import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Transport;

import lombok.extern.slf4j.Slf4j;

import org.springframework.mail.javamail.JavaMailSenderImpl;

/**
 * Used to check the status of exchange server .
 */
@Slf4j
public class CheckSmtpStatus {

    /**
     * The main method.
     * 
     * @param args
     *            the arguments
     * @throws MessagingException
     *             the messaging exception
     */
    public static void main(String[] args) throws MessagingException {
        String host = "smtp host name";
        int port = 25;
        String emailU = "username";
        String emailP = "password";

        CheckSmtpStatus checkSmtpStatus = new CheckSmtpStatus();
        boolean isConnected = checkSmtpStatus.isConnected(host, port, emailU, emailP);
        log.debug("isConnected = " + isConnected);
    }

    /**
     * Checks if is connected.
     * 
     * @param host
     *            the host
     * @param port
     *            the port
     * @param emailU
     *            the email u
     * @param emailP
     *            the email p
     * @return true, if is connected
     * @throws MessagingException
     *             the messaging exception
     */
    public boolean isConnected(String host, int port, String emailU, String emailP)
            throws MessagingException {
        boolean isConnected = false;
        Transport transport = null;
        Session session = createJavaMailSender(host, port, emailU, emailP);
        try {
            transport = session.getTransport("smtp");
            transport.connect(host, port, emailU, emailP);

            // used to check this SMTP service is currently connected or not
            isConnected = transport.isConnected();
        } catch (NoSuchProviderException e) {
            throw new RuntimeException(e);
        } catch (MessagingException e) {
            throw new RuntimeException(e);
        } finally {
            transport.close();
        }
        return isConnected;
    }

    private Session createJavaMailSender(String host, int port, String emailU, String emailP) {
        Properties properties = new Properties();
        properties.setProperty("mail.debug", "true");
        properties.setProperty("mail.smtp.auth", "true");
        properties.put("mail.smtp.ssl.trust", "*");

        JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();
        javaMailSender.setJavaMailProperties(properties);
        javaMailSender.setHost(host);
        javaMailSender.setPort(port);
        javaMailSender.setDefaultEncoding("UTF-8");
        javaMailSender.setUsername(emailU);
        javaMailSender.setPassword(emailP);

        return javaMailSender.getSession();
    }

}




2016/08/02

[閱讀筆記] ZERO to ONE (Part 2)


  1. 經營事業就像下棋一樣。西洋棋王卡布卡蘭卡曾說:「要成功,首要工作就是必須先研究殘局」
  2. 膚淺的人相信運氣,相信環境;意志堅定的人相信因果
  3. 勝利是留給凡事都準備好的人,但一般人都以為只是運氣好
  4. 反摩爾定律觀察到,從1950年開始,每花十億元在新藥研發得到核准通過的新藥數量每隔九年就會減少一半,這跟摩爾定律恰好相反。由於同時間資訊科技業比過去有更快速的發展,因此今天的生技公司面對的大問題是未來能否看到有類似的發展。
  5. 創投的最大秘密是,成功基金的最佳投資應該等於或超過基金其他投資的總和
  6. 如果你是創投者,當你把專注焦點從事業的本質,移轉到是否合乎多元化避險策略的財務問題,那創投者(也就是你)看起來就會很像在買彩券。一旦你以為自己在抽獎,你就要做好輸錢的心理準備。
  7. 冪次法則 (Power Law) = 長尾理論,如80%的人只願意買當中20%的商品,而其餘80%的商品則只有20%的人想購買;又如這個產業80%的獲利被市占率前幾名的公司吃掉,其他公司只能吃剩下的20%的利潤
  8. 你要想清楚,你擅長的事,在未來是否有前景
  9. 在冪次法則 (Power Law) 的世界,你必須非常努力思考自己的行動到底會落在80/20曲線的哪一段,代價太大了。如果你真的自己開公司,一定要知道冪次法則 (Power Law) ,好好的經營。最重要的事情只有一件:一個市場會比其他市場更有利。時間和決策也有冪次法則 (Power Law) ,某些鍵時刻的決策的重要性,將遠比其他時刻更重要。
  10. 獨佔事業的老闆對他們的壟斷地位總是輕描淡寫,避免政府監管;競爭激烈的企業卻策略性的誇大他們的獨特之處
  11. 每個偉大企業都建構在不為外界所知的秘密上,一間偉大公司就是一個合力改變世界的計畫
  12. 身為創業者,你的首要工作是把第一件事情做對,因為你無法在有缺陷的基礎上,建立偉大的公司。早期做了一個差勁的決定就很難在日後彌補,例如你選錯創業夥伴或是雇用不對的人。記住,基礎決定命運
  13. 沒有團隊的支援,想要從0到1非常困難
  14. 一個人數很多的股東會,根本無法有效監督公司的經營,這只是為幕後的獨裁者提供掩飾。如果你不想受到董事會約束,就把股東會的規模膨脹到很大。如果要有一個有成效的董事會,規模必須很小,基本上不會超過五個,除非是上市公司,政府規定九個
  15. 一家公司付給CEO的錢越少,表現就會越好,這是我投資數百家新創事業所注意到的事情。高薪會給CEO誘因維持現狀,像個政客,捍衛目前的薪水,而不是和其他人一起努力找出問題並積極解決。缺少現金的CEO反而會專注提高公司的整體價值。
  16. 績效獎金是鼓勵獲得短期價值的思維。任何用現金支付的薪資,都是比較著眼在現在,比較沒有著眼在未來
  17. 股票是一種報酬,可以有效引導員工去創造未來的價值
  18. 股票無法創造完美的誘因吸引員工加入公司,卻是創辦人能讓大家都站在同一陣線的最好方法
  19. 內部和諧是新創公司的存活條件。我們常以為失敗的新創公司是在競爭激烈的ecosystem 中敗給嗜血的對手,但每家公司都有自己的 ecosystem,派系惡鬥會讓公司無力應付外在的威脅。
  20. 廣告的目的並不是要你馬上買產品,而是要讓你不知不覺地將產品的印象深植腦中,之後再帶動銷售。一個無法察覺廣告影響的人,反而容易被騙
  21. 要把銷售想成產品設計不可或缺的部分,如果發明新東西卻沒有找到有效的銷售方法,不管產品多棒,生意都不會好
  22. 未來最有價值的企業會問的是:電腦如何協助人類解決困難的問題
  23. 優秀的專業計畫必須回答這七個問題:(1)工程問題:你創造的是突破的還是微幅改善的科技;(2)時機問題:現在是開始這個事業的正確時機嗎;(3)獨佔問題:你一開始就在小型市場搶到高市佔率嗎;(4)人員問題:你有適合的團隊嗎;(5)銷售問題:你除了有開發產品的能力,你還有銷售能力嗎;(6)持久問題:你的市場定位可以堅持10年、20年嗎;(7)秘密問題:你是否已經找到別人沒看見的獨特商機
  24. 創業家一開始的挑戰是,先找到一個小市場,並搶下市佔率
  25. 創業者之所以重要,並非因為只有他們的工作才有價值,而是優秀的創業者可以激發其下員工繳出最佳表現
  26. 要從 0 到 1,最重要的第一步是自己獨立思考

2016/08/01

[閱讀筆記] Security Analysis (Part 2)


  1. 對於Security Analysis來說,不能假設過去已經發生的事實,未來也會重複發生,這些事實只能當做是預測未來的rough index
  2. An investment is a successful speculation and a speculation is an unsuccessful investment
  3. 投資vs投機的例子:債券與股票;現金購買與融資;長期持有與短期持有;investment for income與 investment for profit;安全的標的與高風險標的
  4. 雖說債券較安全,被歸屬於投資的類別,但這不是絕對的,如垃圾債券就屬於投機,高評等的企業的股票則屬於投資
  5. 投資的行為是經過分析,了解投資標的的風險,並訂定合理的收益。如果你的行為不滿足以上條件,就稱之為投機
  6. 不要以為債券一定是安全,債券的安全與否,完全取決於債權公司是否有能力履行合約,若因某些因素導致違約,你手上的債券也會造成重大損失
  7. 證券可以分成幾類:固定價值型態的證券(如高評等債券或優先股)、變動價值型態的證券(如較安全與有獲利前景的高評等可轉換債券、如風險較高的低評等債券或優先股)、普通股
  8. 假設本金有實質風險,高票面利率(coupon rate)未必能補償你所冒的風險,如高收益債券
  9. 評斷投資成果,應該要看的是預期回報與預期風險之間的關係
  10. bond selection 是一門負面的藝術(negative art),其成功之鑰是:盡力避免成為loser,而不是一直汲汲營營想要成為winner
  11. 購買高收益債券(high yield bond)的投資組合,必須要聚焦於B-rated評等以上的債券,相較於低評等的債券,高評等債券的收益或許比較差,但是也限制了其違約的風險,大幅降低了不確定性
  12. 一家公司的credit risk(信用風險),源自於其財務槓桿操作與不穩定性。若公司是有限度的操作財務槓桿與擁有溫和的債務需求,這類的公司由於有較穩定的cash flow,故可以從激烈的上下波動中存活下來
  13. interest converge (利息覆蓋率 = EBITDA÷利息支出),用來衡量公司產生的稅前利潤能否支付當期利息的指標。利息覆蓋率是一個風險提示指標,特別是在公司經歷業績低谷,自由現金流脆弱的時期更為關鍵,當該比率低於2.5時就要注意
  14. 當一家公司的債務多到與其資產不成比例時,即便是規模很大的公司,體質也會很脆弱
  15. 記得定期檢視你的投資組合. There are no permanent investments !
  16. 不要妄想去抓market timing,也不要去預測利率變動。你應該把你的力氣花在知道你所能知道的,如瞭解產業、企業、風險等等
  17. 除非你已經做好多元化配置,不然你不要去投資高收益債券 (high yield bonds)
  18. 安全的價位不是透過精密的數學計算所計算出來的,其仰賴市場的受歡迎度來決定
  19. 投資的風險就像火災與傳染病一樣,對於火險與壽險來說,都是非常特殊且難以計算的因素
  20. 棒球打者錯失三個好球,就會被判出局。但投資人錯失無數個投資機會也不會受到懲罰
  21. 一家公司的cash flow stability 很重要,其攸關這家公司在逆境時,是否有能力去處理債務
  22. Bond Selection的主要目標是避免損失,其過程是一個負面的藝術,他是一個排除與拒絕的過程,而不是搜尋與接受的過程
  23. Bond Selection的safety,取決於發行債券的公司是否能履約,而不是衡量其抵押品或合約
  24. Bond Selection時,你要衡量的是在大蕭條時期的存活能力,而不是看景氣好的時候
  25. Bond Selection的時候要注意,高票面利率(coupon rate)是無法彌補風險的
  26. 當所購買的債券公司違約時,投資人很難透過抵押權來彌補投資損失,因為當公司經營失敗,其所抵押的資產價值會大幅縮水;債權人很難主張其所有擁有的法律權益;以及受到財務管理人的拖延
  27. 挑選債券的時候,基本原則是"避免trouble",而不是試圖在touble中保護自己
  28. 沒有產業可以完全不受不景氣的影響
  29. 債券價格崩盤,很多時候原因並不是營收消失此原因,其主因都是其無力負擔過度擴張的債務所導致
  30. 根據歷史數據顯示,中小型企業不具備穩定的獲利能力,故不適合考慮作為fixed-value investments的投資標的
  31. 投資的錯誤範例是:如果你有錢投資,那就去投資,但是當你找不到好的、安全的投資標的,那你就去買次一等級的投資標的
  32. 巴菲特認為:「一些垃圾債券發行方的管理層本身就是以欺騙為目的在發行垃圾債券。華爾街只關注發行垃圾債券能帶來多少收入,而不關心垃圾債券的後果;一些垃圾債券的買家又從不思考。所以二者一拍即合。」
  33. 作為一個謹慎的、智慧型投資者,你寧可選擇一個最好的債券(即便其收益率較不吸引人),也不要因為較高的票面利率的吸引,去購買次等級的債券,將自己的本金暴露於風險之下
  34. 根據幾次大蕭條的歷史紀錄顯示,即便是擁有良好記錄的公司,也是不可靠的,尤其是中小型企業。故挑選時要符合兩個條件:(1) 挑選績優的大型企業 ;(2) 實質獲利率大於債券利息
  35. 債券與利率的關係,與保險費率類似,其根據風險等級來計算費率。高收益與低收益的回報基本上是相等的,高收益投資的收入會有較大的本金損失的風險,低收益的投資收入的本金損失風險也較低

2016/07/31

[Travel] Kobe (神戶)

風見鶏の館
DSC09798




Starbucks Coffee 神戸北野異人館店
DSC09804

DSC09809



神戶牛
DSC09823



神戸港 Kobe Port
DSC09824

DSC09838

DSC09854

2016/07/09

[PDFBox] No ImageWriter found for 'tif' format in WebSphere

Problem
As I try to convert PDF to TIF via PDFBox in WebSphere 8, I got the error message during the conversion process:
1
2
[Line:198][org.apache.pdfbox.tools.imageio.ImageIOUtil.writeImage]No ImageWriter found for 'tif' format
[Line:206][org.apache.pdfbox.tools.imageio.ImageIOUtil.writeImage]Supported formats: BMP bmp jpg JPG wbmp jpeg png PNG JPEG WBMP GIF gif 


Lacking of jai-imageio-core jar file in your classpath must get this error message.
But I have add jai-imageio-core dependency in pom.xml.
Snippet of pom.xml looks like:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<!-- for generating tif file -->
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox-tools</artifactId>
    <version>2.0.0</version>
</dependency>

<dependency>
    <groupId>com.github.jai-imageio</groupId>
    <artifactId>jai-imageio-core</artifactId>
    <version>1.3.1</version>
</dependency>

Therefore, I try to print log to figure out the weird problem:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 try {
     Enumeration<URL> urls = Thread.currentThread().getContextClassLoader()
             .getResources("META-INF/services/javax.imageio.spi.ImageWriterSpi");
     while (urls.hasMoreElements()) {
         log.info("[convertToTiff] url = " + urls.nextElement().toString());
     }
 
 } catch (IOException e1) {
     e1.printStackTrace();
     throw new RuntimeException(e1);
 }

 The jar file exists in my ear file ! What happened?
1
 [convertToTiff] url = wsjar:file:/usr/IBM/WebSphere/AppServer/profiles/AppSrv03/installedApps/FDCSRA205Node03Cell/yuantalife-ecp-manage.ear/yuantalife-ecp-manage-war-0.1.0-SNAPSHOT.war/WEB-INF/lib/jai-imageio-core-1.3.1.jar!/META-INF/services/javax.imageio.spi.ImageWriterSpi

Here is my source code:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package albert.practice.file;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;

import javax.imageio.ImageIO;

import lombok.extern.slf4j.Slf4j;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.tools.imageio.ImageIOUtil;

@Slf4j
public class PdfFileToTif {

    private final float dpi = 300f;

    public static void main(String[] args) {
        File pdfFile = new File("D:\\dropbox\\Getting Started.pdf");
        String destination = "D:\\dropbox\\";

        PdfFileToTif test = new PdfFileToTif();
        test.checkImageIoJarFile();
        test.convertPdfToTif(pdfFile, destination);
    }

    public void convertPdfToTif(File pdfFile, String destination) {
        if (!isFileExisted(pdfFile)) {
            throw new RuntimeException("File not found ! (" + pdfFile.getAbsolutePath() + ")");
        }

        String pdfFileName = pdfFile.getName();

        try {
            // load PDF document
            PDDocument document = PDDocument.load(pdfFile);

            // create PDF renderer
            PDFRenderer renderer = new PDFRenderer(document);

            // go through each page of PDF, and generate TIF for each PDF page.
            for (int i = 0; i < document.getNumberOfPages(); i++) {
                // Returns the given page as an RGB image with 300 DPI.
                BufferedImage image = renderer.renderImageWithDPI(i, dpi, ImageType.BINARY);

                // Assign the file name of TIF
                String fileName = pdfFileName + "_" + String.format("%02d", i + 1);
                log.debug("Generating  " + fileName + ".tif to " + destination);

                // Writes a buffered image to a file using the given image format.
                ImageIOUtil.writeImage(image, destination + fileName + ".tif", Math.round(dpi));
                image.flush();
            }
            log.debug("PDF to TIF conversion well done!");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 判斷檔案是否存在
     * 
     * @param file
     * @return true - 檔案存在; false - 檔案不存在
     */
    private Boolean isFileExisted(File file) {
        Boolean isExisted = Boolean.FALSE;
        isExisted = (file.exists() && (!file.isDirectory()));
        return isExisted;
    }

    private void checkImageIoJarFile() {
        try {
            Enumeration<URL> urls = Thread.currentThread().getContextClassLoader()
                    .getResources("META-INF/services/javax.imageio.spi.ImageWriterSpi");
            while (urls.hasMoreElements()) {
                log.info("[convertToTiff] urls = " + urls.nextElement().toString());
            }

        } catch (IOException e1) {
            e1.printStackTrace();
            throw new RuntimeException(e1);
        }
    }
}


How-to
The root cause is not so clear. It may results from WebSphere's classloading problem.
Hence, I find an API to scans for plug-ins on the application class path, loads their service provider classes, and registers a service provider instance for each one found with the IIORegistry. This strange problem had been resolved as I add ImageIO.scanForPlugins();

Here is my updated source code (Line46):
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package albert.practice.file;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;

import javax.imageio.ImageIO;

import lombok.extern.slf4j.Slf4j;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.tools.imageio.ImageIOUtil;

@Slf4j
public class PdfFileToTif {

    private final float dpi = 300f;

    public static void main(String[] args) {
        File pdfFile = new File("D:\\dropbox\\Getting Started.pdf");
        String destination = "D:\\dropbox\\";

        PdfFileToTif test = new PdfFileToTif();
        test.checkImageIoJarFile();
        test.convertPdfToTif(pdfFile, destination);
    }

    public void convertPdfToTif(File pdfFile, String destination) {
        if (!isFileExisted(pdfFile)) {
            throw new RuntimeException("File not found ! (" + pdfFile.getAbsolutePath() + ")");
        }

        String pdfFileName = pdfFile.getName();

        try {
            // load PDF document
            PDDocument document = PDDocument.load(pdfFile);

            // Scans for plug-ins on the application class path, loads their service provider
            // classes, and registers a service provider instance for each one found with the
            // IIORegistry.
            ImageIO.scanForPlugins();

            // create PDF renderer
            PDFRenderer renderer = new PDFRenderer(document);

            // go through each page of PDF, and generate TIF for each PDF page.
            for (int i = 0; i < document.getNumberOfPages(); i++) {
                // Returns the given page as an RGB image with 300 DPI.
                BufferedImage image = renderer.renderImageWithDPI(i, dpi, ImageType.BINARY);

                // Assign the file name of TIF
                String fileName = pdfFileName + "_" + String.format("%02d", i + 1);
                log.debug("Generating  " + fileName + ".tif to " + destination);

                // Writes a buffered image to a file using the given image format.
                ImageIOUtil.writeImage(image, destination + fileName + ".tif", Math.round(dpi));
                image.flush();
            }
            log.debug("PDF to TIF conversion well done!");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 判斷檔案是否存在
     * 
     * @param file
     * @return true - 檔案存在; false - 檔案不存在
     */
    private Boolean isFileExisted(File file) {
        Boolean isExisted = Boolean.FALSE;
        isExisted = (file.exists() && (!file.isDirectory()));
        return isExisted;
    }

    private void checkImageIoJarFile() {
        try {
            Enumeration<URL> urls = Thread.currentThread().getContextClassLoader()
                    .getResources("META-INF/services/javax.imageio.spi.ImageWriterSpi");
            while (urls.hasMoreElements()) {
                log.info("[convertToTiff] urls = " + urls.nextElement().toString());
            }

        } catch (IOException e1) {
            e1.printStackTrace();
            throw new RuntimeException(e1);
        }
    }
}




Reference 
[1] http://stackoverflow.com/questions/17178591/how-to-add-tiff-imagereader-to-those-registered-in-grails