code_prettify

2013年8月30日 星期五

synchronized method無效的假象

系統有個 table紀錄人員編號, entity為
public Class Foo {
  private String prefix1;
  private String prefix2;
  private int serial;
}
有個取號程式會依(prefix1, prefix2)去取得目前流水號,並將 tablek的 serial加1.
為了避免多個 thread搶序號問題, 取號的 method(select and update table)加上了 synchronized.
但卻發現依然出現 serial重複的問題.
測了半天才發現是因為我們用 hibernate.
第二個 thread load entity時 return的是第一個 thread load後的 cache.
加上 session.clear()就解決了.
害我一直很擔心如果真的是 synchronized失效,不知道要加多少班解決這個問題了.

2013年8月29日 星期四

Class org.apache.struts.chain.commands.util.ClassUtils can not access a member of class with modifiers ""

手殘把 public Class XXX的 public刪掉,成了 Class XXX就出現上述錯誤了

2013年8月16日 星期五

eclipse的 Internal validation error java.lang.NullPointerException line 0 JavaScript Problem

看來這個 bug一直無解.
但是退而求其次,不想看到這些 warning,設定起來也是很騙人布
一直忘記該取消哪些
寫下來省個搜尋的工
1.project>properties>Builders-> uncheck Javascript Validator.
2.Window>Preferences>JavaScript>Validator>Errors/Warnings-> uncheck Enable JavaScript semantic validation.

2013年8月13日 星期二

struts 1的 ActionForm, default scope是 session

在 struts-config中, action tag如果沒指定 scope, 預設 scope為 session.
一般都會把 scope設為 request
不過那個爛系統,竟然有一堆都是 default scope
於是就造成了我的悲劇:
public class TheForm extends ActionForm {
private int[] aField;
........
}
jsp
<form name="theForm">
<table>
<tbody id="讓 user新增資料處">
</tbody>
</table>
<input type="button" onclick="在atbody新增一列sample row"/>
</form>
<table id="已經被儲存的新增資料">
<tr><td>
<input name="oldAField" value="1"/>
</tr></td>
<tr><td>
<input name="oldAField" value="2"/>
</tr></td>
<tr><td>
<input name="oldAField" value="3"/>
</tr></td>
</table>
sample row
<tr><td>
<input name="aField" value=""/>
</tr></td>
只准新增,沒有刪除修改.form submit的時候把"讓 user新增資料處"的內容存到 DB.
scenario:
user新增了一筆資料, session還在的時候,同個頁面修改別的地方後儲存.
由於 theForm放在 session裡,上次 submit的新增資料還在theForm裡
但是畫面上沒有新增 aField, 所以 submit出去的 aField是 null, struts不覆蓋 theForm.aFiled.
於是乎,上次的新增資料再次被儲存.

2013年8月8日 星期四

跨 frame資料存取,不考慮 cross-domain

pseudo code
<html>
......
<iframe id="frame1">
<iframe id="frame2">
</html>

iframe1:
<html>
<html>

iframe2
<html>
<input type="text" name="isOk" value="0"
<html>
需求是在 iframe1裡面需要 iframe2的 isOk的值作判斷
直覺的 javascript(in iframe1):
var isOk = parent.document.getElementById('iframe2').document.getElementById('isOk');
.....
但是測了半天才發現 parent.document.getElementById('iframe2')根本沒拿到 iframe2而是拿到 parent.
印出 parent.document.getElementById('iframe2').document.body.innerHTML才發現根本是 parent的內容.

解決方法:
改用 parent.frames['iframe2']

觀念錯誤處:尚未找出.還是不知道為什麼 parent.document.getElementById('iframe2')拿不到 iframe2

收穫:搜尋過程中找到幾個
Web technology for developers
window.frames解說
each item in the window.frames pseudo-array represents the window object corresponding to the given <frame>'s or <iframe>'s content, not the (i)frame DOM element (i.e. window.frames[ 0 ] is the same thing as document.getElementsByTagName( "iframe" )[ 0 ].contentWindow)
iframe scripting
From the DOM iframe element, scripts can get access to the window object of the included HTML page via the contentWindow property. ThecontentDocument property refers to the document element inside the iframe (this is equivalent to contentWindow.document), but is not supported by Internet Explorer versions before IE8.

2013年7月26日 星期五

遍歷整個 List並且移除符合條件的物件要用 Iterator.remove()或 List.remove(index)

要遍歷整個 Collection並且移除符合條件的物件, 用 for (Object obj : list)不可行(throw ConcurrentModificationException)
要用 Iterator迭代並且用 Iterator.remove()移除(原始 list會被修改).

下面的程式碼不可行(throw ConcurrentModificationException)
List<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < 100; i++) {
list.add(Integer.valueOf(i));
}
String point1 = "point1: ";
String point2 = "point2: ";

for (Integer integer : list) {
log.debug(point1 + list.size());
if (integer % 7 == 0) {
list.remove();
}
log.debug(point2 + list.size());
}
必須用傳統的 for(int i=0....
Integer integer = null;
  for (int i = 0; i < list.size(); i++) { log.debug(point1 + list.size()); integer = list.get(i); if (integer % 7 == 0) { list.remove(i); } log.debug(point2 + list.size()); }
 Iterator.remove()
Integer integer = null;
for (Iterator<Integer> itr = list.iterator(); itr.hasNext();) {
log.debug(point1 + list.size());
integer = itr.next();
if (integer % 7 == 0) {
itr.remove();
}
log.debug(point2 + list.size());
}

2013年6月27日 星期四

SQL中某些 NESTED case when的 coalesce寫法

coalesce: 依序檢查並回傳運算式中第一個 not null的運算結果
ex. select coalesce(col1, col2, col3) from table1.
coalesce依序判斷 col1, col2, col3是否 not null. 若三者皆 not null, 回傳 col1.
這裡面其實已經隱含了 if else的架構,我們只需要適當的分析我們的條件套進去

例如:
select (case when col0<>0
  then col1
  else
    case when col00 is null
    then col2
    else col3
    end
  end
) as col
from EMPLOYEE_WRITE_OFF ewo
join EMPLOYEE_SALARY_DETAIL esd on esd.AUTO_ID=ewo.EMPLOYEE_SALARY_AUTO_ID

可以改寫成如下:
select
coalesce
(
 -- if
  case when col0<>0 then col1 else null end
 -- else
    -- if
  , case when col00 is null then col2 else null end
    -- else
  , case when col00 is not null then col3 else null end
) as col
from table1

至於哪一種比較方便或清楚
可以用 coalesce時個人是喜歡 coalesce.

寫的時候,兩種其實沒甚麼差別.
  就像那種超過 200行的 if else
  ( 就真接手過這種系統
    裡面幾乎所有的主要邏輯
    都有 200行以上的 if else(if), 噩夢)
  寫的時候都是逐步插進去的
  ( 最好是那種2 300行甚至高達 500多行的 if else
    會是 waterfall式地一氣呵成寫下來
    有能力在腦袋裡想完這 2 300行 if else
    為什麼不把時間用在將程式碼規畫好
    該抽出去的抽出去)
  寫起來沒啥難的
  被表到的是接手的人
--------------------------------
題外話: 
以前看混沌理論的介紹書的時候
介紹到科學家羅倫茲的時候
提過一段軼事
說研究生偷偷看了羅倫茲的程式碼
幾千行程式碼不分段落一氣呵成寫下來
望之如有字天書
用來烘襯羅倫茲的天才
寫程式讀程式的時候常會想起這個小故事
引以為 anti-pattern
關起門來愛怎麼搞怎麼搞
難以維護也是保護自己程式的方法之一(真這樣想的人大概不知道甚麼叫混淆器)
只要自己能維護就好
別人管不著
但是在 team work, 在企業環境中
這種人是不是天才有待考證
可以確定的稱號之一叫毒瘤

但如果是忘光後回來重看
我覺得 coalesce寫法我的呆瓜腦袋比較容易吸收:Q