因為需要嘗試透過 Telnet 登入 PTT,雖然理論上覺得 PTT 的 Android App 這麼多,應該不會找不到可以引用的 Open Source
但實際找了,好像還真的找不太到 @@
最後是參考了 Github 上的一個開源專案 [1],擷取了其中連線和取得畫面的部份作為這次的實驗~。
Software entities (class, modules, functions, etc.) should be open for extension, but closed for modification. Junior programmers create simple solutions to simple problems. Senior programmers create complex solutions to complex problems. Great programmers find simple solutions to complex problems. 註1:本部落格的範例程式碼在 2015 年以前的文章中,大多是以全型空白做縮排。如需服用,請自行用文字編輯器的取代功能把全型空白取代成半型空白。
- Bertrand Meyer
- Charles Connell
註2:本部落格的內容授權請參閱部落格底部的授權宣告。
2016年12月27日 星期二
使用 Java 連上 PTT
2016年12月26日 星期一
2016年12月23日 星期五
Maven BOM (bill of materials)
在比較大型的專案中使用 Maven,有頗高的機率會遇到版本衝突的問題
例如 project A 使用了 guava 的某個 15 版才開始有的功能,而 project B 則是引用了 guava v14
接著有一個新的專案 project C,必須要同時引用 project A 和 project B,這時會發生什麼事呢?
有可能會造成最後打包出來的專案,裡面實際上被打包的是 guava v14
因而導致了在執行時,執行到 project A 的程式碼,就遇到 class/method not found 之類的錯誤訊息。
在 Maven 中,針對這個問題有一些基礎的解法 [1]
當同樣的套件被重複引用時,Maven 的基礎規則是誰先寫就看誰
但畢竟在遇到某些動態載入之類的情境時,並不是那麼容易可以決定誰先寫
更何況遇到的如果是 guava 這種被大量引用的函式庫,其實我們不見得能夠清楚地知道到底有哪些函式庫用了它。
因此,在基礎的解法之上的下個階段,就是利用 dependencyManagement 來指派版本了。
具體來說,dependencyManagement 的指派好像有兩種用法,一種是建立父子關係,另一種則是 BOM
詳細的範例其實都可以參考官方文件 [1],這裡紀錄的是 BOM。
2016年12月21日 星期三
變更已經啟動的 Container 的 Port Mapping
在使用 Docker 時,有時會遇到當初開啟 Container 時沒有預期到的 Port Mapping 需求
例如我有個服務本來是把 443 port 轉到 11111 port,但因為想要做 SSL 測試,而測試網站只支援 443 port
因此至少在測試階段需要把服務開回到 443 port 上。
一般查到的作法不外乎是把既有的 Container 做成 image,然後重開一個新的
不過發現另一個方法,可以透過改設定的方式,在不需要重開 Container 的情況下就達到變更的目的。
2016年11月17日 星期四
URL Encode
在寫 RESTful API 的測試案例時,遇到需要在 URL 路徑上寫空白的問題
如果使用 URLEncoder,空白會被編碼成 +,然後在 Jersey 端 + 並不會被編回空白。
簡單查了一下,實際上這個問題是誤用,URLEncoder 事實上是用在 URL 參數的工具
而把空白編成 + 則是 application/x-www-form-urlencoded 的標準作法。
因此,真正的問題在於不該使用 URLEncoder 去編碼 URL 路徑
但如果是片段的 URL,又沒辦法直接使用 new URI() 的樣子~
可以參考 [2] 的回應,使用 new URI(null, xxx, null).toASCIIString()。
另外,如果某個 Path 變數需要帶有 /,則可以手動用 String.replace() 方法,把 / 置換成 %2f"。
至少這樣在 Jersey 上是不會錯,但不保證所有的情境都可以這樣就是了 [3]。
參考資料
2016年11月11日 星期五
在 Windows 上變更 Maven 預設路徑
Maven 預設會在 ${user.home}/.m2/repository 這個路徑內存放所有下載回來的函式庫
不過如果電腦是用 SSD 當系統碟時,就會覺得這樣有點討厭 XD
想要更改路徑的話,只需要在 Maven 的設定檔上加上 localRepository 標籤,指定新的路徑即可。
例如在 ${user.home}/.m2/settings.xml 裡寫上以下的內容,即可把 Maven 存放函式庫的位置移到 D:\maven 裡。
<settings> <localRepository>D:\maven</localRepository> </settings>
參考資料
2016年10月20日 星期四
在全新的 Tomcat 8 設定 HTTPS
前面的文章成功在 Apache2 設定 HTTPS 之後,接著要在 Tomcat 8 上也設定 HTTPS。
環境一樣是要用全新的 Tomcat,因此流程也會包含環境建置。
而金鑰跟憑證的部份跟前面一樣,由 Godaddy 給予的兩個檔案:fe461f1ba212ab7.crt 和 gd_bundle-g2-g1.crt
以及事先產生好的金鑰檔 my-private-key.key。
在全新的 Apache 2.4 設定 HTTPS
在完成跟 GoDaddy 申請憑證之後,Godaddy 網站上可以取得兩個 CRT 檔
我這邊拿到的,一個是命名很像亂碼的 fe461f1ba212ab7.crt 檔案,另一個則是 gd_bundle-g2-g1.crt。
fe461f1ba212ab7.crt 這個檔案是 SSL Certificate File,而 gd_bundle-g2-g1.crt 則是 SSL Certificate Chain File
加上申請憑證前,我們需要自行先產生的金鑰,假設檔名是 my-private-key.key
總共有三個檔案,就可以完成 Apache 2.4 的 HTTPS 設定了。
2016年10月18日 星期二
在 Docker 中安裝 Bugzilla
這篇是簡單紀錄 Bugzilla 的安裝流程,流程中會以 Docker 1.12.0 來部署需要的服務。
Bugzilla 官方提供的安裝文件可以參考 [1]。
2016年10月9日 星期日
GTX650 穩定性問題
本來在玩遊戲時,電腦會頻繁地跳出遊戲畫面,或者是遊戲程式崩潰等等
原先以為問題顯示器驅動程式停止回應
但即使在依照那些方式做了調整後,依然在某些遊戲中會遇到跳出的問題(只是不會有驅動程式停止回應的訊息)
後來又繼續查了一段時間後,發現 [1] 這篇文章
就照著文章最後說的,去調整 PCI-E 的版本,從 PCI-E 3.0 改為 PCI-E 2.0,就….好像是完全好了…..。
不確定結果問題是 EVGA 的顯示卡對 PCI-E 3.0 支援有異常,還是特定一群主機板晶片組對 PCI-E 3.0 支援都有問題
總之應該不用考慮要換顯卡了….。
PS. 我的主機板晶片是 H87M。
參考資料
2016年10月4日 星期二
2016年9月19日 星期一
2016年9月10日 星期六
Gson 基礎使用:序列化與反序列化時,使用不同的名稱
在利用 Gson 做自動序列化與反序列化時,有時會遇到有點特殊的需求
就是序列化與反序列化時,想要使用不同的名稱。
實務上比較直覺的狀況是,某個物件是要從資料庫取出的,然後要將物件內容透過 JSON 格式輸出給使用者
但是又不希望使用者可以直接從 JSON 格式看見資料庫的結構,因此會嘗試至少把名字換掉 XD
(雖然這個例子看起來好像只是鴕鳥心態就是了 XD)
2016年9月7日 星期三
自定義 Logback 的 Encoder
想要試著自定義一個可以產出 JSON 格式的 log
雖然之前已經有 PO 過 logstash 提供的 Encoder,就可以達到把 log 輸出成 JSON 的目的
不過基於某些無聊的理由,還是想要自己寫看看 XD。
2016年9月6日 星期二
SLF4J 與 Logback 的運作流程
最近因為工作需要,開始在研究如何自定義 logback 的 Appender
不過在開始嘗試實作之前,因為想要知道整個 slf4j 到 logback 等的整個執行流程為何
因此就做了這篇的簡單的研究。
2016年9月5日 星期一
2016年8月24日 星期三
Docker container 的實體路徑
Docker 創造出來的 container,各自的實體路徑是在以下的位置:
/var/lib/docker/devicemapper/mnt/<container id>/rootfs/
參考資料
Apache 2 SSL 的 Passphrase 問題
在 Apache 2 裡,如果要使用有被 Passphrase 保護的 key 給 SSL 使用
必須在某處提供 SSL 的 Passphrase 才能讓 Apache 正常啟動。
一般內建的方法是使用 builtin,也就是 Apache 啟動時會直接詢問使用者
其他方法則是可以把 Passphrase 寫在某個檔案裡,要 Apache 啟動時去讀取。
而寫設定的地方,在我的 container 中是放在 /etc/apache2/mods-enabled/ssl.conf 裡。
如果是不想那麼麻煩地處理 Passphrase 問題,想把他從金鑰中移掉
則可以參考 [2] 的方法,只需要指定輸入和輸出的金鑰檔名,然後輸入 Passphrase
就可以重製出一個不需要 Passphrase 的金鑰了。
以 RSA 的金鑰來說,指令如下:
openssl rsa -in /path/to/your/rsakey.key -out /path/to/your/rsa.nocrypt.key
參考資料
2016年8月9日 星期二
(書籤) SSL 憑證
參考資料:
- [筆記] SSL 憑證購買記
- 憑證簽章要求 (CSR) 產生說明 - Apache SSL
- OpenSSL - 金鑰與憑證的管理
- 使用 openssl 產生 SSL 電子證書
- Apache Requires SSL / Passphrase
- Difference between OpenSSL and keytool
- OpenSSL 操作筆記 - 檔案格式轉換
- Difference between trustStore and keyStore in Java – SSL
- How to add or list certificates from keystore or trustStore in Java - Keytool Example
- Re:[問題] URLConnection 產生了HTTP 405 Exception [Re:piaoyi]
2016年8月4日 星期四
2016年7月26日 星期二
(書籤) codegen
General code generator for Java
Libraries for Generating Java Codes
Libraries for Generating Maven
Swagger’s code generator
2016年7月25日 星期一
Amazon Beanstalk 的應用程式位置
隨筆紀錄,如果把 Java 程式部署到 Beanstalk 上
預設在 Beanstalk 的路徑會是 /var/app/current/application.jar。
2016年7月4日 星期一
透過 Gson 輸出 pretty print 的 JSON
當使用 Gson 來解析 JSON 格式時,如果需要讓輸出的 JSON 以 pretty print 格式輸出
可以利用簡單的小工具達成這個目的。
Gson gsonBuilder = new GsonBuilder().setPrettyPrinting().create(); gsonBuilder.toJson(....);
不過 Gson 的這個工具,預設會自動做 HTML 跳脫,因此特殊符號都會自動被置換成 Unicode 表示形式
如果想要關掉 HTML 跳脫,可以使用 .disableHtmlEscaping() 方法。
Gson gsonBuilder = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); gsonBuilder.toJson(....);
2016年7月2日 星期六
對 Jersey 製作的 RESTful API 做單元測試(二):啟用 Servlet
Jersey 中使用 Jersey Test Framework 做測試時
如果遇到需要使用 Servlet 的狀況,例如使用了 @Context HttpServletRequest request
可能就會注意到,HttpServletRequest 這類應該要自動被注入的東西,在測試時都沒有被注入
因此會發生像是 NullPointerException 等等的錯誤。
2016年6月20日 星期一
在 Java 中解析、表達與計算日期時間(二):JSR-310 概述
原本在 Java 7 和更之前的版本中,因為 Java 原生並沒有好的時間類別
因此比較合適的方式是使用 Joda-Time 這個套件,用來表示日期與時間。
不過在 Java 8 當中釋出了 JSR-310,也就是 java.time 套件之後,狀況就不同了
Joda-Time 官方網站中也說明了,如果使用 Java 8 以上版本,應轉移至 JSR-310。
Joda-Time is the de facto standard date and time library for Java prior to Java SE 8. Users are now asked to migrate to java.time (JSR-310).
2016年6月19日 星期日
在 Java 中解析、表達與計算日期時間(一):時間系統與曆法
對大多數人(包括我)來說,大概都不會覺得日期時間有什麼特別的
在參加之前的 Java TWO 以前,其實我也沒有認真看待過這個東西,一直到在 Java TWO 上聽到良葛格談到這個議題
才知道~其實背後隱藏了許多魔鬼,導致這個議題事實上是個相當複雜的問題。
在開始研究如何正確地寫日期與時間相關的程式之前,先了解一下何謂時間、以及時間和曆法的關係為何。
2016年6月16日 星期四
使用 JAX-RS 2 做 HTTP Response 的壓縮
因為前陣子看了一些 RESTful API 的最佳實例(連結可以參考這裡)
裡面有提到好的 RESTful API 應該要支援 GZIP 壓縮,對伺服器端或者客戶端都有好處
因此開始在實作 RESTful API 時,就搜尋了一下,Jersey 上應該如何正確地支援 GZIP 壓縮。
對於「正確地支援 GZIP 壓縮」這個問題,當然最簡單的作法,就是每個 RESTful API 都各自把輸出的東西都呼叫 GZIP 壓縮
然後把壓縮好的結果丟去 Response,並且適當地加上 HTTP Header 即可。
但我覺得這種作法應該不是最好的作法,應該有更好的方式可以讓 Jersey 自動幫每個 Response 都做好這些事。
在 Jersey 上,這件事情最適合的方式就是透過 Interceptors 來實作了。
2016年6月15日 星期三
對 Jersey 製作的 RESTful API 做單元測試(一)
在比較完整的專案中,一般都會至少要包含自動化的單元測試
不過 Application 還好,如果是 RESTful API 的話,應該要怎麼測試呢?
原先我自己的想法是使用 JUnit,然後可能是使用內嵌式的 Jetty
讓測試程式執行時,自動打開一台本地端的 Jetty、把專案佈署上去後開始執行測試。
但既有找到的方法(例如 [1]) 感覺整合性都不太高…。
最後想說,也許其實有更簡易的方式,於是變更了關鍵字之後,發現…真的有 XD。
Jersey 原來本身就有涵蓋了對應的測試架構了。
叢集環境的 logging(三):以 JSON 格式輸出 log
在把叢集中的每個 Application 的 log 都集中起來以後,下一個遇到的問題就是如何分析?
收集起來的 log 數量通常不小,而且各個不同節點的 log 全混在一起
要如何有效率一點地解析他們呢?
實務上,比較容易想像的方式大概就是把 log 導到某個能夠做 log 分析的系統上
例如 ELK 架構(Elasticsearch + Logstash + Kibana)。
不過要讓 Logstash 能夠簡單地把集中起來的 log 全部帶走,最好還是能讓 log 都以 JSON 格式輸出
這樣在 Logstash 那邊寫設定檔時,會比較簡單。
2016年6月7日 星期二
叢集環境的 logging(二):辨識集中化 log 的來源
在前篇文章中,利用了 logback 的 SocketAppender 和 Receiver 功能,將不同來源的 logs 集中到一個地方
但在沒有特別設計的情況下,其實我們通常會分不出來哪個 log 來自哪裡。
不過這個問題在 logback 裡已經被考慮過了,可以利用 Mapped Diagnostic Context [1-2] 來實現。
叢集環境的 logging(一):透過 slf4j + logback 集中化 log
在叢集環境中,應用程式往往會同時存在在很多個節點上
每個節點的 log 都各自輸出到自己的 console,或者可能輸出成某個檔案,但都四散在每個應用程式自己的節點上。
實務上如果想要觀察 log,通常會希望最起碼 log 可以集中到某個地方
這個需求,如果是使用 logback 作為 logging framework 時,可以透過使用 SocketAppender 和 Receiver 來達成。
2016年6月6日 星期一
使用 Maven 建立 Jersey 專案
當想要新建一個使用 Jersey 的 RESTful 的專案時,可以利用 Maven 直接產生範例 [1]
mvn archetype:generate -DarchetypeArtifactId=jersey-quickstart-grizzly2 \ -DarchetypeGroupId=org.glassfish.jersey.archetypes -DinteractiveMode=false \ -DgroupId=com.example -DartifactId=simple-service -Dpackage=com.example \ -DarchetypeVersion=2.23從上述的官方範例中,執行後會自動產生 groupId 為 com.example、artifactId 是 simple-service
並且會先建好 com.example 這個 package 的檔案(包含 src 目錄以及 pom.xml)
之後以 eclipse 來說就直接 import 到 eclipse 裡面,就可以開始增加自己需要的東西了。
另外紀錄一件小事,因為最近在 Windows 上習慣用 PowerShell,但上述的語法卻一直不能使用
研究了一段時間之後才發現,錯誤的並不是語法本身,而是在 PowerShell 上必須加上引號 [2]
例如:
mvn archetype:generate "-DarchetypeArtifactId=jersey-quickstart-grizzly2" \ "-DarchetypeGroupId=org.glassfish.jersey.archetypes" "-DinteractiveMode=false" \ "-DgroupId=com.example" "-DartifactId=simple-service" "-Dpackage=com.example" \ "-DarchetypeVersion=2.23"
參考資料:
2016年6月2日 星期四
推薦的 RESTful API 最佳實踐
(其實也只不過是去 Google「rest api design best practice」而已)
找到兩篇看完覺得我被說服了的文章
推薦有想要好好設計 RESTful API 的朋友可以參考看看。
參考資料:
2016年5月31日 星期二
ISO-8601 字串轉型成 Calendar
ISO 8601 是標準的日期時間表示法 [1],在一些有遵守標準的網站上,很容易看到這種以表示法表示的時間。
在 Java 裡,有一些不算困難的方法,可以把 ISO-8601 表示法的文字轉成對應的 Epoch Time
然後當然因為有了 Epoch Time,就可以進一步轉成 Calendar 或者 Date 等其他日期相關的類別。
2016年5月21日 星期六
2016年5月19日 星期四
使用 JUnit 測試 private method
應該是一個社群持續爭論中的問題~
相關的說法有部份可以參考看看 [1],這裡先跳過這個問題不管。
假設目標是要測試 private method,實務上可以利用 Reflection API 來達成 [2-3]。
2016年5月13日 星期五
2016年5月11日 星期三
2016年5月6日 星期五
2016年5月5日 星期四
檢查物件型態
不過在對於 primitive type 時,無法使用這個檢查
另外當類別只能在執行期間才會知道的情況下,也沒辦法使用 instanceof
這時可以使用類別的 isAssignableFrom() 或者 isInstanceOf() 來檢查。
2016年5月2日 星期一
AWS DynamoDB SDK v2 基礎使用(一):基本認知
DynamoDB 是 Amazon 提供的 NoSQL 資料庫
不過就我最近使用的感覺,其實我覺得它比較像是「有 RDBMS 靈魂的 NoSQL」
換言之,我覺得它其實是個 RDBMS,只是稍微支援了一點 NoSQL 的功能而已。
關於 DynamoDB 的簡介就不細談了,網路上大概可以查到不少
主要想紀錄的是如何使用 DynamoDB 的 Java SDK。
陸續找了不少資料後,我覺得 DynamoDB 的文件 [1] 真是相當差勁。
官方文件給的範例非常地簡略,對於稍微複雜一點的指令就沒有說明該如何實作
Google 往往會找到許多過去的部落格文章、或者甚至是官方的部落格
然後會發現同一件事情有好幾種不同的實作方法,估計大概是新舊的 API 的差別
每種實作方法似乎都有一些優點跟缺點,對使用者來說雖然可以依照自己的需求做選擇
但對於多數剛開始使用 API 的開發者來說,可能只會跟我一樣頻頻想說「WTF」。
2016年5月1日 星期日
顯示器驅動程式停止回應
然後跳回桌面,右下角會顯示「顯示器驅動程式停止回應」。
這時遊戲大概畫面都會有點問題,有時這個問題會一直連續發生,最後會變成藍白畫面。
最初以為是驅動程式不穩定,不過換了很多個版本還是都沒有改善
今天又花了不少時間在找這個問題,不過找到國外的論壇的討論 [1]
其實只要移除掉 Windows 的 KB2685811 這個更新 [2] 就好了!
目前還沒有嚴謹地做過測試,不過至少我現在用 EVGA GTX650 的顯示卡
作業系統是 Windows 7,驅動程式降版到 310.90 WHQL,然後移除 KB2685811 更新
玩 Steam 版的俠客風雲傳可以成功通過最初的對話以及教學戰鬥了 XD。
2016-05-05 更新:實際上還是會出現驅動程式停止回應跟當機的狀況,但已經從原本十分鐘內掛掉,變成可以連續玩幾個小時後,才有可能掛掉。不過再加上 [3] 更改 TDR 以後就沒有再發生了。
2016-07-04 更新:310.90 WHQL 改玩 Steam 的信長之野望時還是一直出問題,後來用 DDU 移除重灌成 337.88 WHQL,目前看起來比 310.90 WHQL 穩定。
PS. 不過這個方法應該不適用 Windows 8,因為 KB2685811 這個更新本來就是給 Windows 8 的更新。
參考資料:
- Nvidia - Display driver has stopped responding and has recovered error
- Windows Vista、Windows Server 2008、Windows 7 及 Windows Server 2008 R2 的核心模式驅動程式架構 1.11 版更新
- Graphics driver stopped responding and has recovered....TDR fix
- "Display driver stopped responding and has recovered" error in Windows 7 or Windows Vista
2016年4月27日 星期三
Java 的基本物件複製
public class Test implements Cloneable { public Object clone() throws CloneNotSupportedException { return super.clone(); } }
不過如果物件成員有包含比較複雜的成員
例如成員有包含另外一個也內含成員的物件的話,會有稍微複雜一點的狀況
可以參考 [1] 去實作。
參考資料:
2016年4月19日 星期二
2016年4月18日 星期一
2016年4月13日 星期三
2016年3月24日 星期四
自行架設 Wiki 引擎(一)補充:手動以 HTTPS 安裝 Foswiki
主要是描述以手動安裝的方式,將 Foswiki 整套安裝起來
其中會這麼做,主要是因為 Foswiki 的 Debian 套件很久沒人更新了。
2016年3月8日 星期二
使用 Selenium 與 HtmlUnit 時,忽略 script error 和 http statuscode 的方法
- 網站的 JavaScript 在解析過程有錯誤。
- 網頁本身失連、或者網頁內的任一連結(包含 JavaScript 檔、CSS 檔、圖片等外部連結)失連。
2016年2月17日 星期三
HttpClient 在重複不斷存取相同的 URL 時持續 timeout 的問題
在測試時發現寫的程式碼第一次執行時正常、第二次執行到一半開始一直 timeout
但關掉程式再重新啟動時,第一次又恢復正常,然後一樣第二次差不多地方開始一直 timeout
存取其他不同網址的網頁時則好像沒問題~
最後發現是因為程式碼在最後忘了把 CloseableHttpResponse 關掉(即呼叫 close() 函式)。
2016年1月18日 星期一
架設自己的 Maven Repository Server(二):發佈專案到 Nexus
在前一篇文章「架設自己的 Maven Repository Server(一):使用 Nexus 架設 Maven Repository Server」中
已經用 Nexus 建好一台非公開的 Maven Repository Server
接下來在這篇中就要把專案發佈到 Nexus 上了。
2016年1月11日 星期一
使用 Maven 打包 jar,並將引用的 dependencies 一併打包
就沒有簡短的途徑,一定要把 jar 引用到的所有第三方函式庫,一併全打包進 jar 裡
在 Maven 中可以透過設定幾個 build 參數來達成。
在 Ubuntu 14.04 安裝 MongoDB 3.2:使用 WiredTiger 儲存引擎
其中會以兩台主機建成 Shard 的 replica set、以三台主機建成 Config 的 replica set,並以一台主機作為 Mongos