顯示具有 debug 標籤的文章。 顯示所有文章
顯示具有 debug 標籤的文章。 顯示所有文章

2021-02-19

升版後 GetValueProvider 導致 GXT Grid 炸 NPE

經過緩慢且冗長的演進之後,開發環境終於逐步變成 Java 8 + GWT 2.8 + GXT 4.0…

然後昨天手賤去升級 Eclipse,結果重啟不能、抱怨 Java 8 不給用、得換到 Java 11(印象中)以後。把 JAVA_HOME 切到 OpenJDK 14.0.1 之後,換 GWT 罷工,理由是 GWT 2.8 只能用 Java 8。為了都使用同一個 JDK 的 無聊 理由,所以 GWT 就乾脆也升到 2.8.2,也就是 Java 14 + GWT 2.8.2 + GXT 4.0。

前面是前情提要,接下來終於進入到主角了:RQC

RQC (14e5fb7) 還停留在 Java 7 + GWT 2.7 + GXT 3.1 的狀態,而且那時 GoogleSheetToolkit 也還沒抽出去。所以得先處理開發環境升級…

然後就爆炸了… <囧>

目前確認的一個詭異炸點(也許還有其他的 😱 )是 SheetIdGrid.javagenColumnModel(),只要用到 GetValueProvider 就會在 attach 的時候炸 NPE(實際上是炸 AttachDetachException)。關鍵點是 GetValueProvider.getPath() 預設回傳 null,只要不用 GetValueProvider 或是 override getPath() 隨便回傳個空字串都行。

帳面上看起來似乎對症下藥了,但其實整件事很謎:

  • GetValueProvider 已經用 N 年、有 N 個 Grid 在用這玩意
  • 在另外一個 project(LATE)完全無法重現這個問題。
    • 這兩個 project 的差別就只有 RQC 原本是 Java 7 + GWT 2.7 + GXT 3.1,而 LATE 原本是 Java 8 + GWT 2.8 + GXT 4.0,其餘 pom.xml / gwt.xml 都(幾乎)一樣。

目前實在沒什麼想法 (X你X的,都無法重現了還能怎樣) ,只能就先留個紀錄備考。當然改變 GetValueProvider.getPath() 的回傳值是一個萬用解,不過那等到其他 project 也炸了再來考慮吧… 😭

2020-02-17

Service Worker 之存貓得狗

最近突然開始在測 Service Worker,理所當然拿教學文件上的那個「第一次看到狗、第二次以後看到貓」的範例自己跑跑看。

為了後面的劇情需要,這裡先講解一下這個範例在幹啥。它是在示範 Service Worker 攔截 request 的能力,程式刻意設計成在第二次(以後)瀏覽,明明網頁要顯示的依然是 dog.svg 這個 resource,但實際上 Service Worker 給的卻是 cat.svg,所以使用者看到的會是貓。

好的,我複製貼上了程式碼、直接抓範例網站的貓狗圖…

為什麼跑出來的完全都是狗狗狗狗狗…

原本還要測一些其他的東西,所以是自己開個 localhost server 試,理所當然沒有 https(我也不會掛… [死]),為了預防萬一所以還丟上 GitHub Pages 試試,一樣還是狗狗狗狗狗… (備註:其實與 https 無關,都可以運作)

◢▆▅▄▃ 崩╰(〒皿〒)╯潰 ▃▄▅▆◣

鬼打牆到已經放棄治療,正準備關機睡覺的時候,無意間發現… 幹,為什麼兩個圖檔開出來都是狗?那不管程式有沒有 bug、Service Worker 有沒有運作都馬一定看到狗阿… [死]

原本以為是自己手賤粗心存檔存錯,打算再抓一次圖檔測試看看,如果成功就自己去跪主機板,結果沒想到…

只要是在範例網站上用「另存圖片」的方式,就會遇到「存貓得狗」的結果

這邏輯感覺很詭異,不過仔細想想可能還是有理可循?以「在新分頁開啟圖片」的結果來說,就會看到 url 依然是 dog.svg 但畫面還是貓,這表示 Service Worker 在不同 tab 一樣會運作。至於「另存圖檔」、「複製圖片」這兩個行為應該是單純拿 url 作 curl 之類的動作,不會觸發 Service Worker,所以依然會得到真正的 dog.svg

(謎之聲:事後諸葛都碼很簡單)

於是我的「範例程式跑不動」歷史又增添了一筆。雖然說 browser 行為的確出乎意料,但是在鬼打牆的時候(明明都有把 catches.match('cat.svg') 印出來看,url 的確是 cat.svg)也沒懷疑到圖檔上頭還是缺失。 於是寫完這篇檢討報告之後來跪個滑鼠墊以作懲處

2019-06-04

JSON 日期碎碎念

最近(終於)在測 gwt-jackson,負責在 server side 噴 JSON 的是 Gson,然後測到日期(java.util.Date)的時候炸了一輪,所以來碎念一下留個紀念… XD

一開始以為是 gwt-jackson 炸掉,畢竟 GSON 資格老關係好(?),GWT 現在還有多少人在用都是個問題 lol。但是狗了一圈沒發現啥災情,事情開始有點詭異…

那找「gson date」試試看… WTF?GSON 預設的日期格式會隨平台不同而變?這就別提什麼 W3C 之類的標準了,根本亂搞一通嘛… =="

不過至少有解,就是可以用 new GsonBuilder().setDateFormat() 來設定 format 然後用這個 builder 來建立 Gson instance。

那麼,什麼是 JSON 標準定義的日期格式呢?根據這個 stackoverflow 的說法,JSON 根本沒做出定義… =="

好吧,至少 JS / W3C 貌似有,就是 ISO-8601

因為懶得查,所以直接狗「java dateformat 8601」,我的搜尋結果第一條是 stackoverflow,不過那是要把字串還原回 Date,不太對題。第二條跟第三條(居然)是簡體中文,都是對岸的 CSDN。

先說第三條,文章裡頭給的 pattern 是 yyyy-MM-dd'T'HH:mm:ss.SSS'Z',hmmm… 看起來跟前面 stackoverflow 附的範例一樣,丟下去跑也能正常 parse,太好了可以收工了… 才怪… 得到時間不對,整整多了 8 小時。WTF?時區問題?

算啦算啦… 去測第二條吧,直接拿文章內說可行的 yyyy-MM-dd'T'HH:mm:ss:SSSZZ 來試試看… 連 parse 都過不了?WTF?等等,為什麼反覆測試下發現有時候會 parse 過、而且值也正確?但有時候卻又 parse 不過?幹這是七月半提前報到嗎?

鬼打牆了 n 分鐘之後,終於發現… 測試會過的時候是測完第三條之後把 Z 前後的單引號拔掉,而測試不過的時候是直接複製第二條的文字…

對,X 他 X 的第二個給的 pattern 根本有問題,按照 ISO-8601 的規格,在 sec 跟 ms 中間應該是「.」而不是「:」。肉眼不仔細比對根本很難發現… Orz

到了這個時候,真的是被嚇到了,乖乖回頭看文件。在 Java API 的定義當中,「X」跟「Z」都表示時區,「X」是 ISO-8601 格式、「Z」是 RFC-822 格式(不過目前看不出差異)。ISO-8601 要求日期與時間之間以一個寫死的大寫「T」連結,寫成 Java 的 pattern 就要前後加上單引號。所以第三條 pattern 尾巴的「Z」是寫死不變的。那,為什麼 parse 會過呢?

ISO-8601 當中規定,如果時區剛好是 UTC(零時區)就顯示 Z,所以得到的是合法的字串,但是除非人在 UTC 不然解出來的實際 Date 就會有時差問題… Orz

心得與結論:

  • 即使有名有號的 library 還是有可能存在奇妙的行為。即使到現在我還是無法替 Gson 在日期上的作法想出任何合理的理由…
    • 寫這篇文章的時候認真找了一下,原來 Gson 有開過 issue-281 還 close 了,整個看起來有點莫名而且最後路人們還是在用 GsonBuilder 這招? WTF?
  • google 出來的結果未必可信,即使排名在很前面。stackoverflow 上也是。像這個解答還有 62 個推,底下也只有一個人指出這是不對的答案。
  • 雖然說官方文件也不是不會出錯,但相比來路不明的 blog,機率還是低的多(雖然啃起來也難過很多)

2019-04-05

GF TextUtil debug 雜記

自從在前前公司接觸 GXT、接著把 Chart 的底層 DrawComponent 給翻了一遍之後,就對這玩意很感興趣,之後陸陸續續以 DrawComponent 為基礎搞了一些東西出來。去年終於搞了一個 GF 版的 TextButton 出來。TextButton重點 惡搞之處在於文字的字體會隨著整體大小而自動調整。好不好用很難說,自己是頗為得意啦… 囧>,因為算是集大成之作:

  • 驗證了 GF Layer 機制的可用性
  • 處理 TextSprite 在視覺上的 y 軸位移問題(雖然沒有相對正統地用後來搞出來的 FontMatrics 來校正 XD)
  • 大幅解決效率問題(因為發現有 Sprite.redraw() 而不用每次都搞 DrawComponent.redraw()

不過實務上陸陸續續有炸出一些問題,在某些狀況下初始的字體並沒有變成正確的大小。但是因為一直都能 workaround 掉,所以沒提煉 SSCCE、自然也沒深究

2011-10-27

GWT 2.4.0 需搭配 gwt-maps 1.1.1rc1

雖然這篇文章可能一兩個月後就沒啥鳥用,但是為了這點鳥事搞了一個下午,還是寫篇文章以供日後緬懷...... [遠目] (其實根本就是想點擊率吧? [指])

故事的前情提要是我想要透過 Google Maps API 作一些壞事,但是用 JavaScript 做起來實在不夠愉快,更不用說有些東西已經偷懶用 JSP 控制還是不能徹底解決問題。好吧,那就徹底 Java 到底,透過 gwt-google-api 的 Maps 來惡搞。

2009-09-10

ColorPicker (auroris) Bug Fix

技術提供:aries

「http://code.google.com/p/auroris/」這是一個 GWT 上的 3rd party library,負責提供還不錯的 color picker 元件。不過,在實際使用的時候,卻會有「某些時候」中間那條直立漸層色條出不來的 bug。經過一番血戰之後,終於抓到了... 設定顏色的時候少一個「#」

//ColorPicker.java 的片段
    public void onClick(Widget sender) {
        if (sender == rbHue) {
            // skip
        } else if (sender == rbSaturation) {
            if (colorMode != SliderMap.Saturation) {
                colorMode = SliderMap.Saturation;
                slidermap.setColorSelectMode(SliderMap.Saturation);
                sliderbar.setColorSelectMode(SliderBar.Saturation);
                slidermap.setOverlayColor("transparent");
                sliderbar.setLayerColor("#ffffff", SliderBar.BarC);
                sliderbar.setLayerOpacity(100, SliderBar.BarD);
            }

            slidermap.setOverlayOpacity(100 - saturation);
            /* ERROR
             * sliderbar.setLayerColor(tbHexColor.getText(), SliderBar.BarD);
             */
            sliderbar.setLayerColor("#" + tbHexColor.getText(), SliderBar.BarD);

            sliderbar.setSliderPosition(256 - (int) ((new Integer(saturation)
                    .floatValue() / 100) * 256));
            slidermap
                    .setSliderPosition(
                            (int) ((new Integer(hue).floatValue() / 360) * 256),
                            256 - (int) ((new Integer(brightness).floatValue() / 100) * 256));
        } else if (sender == rbBrightness) {
            // skip
        } else if (sender == rbRed) {
            // skip
        } else if (sender == rbGreen) {
            // skip
        } else if (sender == rbBlue) {
            // skip
        }

        if (colorMode == SliderMap.Red || colorMode == SliderMap.Green
                || colorMode == SliderMap.Blue) {
            // skip
        }
    }

其實造成「某些時候」才會出問題的原因不在這裡,而是 HTML 碼有沒有這個「
<DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">」。拿掉的話,錯誤也就不會發生,不過,不怎麼建議用這招就是了。

測試環境:
  • GWT 1.7
  • FireFox, Chrome(IE 不會出問題)