Friday, September 23, 2005

cherry tree

ใน Processing Blogs
blprnt เขา post source code ที่่ paint รูปต้นไม้

  • cherrytree (***** เอาไปห้าดาว)
  • birchtree (ตอนที่กิ่งน้อยๆ สวยกว่าตอนกิ่งเยอะๆ)

Related link from Roti

Thursday, September 22, 2005

My First JBI Component

วันนี้ทดลอง implement JBI Component
(Java Technology and Business Integration Services)
เพื่อที่จะทดลอง deploy เข้าไปใน ServiceMix

เหมือนเคย ถ้าทำตาม spec ของ Sun แล้ว
คงต้องทำอะไรต่างๆนานายุบยับไปหมด
(ตามประสา sun ที่ spec มักจะแบ่งเป็นขั้นเป็นตอน
ขั้นนี้ให้ role นี้ทำนะ ขั้นนู้นให้ role นู้นเขาเป็นคนทำ)
พวก developer มือเดี่ยวอย่างเรา (ทำมันทุก role)
ก็เลยขัดอกขัดใจ

โชคดีที่ ServiceMix เปิดช่องให้เรา
ใส่ component ของเรา ผ่านเข้าไปโดยใช้
Spring config file ทำให้ชีวิตง่ายขึ้น

เนื่องจากเป็น component แรกในชีวิต ก็เลยจัดการลอก
จากตัวอย่างที่มีนั่นแหล่ะดัดแปลงนิดหน่อย

เป้าหมายที่ทดสอบ


Quartz timer component ===msg===> Log Component



Quartz Timer Component ก็ใช้ build in ของ ServiceMix
ไม่ต้องลงแรง
ส่วน Log Component ก็ลอกเขามาเลย


public class LogComponent extends ComponentSupport {

private Log log = LogFactory.getLog(TraceComponent.class);


public Log getLog() {
return log;
}

public void setLog(Log log) {
this.log = log;
}

public void onMessageExchange(MessageExchange exchange) throws MessagingExce
ption {
// lets dump the incoming message
NormalizedMessage message = exchange.getMessage("in");
if (message == null) {
log.warn("Received null message from exchange: " + exchange);
}
else {
log.info("Exchange: " + exchange + " received IN message: " + messag
e);
}
}
}


ทดลอง run ปรากฎว่า เงียบหาย
ไม่เห็น message อะไรที่ console
ก็เลยสงสัยว่าเกิดอะไรขึ้น
นั่งพยายามค้นหาอยู่นาน
ในที่สุดก็พบว่า
  • ห้ามลืม implements MessageExchangeListener เด็ดขาด ถ้าลืมมันจะไม่สามารถรับ message ได้
    public class LogComponent extends ComponentSupport 
    implements MessageExchangeListener {...}

    อันนี้ผิดเอง ลอกเขามาแล้วยังลอกผิดอีก
  • ที่เราสั่ง log แสดงผลนั้น มันจะไม่แสดงผลอะไรออกมาให้เราเห็น
    ส่วนสาเหตุนั้นยังนึกไม่ออก ตอนแรกนึกว่าเป็นเพราะชื่อ package เราไม่ตรงกับเขา
    ตัว Logging Filter ก็เลยไม่แสดงผลของเรา
  • คำสั่ง System.out.println จะไม่แสดงผลออกที่ console
    ไม่รู้มัน redirect ไปไว้ไหน
  • สุดท้ายก็เลยต้องใช้วิธีเขียน log ลง File System เอง
    ก็เลยพบว่ามันทำงานได้เป็นปกติ


หลังจากอ่านเอกสารของ ServiceMix ไปสักพัก
ก็พบว่า เราสามารถ implement Component
ในลักษณะ POJO ได้เลย
public class PojoReceiver implements MessageExchangeListener {

public void onMessageExchange(MessageExchange exchange) throws MessagingExce
ption {
NormalizedMessage message = exchange.getMessage("in");
....

}

}


เป้าหมายที่จะลองถัดไปก็คือ
check ดูว่า ActiveMQ ที่ bundle มานั้น support Stomp Protocol แล้วหรือยัง
ถ้ายังก็จะได้ upgrade เสีย
หลังจากนั้นก็ทดลอง integrate ruby application
เข้ากับ ServiceMix ผ่านทาง Stomp protocol

Related link from Roti

convert wma to mp3

มี file wma แต่อยาก convert เป็น mp3
ก็เลย search ใน internet ดู
เจอ script นี้

#!/bin/bash
#
# Dump wma to mp3

for i in *.wma
do
if [ -f $i ]; then
rm -f “$i.wav”
mkfifo “$i.wav”
mplayer -vo null -vc dummy -af resample=44100 -ao pcm -waveheader “$i” -aofile “$i.wav” &
dest=`echo “$i”|sed -e ’s/wma$/mp3/’`
lame -h -b 192 “$i.wav” “$dest”
rm -f “$i.wav”
fi
done

ลอง run แล้ว ตอนแรกนึกว่า Error
เพราะเห็น message บอกว่า malloc ... ยาวเหยียด
แต่จริงๆแล้วไม่ใช่
คงเป็นเพราะเป็นการแปลงแบบไม่รู้ความยาวที่แน่นอน
(ใช้ fifo)

Related link from Roti

Wednesday, September 21, 2005

JBoss Seam

เมื่อวานอ่านเจอเรื่อง JBoss Seam
ซึ่งเป็น Application Framework สำหรับ Java EE5
จุดเด่นของ Seam ก็คือการ integrate context ระหว่าง
Presentation Context (JSF) กับ Business Logic Context (EJB)

Gavin King (founder ของ Hibernate) บอกว่า
One of the (several) goals of Seam is to bring Ruby On Rails style productivity to the Java EE platform


วันนี้ก็เลยนั่งทำ Diagram ที่ present ให้เห็นภาพว่า
การ integrate ระหว่าง jsf context กับ ejb context
ว่าเชื่อมต่อกันอย่างไร



  1. เริ่มจาก user submit ข้อมูลจาก jsp
    seam จะพยายาม binding data เข้าไปที่ Entity Bean
    เมื่อพบว่ามีการระบุ user.name
    seam ก็จะมองหา Entity Bean ที่มี annotaion ระบุ @Name("user")
    เมื่อรู้ว่าเป็น entity ตัวไหนแล้ว
    seam ก็จะ initialize Entity Bean นั้นขึ้นมา
    พร้อมกับทำการ set ค่าให้
  2. ใน submit component ที่ jsp มีการระบุ action ไว้ว่า
    ต้องการให้ trig action ที่ชื่อ register.register
    seam ก็จะทำการหา Session Bean ที่มีการ annotation ระบุเป็น @Name("register")
    แล้ว call method ที่ชื่อ register ให้
  3. ในจังหวะก่อนที่จะเริ่ม call นั้น
    seam จะตรวจว่า Session Bean นั้นต้องการให้ inject
    อะไรบ้าง ซึ่งจะพบว่า RegisterAction ต้องการให้ inject
    user (ที่เกิดจากข้อ 1) เข้ามาด้วย
    นอกจากนี้ยังสามารถ inject FacesContext (Context ของ Presentaion Layer)
    เข้ามาด้วย ซึ่งทำให้เราสามารถส่ง message กลับไปยัง Presentation Layer ได้ง่าย
    เช่นการ push Error Message กลับไป
  4. หลังจากทำงานสำเร็จ method register
    ก็จะ return name ของ Page ที่ต้องการแสดงผลกลับมา
    ซึ่งจะถูกนำไป search ใน face-config.xml file
    เพื่อหาว่า jsp ตัวไหนเป็นผู้รับผิดชอบในการ render


ดูแล้วเยี่ยมมากเลย
เมื่อบวกกับ ประเด็นที JBoss มี Embed EJB3 Container ออกมา
(สามารถนำไป embed ใน Tomcat ได้)
ทำให้ Seam ดูจะเป็นคู่แข่งที่น่ากลัวของ Tapestry 4



ส่วนใครที่ยังไม่เคยเห็น Spec ของ EJB3 นั้น
แนวทางของ EJB3 จะออกมาดังนี้

ใช้ Annotation เข้ามาช่วย
ทำให้ลด xml config file ไปได้จำนวนหนึ่ง
พร้อมทั้งเปลี่ยน model ในการเขียน Session Bean
ไปเป็น POJO (เหมือนที่ spring ทำอยู่)
ทำให้ลด Overhead ในการเขียน EJB แบบเดิม
ซึ่งต้องมี interface วุ่นวายไปหมด

ในส่วนของ Entity Bean ใน Spec EJB3 นั้น
สำหรับคนที่ใช้ Hibernate เป็นอยู่แล้ว
ก็แทบจะไม่ต้องเรียนรู้อะไรเพิ่มเติมเลย

อ่านเพ่ิมเติม
SEAM - Contextual Components

Related link from Roti

Monday, September 19, 2005

เขียน Code Snippet Web Application

ตอนนี้ศึกษาหลาย topic, language พร้อมๆกัน
ทำให้หน่วยความจำในสมองไม่พอใช้ เกิดอาการหลงลืม
คำสั่งต่างๆ ก็เลยคิดจะทำ code snippet ดีๆ ไว้ใช้เอง
วันนี้ก็เลยนั่งเขียนโปรแกรมนี้ทั้งวัน

feature ที่ต้องการก็คือ
  • syntax highlight code ได้
  • ระบุ Tag สำหรับแต่ละ snippet ได้
  • search by Tags ได้


opensource project ที่ load มาใช้ประกอบด้วย
  • Rails -> framework ที่ใช้เขียน
  • Taggable -> เป็น extension ของ ActiveRecord ใช้จัดการเรื่อง Tag
  • Syntax -> ใช้ทำ syntax highlighting
    (build-in support แค่ ruby, yaml, xml แต่สามารถเขียน plugin เองได้)


เวลาที่ใช้เขียนรวมๆ แล้วก็ประมาณ 6 ชั่วโมง
(ยังไม่ได้ทำเรื่องสวยงาม อันนี้ใช้เวลาเยอะกว่าเขียน code แน่ๆ)

ซึ่งไม่เลวเลยสำหรับ framework ที่ยังไม่เคยเขียน
จริงๆจังมาก่อน (เขียนไปนั่งเปิด manual อ่านไป)
ถือได้ว่า rails มี productivity ที่ใช้ได้เลย

ตัวที่ใช้เวลามากๆหน่อย ก็จะเป็นในส่วน
  • syntax highlight ที่ต้องเขียน plugin ให้ render java code ได้
  • taggable -> อันนี้พบ bug ในส่วน finder sql
    คนเขียนเข้าใช้ sql ที่ไม่เป็นมาตรฐาน ทำให้ run บน postgres ไม่ได้ ก็เลยต้องเขียน patch
    ที่ run บน postgres ได้


การเขียนด้วย opensource library แบบนี้ได้ความรู้ดี
เพราะถ้าเป็น opensource ใหม่ๆหรือที่ไม่ได้รับความนิยม
ก็จะไม่ค่อยมีเอกสารมากนัก ต้องเข้าไปใล่ source code ของเขาดูเอง
และเนื่องจากเป็น project ที่ขนาดไม่ใหญ่
ทำให้เราไล่ source code ได้ไม่ยากนัก

เป้าหมายถัดไป ก็คือไป load เอา source code ของ
http://www.bigbold.com/snippets/
มานั่งไล่ source code ดู
ตัวนี้เขียนด้วย rails เหมือนกัน

Related link from Roti

Implement Domain Validatation ด้วย "AspectJ Introduction"

เวลา Design Application เรามักต้องตัดสินใจว่า
จะ implement Validation Logic ไว้ที่ Layer ไหนดี

RubyOnRails implement Validation Logic ไว้ที่ Model
(domain layer)
struts (รวมทั้ง MVC อื่นๆของ java) provide Validation Logic
ไว้ที่ Presentation Layer

ข้อดีของการ provide Validation Logic ไว้ที่ domain
ก็คือ กรณีที่มี Presentation Layer หลายๆแบบ
validation logic ก็จะ share อยู่ที่เดียว ไม่กระจัดกระจาย

วันนี้เราจะลองเอา AspectJ ซึ่งเป็น AOP
มาลองทำ Validation แบบ Mixin บ้าง
สมมติเรามี Class Person
public class Person {

private String name;
private int age;

public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

}

Note: Person Class ที่เราเขียน จะเป็น POJO เพียวๆเลย
ไม่มี business logic อะไรอยู่ในนั้นเลย


ออกแบบ Validataion Framework ให้มี Class ดังนี้



เป้าหมายที่เราต้องการ ก็คือ เราจะเขียน logic ในส่วนของการ
validate สำหรับ Person แยกไว้เป็นอีก file หนึ่ง (เรียก Aspect)
แล้วใช้ AspectJ ทำการ mix Person class กับ Aspect ที่เขียนไว้เข้าด้วยกัน

สร้าง Aspect ที่ชื่อ PersonValidate.aj
public aspect PersonValidate {
declare parents: Person implements Validatable;

public Errors Person.validate() {
Errors errs = new Errors();
if (this.getName() == null ||
this.getName().length() == 0) {
errs.addError("name", "name must not be empty");
}
if (this.getAge() <= 0) {
errs.addError("age", "age must not be negative or zero");
}
return errs;
}

}

ใน PersonValidate.aj จะมีการ declare parents: Person implements Validatable;
การสั่งแบบนี้ ก็คือเราจะกำหนดให้ Person Class implement Interface ที่ชื่อ Validatable
จากนั้นก็กำหนด method validate ให้กับ Person class
(method validate เป็น method ที่ declare ไว้ใน Validatable interface)
สังเกตุดูใน code จะเห็นว่าเราสามารถใช้ this ในการอ้างถึง person instance
ที่ถูก modify ได้

ทดลอง Run
    public static void main(String[] args) {
Person p = new Person();
p.setAge(-1);

Validatable vt = (Validatable) p;
Errors err = vt.validate();

for (int i = 0; i < err.size(); i++) {
System.out.println(err.getError(i));
}
}


ได้ผลลัพท์ดังนี้

name:name must not be empty
age:age must not be negative or zero


จะเห็นได้ว่า แนวคิดนี้ ดูน่าสนใจทีเดียว (ในแง่ Architecture)
แต่ความคิดนี้ยังไม่ได้ทดลองทำจริงนะ ก็เลยยังไม่รู้ว่าจะเกิดโทษ
หรือเกิดประโยชน์อย่างไรบ้าง

Related link from Roti

Sunday, September 18, 2005

Net อืดสุดๆ

ช่วง 3-4 วันมานี้ net ช้ามาก
ได้ความเร็วแค่ 2 k เอง

วันนี้ความเร็วเริ่มเพิ่มขึ้นแล้ว
ก็เลยฉลอง เข้าไปวาดรูปเล่นซะ 1 รูป
http://artpad.art.com/?imz0kkg8vsc

Related link from Roti