Total Pageviews

2016/05/04

[XStream] How to create XML via XStream (a more complex example)

Requirement
The XSD for xml is as following:
 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
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Root">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="Attributes">
          <xs:complexType>
            <xs:sequence>
              <xs:element type="xs:string" name="WorkLoad"/>
              <xs:element type="xs:string" name="DetailDocCat"/>
              <xs:element type="xs:string" name="ScanDate"/>
              <xs:element type="xs:time" name="ScanTime"/>
              <xs:element type="xs:float" name="StockingNumber"/>
              <xs:element type="xs:string" name="CaseId"/>
              <xs:element name="PolicyNumbers">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element type="xs:string" name="PolicyNumber" maxOccurs="unbounded" minOccurs="0"/>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
              <xs:element name="ProposalNums">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element type="xs:string" name="ProposalNum" maxOccurs="unbounded" minOccurs="0"/>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

The resulting XML looks like this:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<Root>
  <Attributes>
    <WorkLoad>TW_NEWNBED</WorkLoad>
    <DetailDocCat>xxx要保書</DetailDocCat>
    <ScanDate>2016/03/02</ScanDate>
    <ScanTime>15:56:00</ScanTime>
    <StockingNumber>2016E000001</StockingNumber>
    <CaseId>ABCD-201600100001</CaseId>
    <PolicyNumbers>
      <PolicyNumber>A12345678</PolicyNumber>
    </PolicyNumbers>
    <ProposalNums>
      <ProposalNum>B87654321</ProposalNum>
    </ProposalNums>
  </Attributes>
</Root>


How-to
Step1. According xsd definition, creating classes to be serialized

Root class looks like this:
 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
package albert.practice.xstream.beans;

import java.io.Serializable;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

public class Root implements Serializable {

 private static final long serialVersionUID = 1L;

 private Attributes Attributes;

 public Attributes getAttributes() {
  return Attributes;
 }

 public void setAttributes(Attributes Attributes) {
  this.Attributes = Attributes;
 }

 @Override
 public String toString() {
  return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
 }
}


Attributes class looks like this:
 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
96
97
package albert.practice.xstream.beans;

import java.io.Serializable;
import java.util.List;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

public class Attributes implements Serializable {

 private static final long serialVersionUID = 1L;

 private String WorkLoad;

 private String DetailDocCat;

 private String ScanDate;

 private String ScanTime;

 private String StockingNumber;

 private String CaseId;

 private List<PolicyNumbers> PolicyNumbers;

 private List<ProposalNums> ProposalNums;

 public String getWorkLoad() {
  return WorkLoad;
 }

 public void setWorkLoad(String WorkLoad) {
  this.WorkLoad = WorkLoad;
 }

 public String getDetailDocCat() {
  return DetailDocCat;
 }

 public void setDetailDocCat(String DetailDocCat) {
  this.DetailDocCat = DetailDocCat;
 }

 public String getStockingNumber() {
  return StockingNumber;
 }

 public void setStockingNumber(String StockingNumber) {
  this.StockingNumber = StockingNumber;
 }

 public List<PolicyNumbers> getPolicyNumbers() {
  return PolicyNumbers;
 }

 public void setPolicyNumbers(List<PolicyNumbers> policyNumbers) {
  PolicyNumbers = policyNumbers;
 }

 public String getCaseId() {
  return CaseId;
 }

 public void setCaseId(String CaseId) {
  this.CaseId = CaseId;
 }

 public String getScanDate() {
  return ScanDate;
 }

 public void setScanDate(String ScanDate) {
  this.ScanDate = ScanDate;
 }

 public String getScanTime() {
  return ScanTime;
 }

 public void setScanTime(String ScanTime) {
  this.ScanTime = ScanTime;
 }

 public List<ProposalNums> getProposalNums() {
  return ProposalNums;
 }

 public void setProposalNums(List<ProposalNums> proposalNums) {
  ProposalNums = proposalNums;
 }

 @Override
 public String toString() {
  return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
 }
}


PolicyNumbers looks like this:
 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
package albert.practice.xstream.beans;

import java.io.Serializable;
import java.util.List;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

public class PolicyNumbers implements Serializable {

 private static final long serialVersionUID = 1L;

 private String PolicyNumber;
 private List<PolicyNumbers> PolicyNumberList;

 public List<PolicyNumbers> getPolicyNumberList() {
  return PolicyNumberList;
 }

 public void setPolicyNumberList(List<PolicyNumbers> policyNumberList) {
  PolicyNumberList = policyNumberList;
 }

 public PolicyNumbers(String policyNumber) {
  this.PolicyNumber = policyNumber;
 }

 public String getPolicyNumber() {
  return PolicyNumber;
 }

 public void setPolicyNumber(String policyNumber) {
  this.PolicyNumber = policyNumber;
 }

 public PolicyNumbers() {
  super();
 }

 @Override
 public String toString() {
  return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
 }
}


ProposalNumbers looks like this:
 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
package albert.practice.xstream.beans;

import java.io.Serializable;
import java.util.List;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

public class ProposalNums implements Serializable {

 private static final long serialVersionUID = 1L;

 private String ProposalNum;
 private List<ProposalNums> ProposalNumList;

 public String getProposalNum() {
  return ProposalNum;
 }

 public void setProposalNum(String proposalNum) {
  ProposalNum = proposalNum;
 }

 public List<ProposalNums> getProposalNumList() {
  return ProposalNumList;
 }

 public void setProposalNumList(List<ProposalNums> proposalNumList) {
  ProposalNumList = proposalNumList;
 }

 public ProposalNums(String proposalNum) {
  super();
  ProposalNum = proposalNum;
 }

 public ProposalNums() {
  super();
 }

 @Override
 public String toString() {
  return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
 }

}


Step2. Utilize XStream API to fulfill our requirement
 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
public class XStreamTestClient {

 public static void main(String[] args) throws IOException {

  // create an instance of beans and populate its fields:
  Attributes attribute = new Attributes();
  attribute.setWorkLoad("TW_NEWNBED");
  attribute.setDetailDocCat("xxx要保書");
  attribute.setScanDate("2016/03/02");
  attribute.setScanTime("15:56:00");
  attribute.setStockingNumber("2016E000001");
  attribute.setCaseId("ABCD-201600100001");

  List<PolicyNumbers> policyNumberList = new ArrayList<PolicyNumbers>();
  policyNumberList.add(new PolicyNumbers("A12345678"));

  attribute.setPolicyNumbers(policyNumberList);

  List<ProposalNums> proposalNumList = new ArrayList<ProposalNums>();
  proposalNumList.add(new ProposalNums("B87654321"));

  attribute.setProposalNums(proposalNumList);

  Root root = new Root();
  root.setAttributes(attribute);

  String xml = new XStreamTestClient().toXml(root);
  System.out.println(xml);

 }

 public String toXml(Root root) {
  // instantiate the XStream class
  XStream xStream = new XStream();

  // create an alias to the desired class:
  xStream.alias("Root", Root.class);
  xStream.alias("PolicyNumbers", PolicyNumbers.class);
  xStream.alias("ProposalNums", ProposalNums.class);

  // whenever you have a collection which doesn't need to display it's
  // root tag, you can map it as an implicit collection
  xStream.addImplicitCollection(Attributes.class, "PolicyNumbers");
  xStream.addImplicitCollection(Attributes.class, "ProposalNums");

  return xStream.toXML(root);
 }
} 




2016/05/03

[XStream] How to create XML via XStream

Requirement
If we would like to generate a xml file like this:
1
2
3
4
5
6
7
<doc>
  <regId>123456</regId>
  <ownerId>A123456789</ownerId>
  <policyNumber>TA800000001</policyNumber>
  <insuredId>B123456789</insuredId>
  <formId>A00123</formId>
</doc>

How to do it?


How-to
We can make good use of XStream to help us to implement this requirement easily.

Add XStream dependency to your pom.xml
1
2
3
4
5
        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.8</version>
        </dependency>


Step1. Create a simple class to correspond to xml tags.
  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
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package albert.practice.xstream.beans;

import java.io.Serializable;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

public class Doc implements Serializable {

 private static final long serialVersionUID = 1L;

 // 訂單編號
 private String regId;

 // 要保人ID
 private String ownerId;

 // 保單號碼
 private String policyNumber;

 // 被保人 ID
 private String insuredId;

 // 表單代碼
 private String formId;

 /**
  * Gets the reg id.
  * 
  * @return the reg id
  */
 public String getRegId() {
  return regId;
 }

 /**
  * Sets the reg id.
  * 
  * @param regId
  *            the new reg id
  */
 public void setRegId(String regId) {
  this.regId = regId;
 }

 /**
  * Gets the owner id.
  * 
  * @return the owner id
  */
 public String getOwnerId() {
  return ownerId;
 }

 /**
  * Sets the owner id.
  * 
  * @param ownerId
  *            the new owner id
  */
 public void setOwnerId(String ownerId) {
  this.ownerId = ownerId;
 }

 /**
  * Gets the policy number.
  * 
  * @return the policy number
  */
 public String getPolicyNumber() {
  return policyNumber;
 }

 /**
  * Sets the policy number.
  * 
  * @param policyNumber
  *            the new policy number
  */
 public void setPolicyNumber(String policyNumber) {
  this.policyNumber = policyNumber;
 }

 /**
  * Gets the insured id.
  * 
  * @return the insured id
  */
 public String getInsuredId() {
  return insuredId;
 }

 /**
  * Sets the insured id.
  * 
  * @param insuredId
  *            the new insured id
  */
 public void setInsuredId(String insuredId) {
  this.insuredId = insuredId;
 }

 /**
  * Gets the form id.
  * 
  * @return the form id
  */
 public String getFormId() {
  return formId;
 }

 /**
  * Sets the form id.
  * 
  * @param formId
  *            the new form id
  */
 public void setFormId(String formId) {
  this.formId = formId;
 }

 /**
  * {@inheritDoc}
  */
 @Override
 public String toString() {
  return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
 }

}


Step2. Serialize object to XML via XStream API
 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
package albert.practice.xstream;

import com.thoughtworks.xstream.XStream;

import albert.practice.xstream.beans.Doc;

public class XStreamTest2 {

 public static void main(String[] args) {

  // prepare bean for XML
  Doc doc = new Doc();
  doc.setRegId("123456");
  doc.setOwnerId("A123456789");
  doc.setPolicyNumber("TA800000001");
  doc.setInsuredId("B123456789");
  doc.setFormId("A00123");

  // Initializing XStream
  XStream xStream = new XStream();

  // create an alias called doc to the desired class (Doc)
  xStream.alias("doc", Doc.class);

  // Serializing an object to XML
  String xml = xStream.toXML(doc);

  // print XML
  System.out.println(xml);
 }

}


Reference
[1] http://x-stream.github.io/tutorial.html

2016/05/02

[閱讀筆記] 圖解國富論 Part 2



  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. 對外貿易是指透過剩餘產物來交換能滿足國內需求,並增加享受其他物品的方式,對外貿易能賦予剩餘產物價值。自由貿易能夠帶來共同的繁榮和進步。

2016/05/01

[閱讀筆記] 你還在努力省錢來投資理財嗎? Part 2



  1. 你該借支退休計畫來支付抵押貸款,還是冒著失去房子的風險?在諸如此類的掙扎中,長期目標常敗給短期需求 。這種累積效應,會讓個人面臨無積蓄的退休生活
  2. 401(K)計畫是把責任轉移到勞動者,逼迫他們像專業理財顧問那樣儲蓄,這會助長高所得者,而高所得者以利己方式儲蓄,並將人類活動轉向資產分配與共同基金業務
  3. 財經領域專家相信,美國人至少要存一百萬美元才夠過後工作時代的生活,而這個數字,只有8%的家庭可以達成
  4. 401(K)計畫是如何鼓勵高所得者以利己的方式儲蓄?看看這個數字,社會頂層10%的家庭擁有80%的股票與共同基金。如果擴大到20%的家庭,後面的數字會攀升到90%
  5. 投資是有風險的,沒有任何保證
  6. 我們多數人為退休所做的投資,只是基於一個未經證實的假設
  7. S&P 500從1927~2011年的平均年化報酬率是9.75%(扣除服務費前),但在1999~2009年間,平均報酬卻是-0.5%
  8. 請注意,每一份財務說明說最底下都會列的那行字:過去績效不代表未來獲利的保證
  9. 複利的魔法,最重要的是投資和儲蓄策略的最後十年。如果你的最後十年是1989~1999年,你的退休可能相當美妙,複利起了作用。但是如果你的最後十年是2000年代,那十年不但無法讓你的資金倍增,連保住本金都有困難
  10. 401(K)最終要達成廣告宣稱的績效,投資人不僅要有紀律的存款,還不能遇到重病、失業或離婚等不幸。投資人還必須了解投資的基本原理。所以401(K)確實對高所得有利,401(K)變成他們節稅的儲蓄工具,尤其對賺大錢的人最有效
  11. 許多理財謀士的謀生之道,是靠賣給我們特定的商品,賺取佣金
  12. 行為財務學教我們兩件事:要不就克服不理性的心理,成為更優秀的投資人;要不就丟毛巾投降,把資金交給指數化的策略
  13. 要注意,高效益與安全的承諾,兩者是牴觸的
  14. 個股交易是一種輸家遊戲,犯錯最少的人才是贏家。那我們幹嘛玩?因為不是每個人都玩不好,至少有Buffett、Peter Lynch都玩得不錯,或許,只是或許,還有你
  15. 在投資的世界,無論賺賠,交易者都要支付交易費用
  16. 選擇權是一種權利契約,係指在未來約定之日期,依照約定的價格買入或賣出約定的股票
  17. 華爾街做的是不利顧客的生意,靠犧牲投資大眾來獲取利益;當沖交易則是靠犧牲華爾街來獲利,以其人之道還治其人之身
  18. 你自己要問業務員,如果他們的投資工具與投資標的真的這麼棒,他們為什麼還要費盡時間與心力來賣給你我
  19. 除非你在正確的時間找到適當的大師,長久而言,指數型基金或許對你比較有利
  20. 我們可以學到的教訓是,如果看起來好得過頭了,或許就不是真的


2016/04/30

2016/04 Travel

舊草嶺環狀線自行車道一隅



2016/04/10

[Java Mail] Embed Images into Email

Requirement
If we would like embed a image file into Email as bellows:

How to do it?

How-To
In the velocity template file, we define a image tag and define a cid (content id):
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<html>
   <body>
      <p>親愛的保戶您好</p>
      <p>     </p>
      <p>感謝您對xxxx的支持,您在網路上申請的旅平險保單已投保完成,以下是您的投保明細,供您參考。</p>
      <p>【投保內容】</p>
      <p>保單號碼: ${customer.policyNumber}</p>
      <p>被保險人: ${customer.name}</p>
      <p>申請日期: ${customer.applyDate}</p>
      <p>保險期間: ${customer.fromDate} ~ ${customer.toDate}</p>
      <p>旅遊地點: ${customer.place}</p>
      <p></p>
      <p>※保險單及保險費送金單將於近日內寄至要保人所指定之聯絡地址。</p>
      <p></p>
      <p>                     敬祝  闔家平安 </p>
      <p><img src="cid:panda"></p>
   </body>
</html>

Here is code snippet:
 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
96
97
98
99
 public static void main(String[] args) throws IOException, MessagingException {

  ApplicationContext context = new ClassPathXmlApplicationContext("spring-beans.xml");
  VelocityEngine velocityEngine = (VelocityEngine) context.getBean("velocityEngine");

  // set value to template
  Customer customer = new Customer();
  customer.setPolicyNumber("12345678");
  customer.setName("測試");
  customer.setApplyDate("20160325");
  customer.setFromDate("20160401");
  customer.setToDate("20160410");
  customer.setPlace("日本關西");

  // set customer to map for velocity email template
  Map<String, Object> model = new HashMap<String, Object>();
  model.put("customer", customer);

  // get email content from velocity email template
  String mailTemplate = "albert/practice/mail/templates/insurance.vm";
  String content = VelocityEngineUtils.mergeTemplateIntoString(velocityEngine, mailTemplate, "UTF-8", model);

  // set file attachments
  File pdfFile = new File("/Users/albert/Dropbox/Getting Started.pdf");
  File mindmapFile = new File("/Users/albert/Dropbox/eBooks//The Intelligent Investor.png");

  List<File> attachments = new ArrayList<File>();
  attachments.add(pdfFile);
  attachments.add(mindmapFile);

  // set email parameters
  EmailParams params = new EmailParams();
  params.setReceiverEmail("junyuo@gmail.com");
  params.setSubject("網路投保完成通知");
  params.setContent(content);
  params.setAttachments(attachments);

  new MailTest().sendMail(params);
 }

 public void sendMail(EmailParams params) {

  JavaMailSenderImpl sender = getJavaMailSender();
  MimeMessage message = sender.createMimeMessage();

  List<File> attachemtns = null;

  try {
   MimeMessageHelper helper = new MimeMessageHelper(message, true);
   helper.setTo(params.getReceiverEmail());
   helper.setSubject(params.getSubject());
   helper.setText(params.getContent(), true);

   // add attachment(s)
   if (params.getAttachments() != null && params.getAttachments().size() > 0) {
    attachemtns = params.getAttachments();
    for (int i = 0; i < attachemtns.size(); i++) {
     FileSystemResource attachment = new FileSystemResource(attachemtns.get(i));
     helper.addAttachment(attachemtns.get(i).getName(), attachment);
    }
   }

   // embed image in email
   InputStreamSource logo = new ByteArrayResource(
     IOUtils.toByteArray(getClass().getResourceAsStream("img/panda.png")));
   helper.addInline("panda", logo, "image/png");

  } catch (MessagingException e) {
   throw new RuntimeException(e);
  } catch (IOException e) {
   throw new RuntimeException(e);
  }
  sender.send(message);
  System.out.println("mail sent..");
 }

 

 private JavaMailSenderImpl getJavaMailSender() {
  // enable starttls
  Properties props = new Properties();
  props.put("mail.smtp.starttls.enable", "true");

  // mail server configuration
  String host = "smtp.gmail.com";
  int port = 587;
  String userName = "xxxx";
  String password = "xxxx";

  JavaMailSenderImpl sender = new JavaMailSenderImpl();
  sender.setJavaMailProperties(props);
  sender.setHost(host);
  sender.setPort(port);
  sender.setUsername(userName);
  sender.setPassword(password);
  sender.setDefaultEncoding("UTF-8");

  return sender;
 }

Remember to update your maven dependency:
 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
 <!-- email -->
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4.7</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>jaf</groupId>
            <artifactId>activation</artifactId>
            <version>1.0.2</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-mail</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>

        <!-- velocity -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity</artifactId>
            <version>1.7</version>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-tools</artifactId>
            <version>2.0</version>
        </dependency>


Reference
[1] http://www.rgagnon.com/javadetails/java-0504.html