2014年2月20日 星期四

台灣縱貫單車行(四) 合歡山小風口 - 武嶺 - 埔里 - 日月潭


昨天晚上非常的冷,還時不時的下驟雨,擔心帳篷進水讓我晚上睡不是很安穩,不過睡袋倒是夠暖和。但要是再冷一點就難說。



早上六點正式起床,跟新認識的朋友約好早上一起去拍日出,決定先去石門山晃晃再回來收拾營地。
一路上風非常的大,經過克難關把機車停在路旁,花十分鐘走到石門山山頂,站在雲海頂端看著四週山上的霧緩緩加入,非常壯觀。

 石門山攻頂...超容易。
 先來讚一下
合照當然是要的

我們四處拍照,遇到一群香港來的旅客,回服務站扎營處的路上也不停的尋找值得拍照地機會與地點。
 一大早從紮營處往公路看去
 天堂路有著天堂般的美景
總之就是拼命的拍
回到營地開始拆帳篷收拾行李,東西全都是溼的,要收進馬鞍袋裡又必須避免不該溼的東西溼掉,重新安排花費了很多時間,著實麻煩。收完東西回到服務中心前面的桌椅,我把所有的泡麵、雞蛋都煮了當早餐振奮一下精神,畢竟接著就要挑戰上武嶺的最後一段陡坡了。

吃完早餐,跟朋友彼此交換聯絡方式加了FB,正準備要收拾走人的時候,遇到了另一位從香港來的單車騎士。他昨晚睡大禹嶺的民宿,今天纔剛從那兒上來,於是我邀他一起攻武嶺。

在路上我跟騎機車的軍人朋友道別,接下來就是兩小時風超大超冷,超硬陡的爬坡。

一路上我們一邊透過閒聊,拍照,調整推車的姿勢來休息並轉移注意力,一邊觀賞著這合歡山天堂路的美景,的確,這裡可說是全臺灣最接近天堂的地方了。


過了克難關,看到開始是下坡了,我們又叫又跳超興奮的,然後我才想起還有松雪樓到武嶺這段一公里多要爬呢。

滑降到松雪樓,我們跑去服務站休息了一下,再來就是中橫最後一段上坡了。沿途溫度比起克難關又更低了,霧氣也更濃,沿途山壁上有許多沒有化掉的冰瀑讓路過的遊客非常興奮。

在十一點半終於看到武嶺的大字時,非常的感動,雖然一直相信自己是上得來的,但壞天氣、高山症的陰影一直都在,現在上都上來了,下去頂多只會碰上霧而已,接近中午正是交通繁忙的時候,不論上山下山都是車水馬龍,那種會在山道上狂飆的白目也只能乖乖的龜在隊伍裡,不能成為危險因素了。


在武嶺拍完照,吃了點東西,就趕緊要下山了。這裡實在太冷,不維持活動的狀態站著不動,不要半個鐘頭身體就冷到直發抖。

開始滑降不到十分鐘,只套了半指單車手套的我們就凍得兩手痛得握不住煞車,覺得這樣太危險的我趕緊叫他停車,想想該如何解決這問題。後來我想起我剛好有帶一付洗衣服用的媽媽樂橡膠手套,而帶上來的滑雪禦寒外套裡也剛好還塞著前年去加拿大滑雪時用的防寒手套,問題就解決了,雖然他戴著媽媽樂手套的樣子很像某種造型奇特的洗碗工,不過醜總比手指凍僵煞車沒握好來的強吧?

滑降到昆陽的途中霧非常的濃,能見度大概30公尺左右,到了昆陽拐個彎轉進去一片空地邊上有三四個小吃攤在賣一些簡單的食物,吃了點東西,再來我們行程步調不同,單車設定不同,只好先跟他道別要先走一步了。

從昆陽一路滑降到翠峰然後過清境農場這段是最驚險的,我的車體重,滑降的時候一直猛拉煞車那一下子煞車塊就過熱了反而危險(這是檢討項目,我雖然有記得要換煞車線、變速線卻忘了換煞車塊,走這種行程以後得更小心,這個失誤也成為後來不能走阿里山公路的原因之一),不如利用車子幾何良好、重心低(重裝馬鞍袋就又更低)搭配下坡把帶來的操控優勢只做必要的煞車來得安全,車速雖然比較快,但保持跟前車等速同時拉出足夠的煞車間距就好。
保持車距滑降
沿途雲煙繚繞,陽光不時的從縫隙間透下來照著遠方

往翠峰爬了段小坡
再來就是清境農場了


清境清境六根不淨,雖然這裡很是可以滿足一般台灣人對旅行時吃喝拉撒睡品質的要求同時兼顧對旅遊的想像,但把山地開發成這樣亂糟糟的一片實在讓我提不起興致留步,倒是底下去埔里的路上遇到的櫻花林配著鄉間悠閒的景緻更叫人欣賞。
迅速通過清境農場

到了霧社,首先映入眼簾的就是霧社水庫(又稱萬大水庫、碧湖)。
很漂亮,但也令人哀傷,看得見嚴重的淤積啊。

經過仁愛鄉公所一點點,路旁可以看見紀念當年霧社事件的莫納魯道的牌坊,是的,就是電影賽德克巴萊的那個莫那魯道。不過我實在覺得這牌坊怎麼看怎麼怪,這東西不論設計題字都是中國風的,怎麼看就跟原住民無關,想來是當年國民黨為了透過「抗日」這個共通點來招撫原住民搞出這玩意。

到埔里鎮之前,剛好我一位朋友老家就在埔霧公路上,於是跑去她家作客,順便一起去埔里市區逛逛吃點小吃。
首先先排隊吃羅春捲,這家店排隊排超長,一個客人常常一買就是好幾套,我們排了20分鐘左右才吃到。雖然我不是春捲的Fans,但這家真的很好吃。第二家店吃阿菊肉圓,屬於偏清蒸類型的肉圓味道相當不錯,吃到剩一點點再加湯沖成一碗喝下,相當暢快。最後是吃王記蚵仔煎,吃起來味道普通,皮有些部分有煎脆,但口味主要都靠澆頭,但這也不能太要求,畢竟埔里是個靠山的地方。

暢快的逛完吃完回到她家再出發已經是下午六點出頭,接著就朝今天的終點:日月潭青年活動中心邁進。

才離開朋友家沒多久就開始下雨了,這剛好是一個測試新雨衣性能的好機會,二話不說把它披上繼續騎,這雨衣是我爸去大陸玩的時候買的,為了這次旅行專門為了這單車的設定改造過(加了可以固定在前貨架的魔鬼沾與帶子,挖了讓前車燈可以透出來的孔)。實際使用效果相當不錯,雖然因為不透氣的關係人還是濕的(汗溼),但至少車子上半部都能保持乾燥。

從埔里去日月潭有兩條路,一條走台21、另一條走縣131,看了看,我選擇走較短的縣131,當然,大部份的人這時候會決定留在埔里過一晚,明天再去日月潭,但有過之前夜雨紫來產業道路往坪林、夜雨蘇花高到和平、夜颱風到瑞穗、夜雨台九線去台東大武等經驗...我對凡是出去自行車旅行必定碰上瞎燈黑火的夜雨XXX已經見怪不怪了。「牧羊少年的奇幻之旅」裡有段話意思大概是這樣的:「一件不可能發生的事要發生了、這是倒楣,要是發生了第二次,這是你真倒楣,要是還有第三次,那就不是倒霉而是往後必然會再發生。」

縣131這條路晚上騎別有番趣味,一路沒有行人、沒有車子、四週房舍靜悄悄地,細雨中我緩緩踩踏著,黑夜中世界彷彿靜止、失去顏色,只有黑與灰。遠方山谷農田化成一幅潑墨山水背景,農舍與路燈的光芒像是濃重的黃紅油彩滴灑其上,而斜斜灑下的銀絲劃開油彩,構成一幅後現代的畫作。

騎進隧道,景色一下子切換成鈉燈特有的暖黃色,霎時間有種回到文明、但又像是踏入了某個老膠卷底片的世界裡。離開隧道,投入全然的黑暗裡,細雨持續著,我緩緩騎向道路遠方的小鎮。

穿過魚池鄉,切進一條往日月潭的小鄉道,再來就是雨中的爬坡了。
日月潭的地形很特別,它是一個堰塞湖,地勢比周圍高出許多,這段上坡雖然只有不到三公里,但在這樣的天氣裡重裝爬坡並不是件有趣的事。
使勁的翻過一座小山,就來到日月潭邊上了,接著順順的往湖邊繞,青年活動中心就在纜車站旁邊。

到了青年活動中心的櫃檯,剛好接待我的就是兩小時多前還在埔里時通過電話的那位櫃台小姐,她很訝異我在這種雨天還能那麼快騎到,照她說騎機車差不多要40分鐘。
問了房間與價格,剩下一間雙人房一晚1700,有點貴不過也沒辦法。住房都在別棟樓,接過鑰匙就推著車去房間了。

偷偷的把車子抬上二樓牽進房裡,一邊高興今晚可以睡在床上,一邊觀察要怎麼把所有的東西攤開來晾。

後來決定先把濕衣服脫掉、把所有要洗的東西丟進淋浴間。把馬鞍袋全部清空,袋口敞開讓水氣散掉,帳篷雨衣睡袋睡墊爐具全掏出來晾,電氣設備開始充電。
在合歡山上紮營時全溼掉的帳篷內外帳展開攤在地上,連門廊地上都用上了。

洗完澡、洗完衣服,把梨山上買的大水梨吃掉當做今日獎勵,就刷牙關燈準備睡覺了,真是充實又疲憊的一天啊。

2014年2月15日 星期六

台灣縱貫單車行(三) 梨山 - 合歡山小風口

起床的時候天已經大亮了,看了看表,差不多是七點整,看到帳篷外面今天又是個大晴天,昨晚令人擔憂的小雨像是假的一樣。
出帳篷後正前方就看得見梨山附近山坡地開發過頭的景象:


天氣很好,昨天連續10多小時的騎乘造成的疲勞消除大半,今天的旅程到小風口約35KM不長,懷著這樣輕鬆的心情收拾東西、吃早餐、跟鄰居聊天整個就拖拖拉拉的,一直到九點才正式上路。



從梨山到大禹嶺這段,一開始是一段爽快的滑降,到了末段會經過好幾個坍方處。

途中我先遇到一對在路邊賣水果的老夫妻,經過的時候老先生熱情的跟我打招呼,旁邊還煮了一大桶薑母茶免費給路人喝。一邊喝著熱燙的薑茶、吃著切好得水梨,一邊與他們聊天,他們就住在這裡,一條很陡的土路上去十公尺就是一間矮鐵皮屋子藏在林子裡,不抬頭看還真不會發現。

在滑到一個坍方前,遠遠地我聞得到一股柴煙,繞過坳口,看到一個頭戴黃色工地安全帽的太太以一根巨大的樹幹當柴在生火煮飯,旁邊還有個身高剛過她膝蓋的小女孩,一看到我就瞪大眼睛躲到她母親背後改偷瞧著。
我好奇詢問下才知道,這一家子丈夫妻子都是修路的,春節期間要守著這危險的路段指揮交通、維護用路人的安全,可附近的村落都放年假去了買不到便當、孩子放寒假也沒人能幫忙戴,他們只好一家三口全守在這克難的煮點東西果腹了...

通過坍方處到了另一頭,跟這一家三口的先生點頭致意,我繼續我的踩踏。

接著到了最大的坍方,這邊沒有鋪柏油就是一層細石加混凝土碎塊構成的土路,路況可以說是off road的水準,特別陡又特別的爛。正通過最低處要往上推的時候,後面來了一個全以Vespa Scooter為坐騎的車隊。五台車從我旁邊經過,一上去,兩台就後輪陷在沙土裡空轉了,騎士們只好在轉倒前跳下來跟我一樣開始推車。

通過這區坍方,再來就差不多是繞行武法奈尾山山腰的緩上坡了。



一路上一堆小聚落,大概是方便附近採收果子而設的吧?春節期間都沒有人。不過麻煩就麻煩在人走了狗留下,而且還整群整群的,狗這種生物只要一成群結隊就不怕人,看到慢車經過會集團追著狂吠找機會咬,幸好我的旅行車體積龐大,腿不停的踩踏狗也很難瞄準,而且又有打綁腿咬到也不太會受傷,就索性任他們圍著吠了。偶爾遇到幾隻白目的貼上來不放的(大概是頭頭要耍威風吧?)用後腳跟朝鼻子踹牠就會躲開放棄了。


途經某個小聚落的時候,一台轎車緩緩的從旁邊接近並把車窗搖下來跟我攀談,原來也是位車友,他是桃園博愛車隊的隊長,趁年假帶朋友一起遊山玩水。他看我裝備這麼誇張感到很新奇,還特地停車跟我介紹他們的車隊並合照。最後要分別前還送我一堆餅乾、水果。沒想到糧食越吃越多了。


從梨山到大禹嶺途中除了經過的車輛,其他什麼人也沒遇見,有種千山獨行的感覺,終於繞過武法奈尾山,看到隧道口出現在前方時真的非常的開心啊。



過了隧道看了看時間,已經是下午兩點多了,開始非常擔心今天的進度,所以到了大禹嶺停也沒停就開始爬坡上武嶺。這坡度真不是蓋的,坡度多是10%左右, 12%以上持續超過300m 的也好幾個, 雖然昨晚有跟梨山一起露營的鄰居詢問過路況,今天出發前也早有心裡準備了,但面對這個根本騎不動,只能一路推車慢慢龜的五公里,時間過的既緩慢又痛苦。

雖然推車推得很苦,沿途的風景卻是越來越壯麗,已經看得見雲海從遠方的群山中探出來。







在這樣的高海拔即使是推車也不輕鬆,時速通常只有2.7(以我的車重,推車速度超過4.5才可以用騎的不爆心跳),為了防止推車推到過度疲乏,我不停的檢查心跳表,超過155就休息到回復130,這裡的海拔已經超過2700,已經有一點呼吸困難眼框發漲的現象。

休息的時候,一邊喝水、一邊吃著黑糖塊,一邊看著風景:


曾身為測量人,當然要拍張一等水準點。

這裡就是小風口,繞過去就是服務站了。

右邊都是這樣的由枯黃箭竹蓋著的緩丘。

去服務站前,先來張奇萊山

再來一張奇萊山


推過小風口看到國家公園服務站時是下午四點半多,多少鬆口氣,馬上衝進去點了兩個肉粽來吃。
補充能量後,開始跟在服務站工作的原住民員工打聽住宿的情報。

發現這裡到松雪樓還有一段不短的路,以我的狀況大約要一小時,但松雪樓有點貴又不見得有位子。
至於直上武嶺大概得要晚上七八點了,武嶺可沒地方住人,來到這就只能滑降到昆陽碰碰運氣,不然就是一路直下到清境農場去住貴到爆炸的民宿了,重點是體力跟精神力被昨天上梨山那段路給耗得七七八八的,今天玩沒50 km就接近極限。
既使服務站充滿著各種警告「禁止」標語,但對於又冷又累,一點也不想挑戰夜間推車,翻過濃雲封頂、標高3275公尺武嶺的我來說,就地紮營是唯一的選項。

趁服務站關門前趕緊泡泡麵,上廁所,穿衣服,把鍋碗瓢盆全掏出來裝熱水,然後就四處打聽一下哪裡適合紮營的消息。

這時候,我看到一個背著登山大背包、穿著雨鞋,拿著相機的高個年輕人,心想他大概是附近最有可能知道哪裡可以露營的人了。

閒聊了一會兒,他剛好也想在這附近露營,那就彼此作伴吧,我們在服務站附近的小山丘繞了一下,發現比起網路上有人推薦的馬路對面的停車場要更好,箭竹叢可以抵銷一點風勢,離服務站更近,重點是停車場要是有人在巡邏實在太容易被發現了。

在服務站關門後,我把腳踏車跟所有的裝備都扛上小山丘,趁著天還亮趕緊把帳篷搭起來,然後就跑回服務站的廁所梳洗。

夜晚,一邊跟新認識的朋友聊天,一邊各自躲在各自的帳篷睡袋裡取暖,天氣變得越來越冷,天上濃雲密佈,我開始擔心今晚恐怕不會很好過。

2014年2月11日 星期二

台灣縱貫單車行(二)留茂安 - 南山 - 梨山

今天3:40 就起床了,前一天緊急迫降,晚上睡的還算舒服,早上被公雞叫起床後就又開了一罐豆子吃掉,這玩意實在重的要死。至於味道嘛,總之就是華人很難接受的豆味。收拾帳棚、營地摳摳摸摸到5:30才出發,天色還是全黑的,騎起來有點膽戰心驚,沿途經過的車不少,得將後車燈全部打開才覺安全。

到了六點半天終於漸漸亮了,好不容易才爬坡到四季,夜燈未熄的山城有種特別的美,沒想到這坡度祇是小菜一碟,真正的苦難在後頭。


從四季到南山的路上,又是一路之字上坡啊!之前還想要盡可能用騎的,但沒幾分鐘就放棄了,上個月急性足底筋膜炎的記憶還在,後來凡陡上坡我就都用推的了。

往四季平台的路上剛過一座不知名的橋的時候,遇到一個喜歡機車旅行四處拍照的朋友,他跟我說這幾天要開始下雨了,上武嶺要有心理準備。這讓我開始擔心路面結冰的問題了,我當初設定的撤退條件就是山區連續下雨跟路面結冰,這兩個發生任一個,想要從台灣這種變態山區道路安全滑降下去根本不可能。

看到南山加油站的時候已經早上九點多,之前還在肖想今天攻上武嶺的,到這裡已經完全放棄。其實這趟一直到此刻才估算出平均時速大概是多少,非常可恥的8km/hr, 車體實在太重了。但無論如何這趟來我確實的蒐集到臺灣高山公路重裝自行車爬坡一些必要的數字。要估算行程,規劃未來的洲際旅行更有信心了。


在南山村最有名的賣茶葉蛋的雜貨店吃了饅頭配茶葉蛋、喝了黑松沙士,在陽光下曬也曬夠了,就開始挑戰今天最拼的一段:南山到思源啞口...








總之就是一個字,龜,下車用推的慢慢的給它龜上去!,最後那連續八個不同方向的髮夾彎真是黯然銷魂啊。抵達思源啞口涼亭的時間如我所料是中午十二點,休息了半個鐘頭吃完午餐再出發。



正在吃帶上來的麵包,風乾了一整夜超硬,得要一直和水吃。

接下來一路往下滑降,經過去年四月要爬武陵四秀時,拜訪過不給露營的勝光派出所、以及借住過的廟,很快就來到往武陵農場的叉路口。


從這裡開始就又是一路上坡了,如果說從留茂安往南山這一路上什麼最多,那就是高麗菜田,那從武陵到梨山什麼最多呢?就是各種高冷果樹了,看著滿山遍野光禿禿的果樹,鼻腔充斥著尿素肥料與柴油車尾氣的臭味,我默默的戴上防毒面具,再度開始爬坡。






到梨山的最後那段抄捷徑的路是最折騰的,每次聽信Garmin GPS 的下場都很悲劇,整整三公里坡度超過15%的連續陡坡啊(松東巷轉民生巷)〜已經被前面的十小時的上坡給摧殘過的我,要推著這40kg的重裝旅行車進行這最後的高潮...真的很想死,不要說每100公尺都要休息幾十秒,旁邊的住戶跟路過的車輛都用新奇的眼光跟加油聲嘲笑我的愚蠢...果然人生就是要走正道,狀況越苦越累就越不應該抄捷徑。

到了梨山市區巡了一圈...悲劇,想說找間便宜的可以洗澡睡覺的旅店就好,沒想到隨便一間起跳都要2800啊,還一下就滿了要住都沒有。最後跑去遊客中心看有沒有什麼有用的資訊,裡面的工作人員愛莫能助,但他們很好心的幫我把水裝滿,省下一筆錢。

後來遊客中心打烊後,我先去旁邊的洗手間洗澡,要在一般的公共洗手間洗澡,你得準備幾樣東西:

一雙拖鞋,你得先把布鞋換掉,弄濕鞋子是最慘的。
鍋子跟一個紅白塑膠袋,都裝滿水,紅白塑膠袋沒破可以裝2~4L的水,很好用。
最後帶著換洗衣物、毛巾、洗髮精、沐浴乳,找間有蹲式馬桶的洗手間吧。
把所有衣物脫掉(除了拖鞋)連同所有貴重物品塞進有背包套的背包裡,背包背對外面,這樣不管怎麼洗東西都不會溼,也可以放心的放在溼嗒嗒的地上。

裝滿水的塑膠袋掛門把或門上掛鉤,鍋子放地上,毛巾浸濕後滴上沐浴乳,開始擦全身,把第一鍋混濁肥皂水給擦掉後,塑膠袋的水再倒進鍋子裡繼續擦,塑膠袋通常可以倒兩鍋左右的水,這樣對男生來說已經可以洗的很乾淨。

洗完澡後天色已黑,開始擔心露營的問題,天空開始飄下毛毛雨,我想來想去不知道該怎麼辦,就在遊客中心旁邊涼亭的二樓搭起緊急帳,心理覺得今晚會有點難熬,想說睡袋也不拿出來了,衣服多穿幾件睡就好。

準備的差不多後,想說這樣實在太慘了,就跑去附近遛達看看有沒有更適合的地方,意外跟攤販探聽到賞楓步道旁有一整排政府亂蓋的蚊子攤位,有頂蓋、又是三公尺見方一格,剛好就是最適合的露營地,看過去已經有四五頂帳蓬在那,我就順便加入了。

搬過去時,免不了的大家看到我的行囊都會睜大眼睛詢問一番,知道我要挑戰縱貫行他們都給予我最誠摯的祝福。其中一家人是來這區煮飯吃晚餐的,晚點就要下山了,他們還特地把多出來的高麗菜都炒掉給我,像這樣隨處流浪的旅行總是能遇見熱心人。

晚上把豆泥跟剩下的鹹豬肉還有蔬菜全部煮掉,這樣明天開始就沒有罐頭類的東西了(蠢)。
也因為搬家拖到一下,一直到九點才吃完晚餐,到都弄完要睡覺的時候已經是11點多了,想說隔天就睡到自然醒吧。要上武嶺,35 km 超硬的路程,希望是個好天氣。

台灣縱貫單車行(一)宜蘭 - 留茂安


這次規劃獨騎三橫一豎的一豎,雖然最後很殘念的沒有完成最後的阿里山公路段(強降雨+坍方),但能夠順利的爬上武嶺騎到日月潭已經很開心了。

這次跟之前一樣,都採用洲際旅行水準的重裝備方式來騎,以下是出發時的裝備清單:

單車:
Pacific Reach 2009、前後貨架、後輪環狀發電機、備胎*2、維修工具、簡易單車鎖、固定用彈力帶*3
BW 60Lux 前後燈、USB 後方指示燈*2、單車雨衣、單車雨帽、防風眼鏡、口罩(3M 7052+P100濾片)

行囊:
前馬鞍袋、後馬鞍袋、前貨架上袋、後貨架上袋、camelbak 40升水袋背包、攜車袋

電器設備:
Garmin Edge 810、手機、ipad mini、Gopro Hero3、Power bank*2、多孔插座、1A USB充電座*2

露營設備:
帳篷、地布*2、營釘*6、睡袋、充氣睡墊、充氣枕頭、JetBoil、2L 鈦鍋、瓦斯*2(用一半的)、瑞士刀、餐具、橡膠手套、肥皂、頭燈。

衣物:
安全帽、遮陽帽、車衣、車褲、單車背心、短褲(穿在車褲外面保暖兼放東西)、運動長褲(睡覺用)、短袖上衣(睡覺用)、小腿收縮套、綁腿、運動鞋、拖鞋、半指手套、防寒手套、雨褲、Buff、防水外套、保暖外套、羊毛襪(睡覺用)、快乾短襪、長襪。

食物:
水壺兩個(共1.6L)、3L水袋一個、土司兩條、泡麵*4、蛋*4、鹹豬肉*1、豆子罐頭*3、蔬菜罐頭*1、牛肉乾*3、黑糖一包、花生糖一包、橘子*4、棗子*4、

全部加起來車重約45KG 正負5,大概長這樣:



今天是出發的日子,天氣非常不錯,不過八點起床實在不夠早,應該要六點的。

到了市政府搭首都客運,人超多,等了三台車才上,幸好首都客運還是一樣友善,讓我的重裝上車不說,還主動幫我喬行李倉的位置,決定以後去宜蘭都要坐首都了。

一上車就自動昏睡,就這樣睡到宜蘭,到的時候已經12點半,在附近吃了點東西就1點了,跟預計的出發時間足足差了2小時啊。出發時天氣超好:


吃完就趕快上路了,一路上些微上坡,但時速一直拉不起來,只有15km/hr左右,有點擔心今天騎不騎得到南山,路邊的風景非常漂亮,宜蘭支線的櫻花正是花季,雖然沒有太多時間逗留,還是拍幾張意思一下。






這次的行李比起之前雙塔實在多太多了,帳篷,睡袋,爐具鍋碗,糧食,全部加起來超過40 kg, 已經逼近這台車的設計極限,沒辦法,一路都是山區,不見得有吃的,旅館就算有過年期間也不可能訂得到,看來就多吃一點多多消化吧。
今天本來目標是要到南山的,但因為晚出發所以過英士的時候都4:30了,到了岔路往太平山的地方約6點多:



經過留茂安的時候看到衛生所外面有一個鋼骨搭的天頂棚,天也已經全黑了,就問了旁邊雜貨店的老闆可不可以讓我在空地邊露宿一晚,他們想了一下就答應了,雖然沒廁所非常的不方便,自來水還是從水塔管路接管漏水的地方偷接的,但這也算難得的經驗。

晚餐第一次嘗試把昨晚自己醃的鹹豬肉切一塊來炒,發現這啥勞子非常的難處理,差點要煮焦,看來剩下的得切小塊一點用水煎的方式處理。

2014年1月17日 星期五

每個人都有自己的觀點,我們應當尊重言論自由

『我它X的放X的狗屁!』怎樣?尊重一下我現在罵的髒話阿。

講這句話的人常常就一副『我有權利說這話,你們不可以批判我說的話』的調調,但這種『我喜歡在密閉空間裡放屁,而每個人都會放屁,所以你不可以批評我,要尊重我,讓我自由自在的放屁給大家聞』的白痴邏輯到底有什麼值得尊重的?

尊重『言論自由』、跟尊重『言論』是兩回事,尊重言論自由意思是,我不會因為你說了,或者將會說我不喜歡聽的話,就仗持權勢不許你在會議中開口、甚至玩手段不讓你參加會議、或者成績上搞你、還是晚上就去你家門口堵你、拔妳的官、叫教官警察去弄些莫需有的玩意找麻煩。


你覺得想放屁、覺得你放的屁特香,你就繼續放,那確實是你的自由。
但發表批鬥這種噁心行為的言詞也是我的自由。

覺得很委屈,覺得被公審?要是你真的相信你講的,你覺得你就是對的,那好阿,當年的施明德、鄭南榕,還是曼德拉、甘地都是你傚仿的對象。

尊重你的自由不代表我得尊重你,更不用說尊重你放的屁。

2013年11月11日 星期一

這陣子的開發心得



好的Source version control真的很重要,用到很鳥的(例如perforce)生命就是會浪費。

Maven 沒有incremental build實在很麻煩,有很多plugin應該要考慮把處理過程的中繼資料存起來,有改的才跑就好。

不跑integration test是省掉了一些時間沒錯,但專案一大每次重頭build還是等的很煩。

Jenkins是好東西。

GWT build 實在是浪費時間。

開發團隊一大,CI + DEV ENV就需要專人維護,而且這人還必須有經驗不能亂找,因為這人對環境的任何改進,都會直接乘到團隊的人數上。

測試真是門藝術,有些程式碼是照規矩寫,簡單檢查一遍邊界條件與異常狀況就收工了,有些測試程式碼甚至只有被執行一次的的價值。但常常一個系統最有價值的部分:扯上語言、扯上條件組合、扯上時間的,就很容易怎麼測都不是很敢保證東西在任何的合理輸入下都會對。這需要修行與案例討論。

User 方的品味與專注程度會根本性的決定成果的價值。

Code review很重要,review的人必須專心在模型可能的瑕疵與合理性上,被review的人則要對「如何有效的讓設計能被他人理解」負責...這實在超難,畢竟英文非母語,而到底是review的人心中有成見,還是被review的設計真的不夠好,這有時實在很難釐清。但被review的人是有責任去盡可能的把可以預先想到的其他設計分枝,在初始階段就先考慮過一遍的。畢竟從多個可能性裡選一個,跟一開始直覺想到的第一個就一路做下去,這絕對差很多。

跑Scrum 還是要大家都在同一間辦公室比較好,分成兩個地方實在打很多折扣。

Pair programming 是任何團隊開發絕對要優先考慮的方式,光是「兩個人一起做,所有的社交軟體的干擾就會消失掉」這點在現代就起碼給你增加了15%up的產出,其它像是知識分享,工作進程的人腦備援,旁觀者清,聚焦集中且有效率的時間區段延長等等。更重要的是透過這種方式才能逐漸瞭解其他人的思維模式,進而找出適當的分工方法。

2013年8月12日 星期一

Apache CXF 筆記

為啥要玩Apache CXF呢?簡單的說就是要從它跟Jersey之間挑一個來用,目標是用它作為Web Application的後端跟GWT 開發的前端(透過 Resty GWT)溝通使用。

至於為什麼不直接用GWT RPC呢?因為公司的Architects覺得GWT有點朝不保夕的感覺,他們希望如果哪天GWT死掉了,前端可以有機會一點一點的換成Javascript native implementation...我是覺得這有點異想天開啦,但是看他們好像有人有基於這種架構開發過還很舒服的樣子,我就不多說了,玩下去就知道。

Jersey 公司已經一堆人會了,也有人用過,於是我就自動請纓來Survey CXF了...雖然我覺得這玩意八成不會被接受(開玩笑,一堆人會就代表開發成本低、有默契,這玩意很多時候比架構重要)。

CXF的基本介紹

CXF 是 Apache Foundation 底下開發SOAP、JAX-WS、JAX-RS應用的一個較為現代化(?)的應用框架。 它支援了幾個重要的Feature:

JAX-WS Support

基於JSR 224的實現,不多廢話,這玩意很老,overhead 很重,但跟異質系統做資料交換且要確保資料型態的正確性還是得靠這個。

Spring Integration

CXF的核心在2.4版以前跟Spring緊密的接合在一起,2.4版後將Spring作為configuration的一種選項(但這是一個強力建議的選項,不用Spring...你得搞懂它的核心是由哪些部件組成然後自己組一個才行)。

Aegis & JAXB Data Binding

CXF 提供在"Databinding"層提供多種選擇,它所謂的Databinding指的是Object to Structured Text(XML, Json, etc...)之間的轉換。

JAX-RS(RESTful Services) Support

基於JSR 339的實現,這篇文章主要想要玩想要討論的東西。JSR 339還蠻新的(final release: 24 May, 2013),CXF還沒有很好的實現它,想單純玩JAX-RS2.0的建議用Jersey,畢竟Jersey是reference implementation,沒做好Oracle就該打屁股了。

Apache 2.0 Licensed

Apache 出品,當然是Apache 2.0 License。


開始一個新的CXF JAX-RS專案


學一個東西,當然先從它的文件與Sample Code開始(...這是指好的情況,有時候人品爆發,就會從看Code 開始)。CXF如果完全照它最簡單的設定走,其實還蠻簡單的,首先,讓我們用CXF所提供的maven archetype來generate 一個Eclipse Project。

如果用的是Eclipse + M2E來開發的,可以很簡單的用m2e的new maven project 來開始新專案,當中在選擇archetype時,建議用 catalog: http://repo1.maven.org/maven2/archetype-catalog.xml 下的cxf-jaxrs-service,來生成project,generate 出來的結果最有趣的部份在build區塊內,讓我們分段的來看一下它的內容:
   <plugin><!--get a random port from system -->
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <version>1.5</version>
    <executions>
     <execution>
      <id>reserve-network-port</id>
      <goals>
       <goal>reserve-network-port</goal>
      </goals>
      <phase>process-test-resources</phase>
      <configuration>
       <portNames>
        <portName>test.server.port</portName>
       </portNames>
      </configuration>
     </execution>
    </executions>
   </plugin>
   <plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <executions>
     <execution>
      <id>start-tomcat</id>
      <goals>
       <goal>run-war</goal>
      </goals>
      <phase>pre-integration-test</phase>
      <configuration>
       <port>${test.server.port}</port>
       <path>/jaxrs-service</path>
       <fork>true</fork>
       <useSeparateTomcatClassLoader>true</useSeparateTomcatClassLoader>
      </configuration>
     </execution>
     <execution>
      <id>stop-tomcat</id>
      <goals>
       <goal>shutdown</goal>
      </goals>
      <phase>post-integration-test</phase>
      <configuration>
       <path>/jaxrs-service</path>
      </configuration>
     </execution>
    </executions>
   </plugin>

可以看見這段是先利用build-helper-maven-plugin 先去取得一個OS上沒有用到的IP,然後存到變數test.server.port上,這樣之後tomcat7-maven-plugin要啟動tomcat7時,就有了一個適當的IP可以用了。

而Tomcat7-maven-plugin會在pre-integration-test phase做start up,然後在post-integration-test phase做shut down,這樣在integration-test phase 期間,unit test case執行的時候就有正確的環境可以執行,底下是maven跑integration-test 的設定:
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>2.8.1</version>
    <executions>
     <execution>
      <id>integration-test</id>
      <goals>
       <goal>integration-test</goal>
      </goals>
      <configuration>
       <systemPropertyVariables>
        <service.url>http://localhost:${test.server.port}/cxf_demo2</service.url>
       </systemPropertyVariables>
      </configuration>
     </execution>
     <execution>
      <id>verify</id>
      <goals>
       <goal>verify</goal>
      </goals>
     </execution>
    </executions>
   </plugin>

像這樣的對continuous integration的友善支持,對以現代化開發流程為前提要選用framework來說,是很重要的。
像我一樣,跟Maven不很熟的朋友,建議看一下 Maven - Introduction to the Build Life-cycle,了解一下Maven會跑哪些步驟,你可以做些什麼。



CXF在Container裡面的設定

CXF 在Application configuration上,在2.4版以前是與Spring Framework耦合的,也就是說,你得給一份Spring的xml configuration。
在web.xml上,你有兩個方式可以apply這個設定:
宣告一個Spring的ContextListener

 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>WEB-INF/beans.xml</param-value>
 </context-param>

 <listener>
  <listener-class>
   org.springframework.web.context.ContextLoaderListener
  </listener-class>
 </listener>

或者,在CXFServlet 的宣告裡,透過init param 指定
<servlet>
 <servlet-name>CXFServlet1</servlet-name>
 <servlet-class>
  org.apache.cxf.transport.servlet.CXFServlet
 </servlet-class>
 <init-param>
  <param-name>config-location</param-name>
  <param-value>/WEB-INF/beans1.xml</param-value>
 </init-param>
 <load-on-startup>1</load-on-startup>
</servlet>

我並不是很喜歡採用一個web service方案的時候,還要被強迫在專案指定特定的DI framework,但我可以理解基於CXF的龐大與複雜度,一個適當的DI framework可以幫忙做很多骯髒活。
不過在Configuration DI 的Solution這個方面的選擇,個人認為Jersey做了一個比較漂亮的決定 - HK2 (HK2是一個相容於CDI、非常的輕量、一旦把作為一個組裝器的事情給做完,可以把後續移交給其他DI Container的DI framework)。
在2.4版之後,CXF開始將Spring從核心切割出去,想要開始一個不基於Spring做組裝的CXF核心,你可以在web.xml裡下這樣宣告:
<servlet>
 <servlet-name>NonSpringServlet</servlet-name>
 <servlet-class>
  org.apache.cxf.transport.servlet.CXFNonSpringServlet
 </servlet-class>
 <load-on-startup>1</load-on-startup>
</servlet>
簡單的說,不想要Spring就宣告個CXFNonSpringServlet(...這真的是很醜),這個Servlet 提供了一缸子的<init-param>給使用者客製化,大部分的值接受以換行符號或逗點分隔來給予多個參數(...這真的有夠醜,誰想要自己的web.xml被搞成這樣啊?)不喜歡這個作法的朋友,請create一個java class 去繼承CXFNonSpringServlet,事實上,目前的CXFServlet就是透過繼承它來實作的(也就是有地方可以給你挖Code、抄Code啦)。
於是,為了實現Google Guice + CXF,我自己實作了一個MyGuiceCXFJaxrsServlet.java:
public class MyGuiceCXFJaxrsServlet extends CXFNonSpringServlet {
 private static final long serialVersionUID = 4798627144134171969L;

 @Override
 public void init(ServletConfig servletConfig) throws ServletException {
  super.init(servletConfig);
  
  Bus bus = this.getBus();
  BusFactory.setDefaultBus(bus);

  JAXRSServerFactoryBean jaxrsFacBean = new JAXRSServerFactoryBean();
  jaxrsFacBean.setBus(getBus());

  
  // config OUT interceptors...
  configInInterceptors( jaxrsFacBean);
  
  // config IN interceptors...
  configOutInterceptors(jaxrsFacBean);
  
  // determine target jax-rs services
  configResources(jaxrsFacBean);
  
  jaxrsFacBean.setProvider(new JacksonJsonProvider());
  jaxrsFacBean.create();
 }
 /**
  * 
  * @param jaxrsFacBean
  */
 protected void configInInterceptors(JAXRSServerFactoryBean jaxrsFacBean) {
  List<Interceptor<? extends Message>> interceptors = 
    new ArrayList<Interceptor<? extends Message>>();
  
  interceptors.add(new JsonpInInterceptor());
  jaxrsFacBean.setInInterceptors(interceptors);
 }
 /**
  * 
  * @param jaxrsFacBean
  */
 protected void configOutInterceptors(JAXRSServerFactoryBean jaxrsFacBean) {
  List<Interceptor<? extends Message>> interceptors = 
    new ArrayList<Interceptor<? extends Message>>();
  interceptors.add(new JsonpPreStreamInterceptor());
  interceptors.add(new JsonpPostStreamInterceptor());
  
  jaxrsFacBean.setOutInterceptors(interceptors);
  
//  interceptors = new ArrayList<Interceptor<? extends Message>>();
//  interceptors.add(new FaultOutInterceptor());
//  jaxrsFacBean.setOutFaultInterceptors(interceptors);
 }
 /**
  * 
  * @param jaxrsFacBean
  */
 protected void configResources(JAXRSServerFactoryBean jaxrsFacBean){
  
  
  //TODO make this configurable...
  
  Injector injector = Guice.createInjector(new AbstractModule() {
   @Override
   protected void configure() {
    bind(User.class).toInstance(new User("Zanyking"));
    bind(CustomerService.class);    
   }
  });
  
  jaxrsFacBean.setResourceClasses(CustomerService.class);
  jaxrsFacBean.setResourceProvider(CustomerService.class, 
    new SingletonResourceProvider(
      injector.getInstance(CustomerService.class)));
 }
 
}
最主要將Guice與CXF接合起來的地方是在 ConfigResource(JAXRSServerFactoryBean) 這個method 的實作裡,我用Guice生成了一個基於jax-rs的CustomerService物件,給CXF去用。
對於想要直接custom一個CXF系統來用的情境,這個method的傳入參數:JAXRSServerFactoryBean的API就是關鍵,今天如果有人想要搞一個GuiceCXF還是WeldCXF,那需要的就是從這顆bean開始去挖CXF的架構來設計。
PS:其實,我還另外挖到一支 org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet ,它的介紹竟然只有這樣...這讓我感到很悲傷啊。

結論

我對於CXF感到不滿意的地方:
  1. JAX-RS 2.0的支援並不完全。應該說它還沒做完,在目前version 2.7.6,CXF並不支援javax.ws.rs.client.Client(我下了3.0.0-SNAPSHOT來看,看來未來它會把API都接好,但目前這個snapshot玩下去功能整個不會動是爛的...悲劇),你得用它的專屬WebClient API來撰寫測試。
  2. Documentation關於NonSpring這段的使用不完整且不友善,沒doc也就算了,沒sample code就很糟糕了,大部分的使用案例得要開發者看著Spring bean.xml去自己腦內翻譯成none spring version。

我對於CXF感到滿意的地方:
  1. 如果你喜歡XML configuration、Spring就是你的菜,那CXF太棒了。
  2. 出了很久,所以會發生的問題、範例、效能調整之類的東西,該解的都解了,如果用出問題,比較高的機會是開發者自己的問題。
  3. Maven有給archetype,這不是什麼了不起的玩意,但它有做。
雖然我想在目前跑的專案上,因為這玩意還不完全支援JAX-RS2.0,而且XML configuration對於專案成員來說也不是特別偏愛(都在用Guice了,你可以想見有很高的機率有人是XML hater)所以大概要出局,但若要我給這個產品一個分數,我想她還蠻OK的,基礎架構設計非常的java classic,當初開架構的沒有為了跟風亂搞什麼太fancy的東西結果四不像,一旦搞懂它的模型,設定上就四平八穩。
可見的未來它可能得遭遇一段陣痛期,我認為它得做好的工作有:
  • JAX-RS2.0 Compliant:沒啥好說,越快支援越好,還不支援的每天它都正在流失客群。
  • 去把跟其他DI的部份整好:不是誰都想用Spring的,而照顧其他DI framework使用者的需求不是一句:『自己去看Code』就結束的,做solution survey會真的挖下去看code的開發者可沒想像中那麼多。
  • 網站本身Doc的水準有待加強:我知道Apache是Open Source Java界的丐幫(專案武林最多、組織最大、什麼千奇百怪的需求都照顧),但一個向上爬、積極爭取眼球的專案最重要的就是doc與sample code,有很多外人幫你試出好的用法不代表你就不用去整理。

不曉得有多少人在用CXF?有在用的、或有什麼其他關於CXF的問題的朋友,歡迎回應。