Saturday, April 01, 2006

SCA (แถม SD0)

มาอีกแล้ว Term ใหม่ที่ชื่อ SCA (ไม่ใหม่เท่าไร, white paper ที่ผมอ่าน,มัน เดือน november 2005)
SCA (Service Component Architecture)
โต้โผก็คือ IBM, SAP, IONA, BEA, Oracle, ... (ยกเว้น SUN)
ผลักดันเพื่อเป็นตัวเสริมทัพ SOA (Service Oriented Architecture)

ท้าวความ SOA นิดหนึ่งก่อน
SOA จะมี nature อย่างหนึ่งก็คือ
มันเป็น coarse-grained service
nature ของ coarse-grained service ก็คือ
มี method ให้ใช้ไม่มาก, parameter ที่่รับส่งมักจะเป็นแบบ document oriented style

ตัว SCA ก็คือ Framework ที่เราสามารถใช้
fine grained component
ประกอบขึ้นเป็น SOA Service (coarse-grained service)
(ผู้ไม่คุ้นกับ java คงจะเริ่มบ่นว่า ยุ่งจังโว้ย)

ผมเป็นพวกต้องเห็น code ก่อนจึงจะเข้าใจ concept
ดีที่ตอนนี้มี Incubator project ที่ชื่อ Tuscany
submit code เข้าไปใน apache แล้ว
ก็เลยมีตัวอย่างให้ดู

ลองดูตัวอย่าง HelloWorld service ก่อน

เริ่มด้วยการ define interface ก่อนว่า helloworld มี method อะไรให้เรียกใช้
public interface HelloWorldService {

public String getGreetings(String name);

}

จากนั้นก็ตามด้วย implementation
@Service(HelloWorldService.class)
public class HelloWorldServiceComponentImpl implements HelloWorldService {

/*
* @see org.apache.tuscany.samples.helloworld.HelloWorldServiceComponent#getGreetings()
*/

public String getGreetings(String name) {
return "Hello " + name;
}

}

เริ่มสังเกตุเห็น key concept ของ SCA แล้ว
  • Service Implementation มีลักษณะเป็น POJO (plain old java object)
  • ใช้ Annotation เข้ามากำหนด Nature


เมื่อมี interface กับ implementation แล้ว
ก็มาถึง module definition
module ก็คือ group ของ component ที่ deploy ร่วมกัน
(ในกรณี helloword เรามี component เดียว)
<module xmlns="http://www.osoa.org/xmlns/sca/0.9" xmlns:v="http://www.osoa.org/xmlns/sca/values/0.9"
name="sampleHelloworld">

<component name="HelloWorldServiceComponent">
<implementation.java class="org.apache.tuscany.samples.helloworld.HelloWorldServiceComponentImpl"/>
</component>

</module>

ตรงนี้ยังมองไม่เห็นอะไรมากนัก เพราะมันยังมีแค่ component เดียวอยู่
ไว้กลับมาดูอีกทีตอนมีหลาย component

มาดูตอนใช้งานบ้าง
ส่วนของ client ที่เรียกใช้ จะมีหน้าตาดังนี้
public class HelloWorldClient {

public static final void main(String[] args) throws Exception {

// Obtain Tuscany runtime
TuscanyRuntime tuscany = new TuscanyRuntime("hello", null);

// Start the runtime
tuscany.start();

// Obtain SCA module context.
ModuleContext moduleContext = CurrentModuleContext.getContext();

// Locate the HelloWorld service component and invoke it
HelloWorldService helloworldService = (HelloWorldService)
moduleContext.locateService("HelloWorldServiceComponent");

String value = helloworldService.getGreetings("World");

System.out.println(value);

// Stop the runtime
tuscany.stop();
}
}

จะเห็นว่ามี concept ของ Runtime
ตัว SCA เป็นแค่ spec ดังนั้นต้องมี implementation ถึงจะทำงานได้จริง
Tuscany ก็คือ implementation ที่ว่า
นอกจากนี้ จะเห็นได้ว่าเราต้อง lookup service จาก module

ลองดูตัวอย่าง Module definition ที่มีหลาย component บ้าง
<module xmlns="http://www.osoa.org/xmlns/sca/0.9" xmlns:v="http://www.osoa.org/xmlns/sca/values/0.9"
name="sampleHelloworld">

<component name="HelloWorldServiceComponent">
<implementation.java class="org.apache.tuscany.samples.helloworldmc.HelloWorldServiceComponentImpl"/>
<references>
<v:greetingPrefix>GreetingPrefixComponent</v:greetingPrefix>
<v:greetingSuffix>GreetingSuffixComponent</v:greetingSuffix>
</references>
<properties>
<v:greetingMiddle>SCA</v:greetingMiddle>
</properties>
</component>

<component name="GreetingPrefixComponent">
<implementation.java class="org.apache.tuscany.samples.helloworldmc.GreetingPortionProviderImpl"/>
<properties>
<v:greetingPortion>Hello</v:greetingPortion>
</properties>
</component>

<component name="GreetingSuffixComponent">
<implementation.java class="org.apache.tuscany.samples.helloworldmc.GreetingPortionProviderImpl"/>
<properties>
<v:greetingPortion>World</v:greetingPortion>
</properties>
</component>
</module>

เห็นแล้วอย่าพึ่งถอดใจ ปรับสายตาสักนิด จะเห็นว่า
มันใช้หลักการเดียวกับ Spring นั่นคือ Dependency Injection
การร้อย component หรือการ config component ใน SCA
จะใช้หลักการเดียวกับ spring

หลายคนจะเริ่มสงสัยแล้วว่า มันเป็น webservice อย่างไร
กรณีที่เราต้องการให้เป็น web service ก็ต้องมีการ กำหนด entry point
ใน Module ด้วย
<module xmlns="http://www.osoa.org/xmlns/sca/0.9" xmlns:v="http://www.osoa.org/xmlns/sca/values/0.9"
name="sampleHelloworld">

<entryPoint name="HelloWorldService">
<interface.wsdl interface="http://helloworldaxis.samples.tuscany.apache.org#HelloWorldServiceImpl"/>
<binding.ws port="http://helloworldaxis.samples.tuscany.apache.org#helloworld"/>
<reference>HelloWorldServiceComponent/HelloWorldService</reference>
</entryPoint>

<component name="HelloWorldServiceComponent">
<implementation.java class="org.apache.tuscany.samples.helloworldws.HelloWorldServiceComponentImpl"/>
</component>

<import.wsdl
location="wsdl/helloworld.wsdl"
namespace="http://helloworldaxis.samples.tuscany.apache.org"/>

</module>

จะเห็นประเด็นหนึ่งที่ว่า definition ของ entrypoint ได้มาจาก
file wsdl โดยตรง
และมี keyword ที่เรียกว่า "binding"
spec ของ SCA เปิดโอกาสให้เรา binding ในรูป protocol อื่นได้เช่น
    <entryPoint name="HelloWorldService">
<interface.java interface="org.apache.tuscany.samples.helloworldjsonrpc.HelloWorldService"/>
<jsonrpc:binding.jsonrpc/>
<reference>HelloWorldServiceComponent/HelloWorldService</reference>
</entryPoint>

อันนี้เป็นการ binding service เป็น JSON rpc service

ที่ขาดไม่ได้คือ key สำคัญของ SCA ไม่ได้อยู่ที่ model ของ Component อย่างเดียว
แต่อยู่ที่ SDO (Service Data Object) ด้วย
SDO เข้ามาเป็น key ได้อย่างไร
จำประโยคที่ว่า "Coarse Grain Service พึงมี parameter style เป็น Document Style"
SDO ก็คือ Data Model ที่ช่วยให้เราจัดการกับ Document Style นี้ได้ง่ายขึ้น
เพราะ เราสามารถ pass document ในรูป SDO ไปให้ Party อื่นๆ
เมื่อ Party นั้นๆ ทำการแก้ไขรายการใน document เสร็จ (เช่น fill-in, append, delete)
ก็จะส่ง document นั้นคืนมา
ซึ่งเราสามารถใช้ feature ของ SDO เข้าไปดูเฉพาะ
dataset ที่เกิดการเปลี่ยนแปลงได้
เช่นหาเฉพาะ list item ที่ถูก เพิ่ม หรือ ลบ ออกจาก document

ลองดูตัวอย่าง test case ของ SDO
เริ่มด้วยการสร้าง DataObject
(เห็นมันเป็น object อย่างนี้ แต่เวลาที่มันถูก serialize เพื่อรับ/ส่ง
ระหว่าง program แล้ว มันจะถูก serialize ในรูป xml file)

DataGraph dataGraph = SDOUtil.createDataGraph();
DataObject quote = dataGraph.createRootObject("http://www.example.com/simple", "Quote");

กรณีที่ต้องการบันทึกการเปลี่ยนแปลง
ก็จะใช้ method beginLogging กับ endLogging
เข้ามาช่วย
ChangeSummary changeSummary = dataGraph.getChangeSummary();
changeSummary.beginLogging();

quote.setString("companyName", "FlyByNightTechnology");
quote.setBigDecimal("price", new BigDecimal("1000.0"));
quote.setBigDecimal("open1", new BigDecimal("1000.0"));
...

DataObject child = quote.createDataObject("quotes");
child.setBigDecimal("price", new BigDecimal("2000.0"));

changeSummary.endLogging();


ถ้าอยากเห็นว่า IBM นำ SDO ไปประยุกต์ได้อย่างมีประสิทธิภาพอย่างไร
ต้องดู FacesClient Components Developer's Guide

ที่สำคัญคือ IBM เริ่มออก sdo api ที่อยู่บนภาษาอื่นออกมาแล้ว
มี SDO for php ที่สามารถใช้บน php ได้

Related link from Roti

Online Tutoring

Online tutoring pays off at home, abroad
online กันตัวต่อตัว
บ้านเราไม่รู้มีหรือยัง

Bikram Roy founded Chicago-based Studyloft.com in November. Already, its office in Bangalore provides tutoring to 5,400 US students. ''We're trying to leverage the accessibility of the Internet to bring students tutoring when they need it and where they need it," Roy said.


Both Growing Stars and Studyloft say that the majority of their tutors hold master's degrees or doctorates in their subjects;

Related link from Roti

Dabble DB

demo ของ Dabble DB
ได้รางวัล Best in Show Award
เป็น app ที่น่าสนใจทีเดียว
ทั้งในด้าน interface และ การนำไปใช้งาน

Related link from Roti

Tapestry in Ruby

สงสัยมานานว่า ทำไมไม่มีใคร implement
web framework แบบ component oriented ใน ruby บ้าง
วันนี้โชคดี หาเจอแล้ว
CGIKit
(ตั้งชื่อไม่สื่อเลย)
แต่โชคร้ายหน่อย ตรงที่คนเขียนเขาพึ่งจะเลิก Maintainence เอง
เหตุผลก็คือ เขาจะเปลี่ยนไปใช้ python

Related link from Roti

Friday, March 31, 2006

Hibernate Load, subclass mapping

กรณีที่เราออกแบบ class ของเราให้เป็น Inheritance mapping



ถ้าเราใช้คำสั่ง load กับ base class
Person person = session.load(Person.class, id);
Employee emp = (Employee) person; // ClassCastException here

เวลา run จะเกิด ClassCastException
โดย object ที่ return จาก method load จะอยู่ในรูป
proxy object ทำให้ cast ไม่ได้

ไปค้นหาใน Issue Tracking ของ Hibernate
พบ issue ที่ HHH-80
อธิบายว่า มันเป็นพฤติกรรมที่พึ่งมีใน Hibernate 3
กรณีที่ lazy="true" (default setting), คำสั่ง load จะได้ผลลัพท์เป็น proxy object

การแก้ไข เลือกวิิธีการใดการหนึ่งจากต่อไปนี้
  • เลือก config lazy="false"
  • ใช้คำสั่ง session.get แทน session.load

Related link from Roti

Thursday, March 30, 2006

Tapestry 4

หลังจากติดอกติดใจกับ Rails มาพักใหญ่
วันนี้ก็ได้ฤกษ์กลับไป Evaluate Tapestry4.0 อีกครั้ง
(ปัจจุบันที่บริษัทฯใช้ version 3 อยู่)

แรกสุด ก็ต้องดูที่ startup time ก่อน
เมื่อใช้กับ jetty, Tapestry จะใช้เวลา start ประมาณ 5 วินาที
อืมม์..ใช้ได้ จำได้ว่า ตอนที่เป็น beta แรกๆ มันนานกว่านี้เยอะ
ในเวลา 5 วินาทีนี้ เป็นของ Hivemind (ฐานรากของ Tapestry) ไปซะ 3 วินาที

เวลาชุดถัดไปที่ต้องวัด ก็คือเวลาในการ compile page,
tapestry ก็ใช้ technique เดียวกับ JSP
นั่นคือ เมื่อเรียกใช้ ก็จะมีการ compile
(สิ่งที่ tapestry ทำ ก็คือ การ generate class file ขึ้นมา
โดยใช้ javassist)
ผลก็คือ ใช้เวลา compile ไปเสีย 9 วินาที
อันนี้สินาน แต่ก็พอยอมรับได้ (เพราะมันทำเฉพาะครั้งแรกครั้งเดียว)

ความแตกต่างต่อไปที่เห็น ก็คือ
เดิม tapestry ต้องมี xml file ที่ใช้เป็น glue ระหว่าง
html file กับ class file
โดย xml file นี้จะระบุว่า html นี้จับคุ่กับ class file ไหน
มาใน Tapestry 4.0 นี้ มีการใช้ convention แบบ rails เข้ามาช่วย
กล่าวคือ สมมติว่า html ของเราชื่อ Home.html,
Tapestry จะมองหา class file ที่ชื่อ Home.class ใน default package
ถ้าเจอ ก็จะใช้ตัวนั้นเป็น BasePage
ซึ่งเราสามารถ config ระบุ package prefix ที่จะใช้ในการค้นหา class file ได้
<application>  
<meta key="org.apache.tapestry.page-class-packages" value="myproj.pages"/>
</application>

ส่วนกรณีที่ html page เราอยู่ใน subfolder
เวลาค้นหา BasePage, ชื่อของ subfoder ก็จะถูกแปลงเป็น packaege name ด้วย
ยกตัวอย่าง "admin/UserEdit,
การค้นหา class ก็จะค้นหา class ที่ชื่อ UserEdit
ใน package "package_prefix.admin"

ประเด็นที่ยังค้างคาใจ ใน tapestry4 ที่ต้องลองต่อ ก็คือ
การนำเอา annotation มาใช้เป็นกลไกในการ inject (dependency injection)
อยากรู้ว่า มัน work ไหม

Related link from Roti

Wednesday, March 29, 2006

หน้าตาประหลาด

ใน Signal vs Noise
เขาพูดถึง เรื่อง รูปถ่ายแมลง
มีอยู่รูปหนึ่งที่ผมติดใจมาก คือรูปนี้
Pseudocreobotra wahlbergii female

It also has a distinct “#9” spiral in yellow on top of its wing.

ถ้ามาเจอในบ้านเรา ต้องมีคนเอาเลข 9 ไปไปแทงหวยแน่เลย

ใครอยากทำความรู้จักให้มากขึ้นอ่านที่นี่
Link
(คนเขียน เขาเขียนได้ดีมากเลย)

Related link from Roti

Hibernate กับ ทักษิน

ช่วงนี้ บ้าน(ประเทศ)เรากำลังเรียนรู้หลายอย่าง
ในโลก opensource ของ java ก็เริ่มมีการปะทะชุดใหม่เกิดขึ้น

Gavin King (คนเขียน hibernate) ออกมาปะทะคารม
กรณีข้อกล่าวหา "Hibernate hates Spring"

ประเด็นของ Hibernate กับ Spring นี่
ผมไม่รู้เรื่องเลย แต่อ่านแล้ว มันมีประเด็นเรื่อง
  • ความขัดแย้งในเรื่อง JSR-220 spec
    ระหว่าง spring กับ hibernate
  • Gavin ไม่ชอบ HibernateTemplate(ใน spring) อย่างมาก (น่าสนใจว่าทำไม)

    We have already explained in other places that we dislike the noisy, inelegant HibernateTemplate stuff that Spring tries to promote. Everyone using use this stuff today should seriously reconsider.
    Until Spring redesigns their Hibernate integration stuff, we simply cannot recommend it to our users.

  • มีการ remove reference page ที่เกี่ยวกับ Spring ออกจาก Web site ของ hibernate


ส่วนประเด็นว่า แล้วมันไปเกี่ยวอะไรกับทักษิน
ไม่เกี่ยวหรอกครับ
แค่มีกลิ่นบางอย่างคล้ายๆกัน
(โปรดใช้วิจารณญาณ คนแต่ละคนรับรู้และตีความกลิ่นที่ได้รับไม่เหมือนกัน)
(กลิ่น เป็น คำอุปมา)
คือผมอ่านสิ่งที่ Gavin เขียน แล้วรู้สึกเหมือนฟังทักษินพูดอย่างไงไม่รู้
Scott ที่เป็นเจ้าของ blog ก็ยังตอบเลยว่า
I’m also surprised you think I attribute “evil” to Hibernate. The only real evil I associate with Hibernate is arrogance

(ลองเปลี่ยนคำว่า Hibernate เป็น ทักษิน ดูสิ)

Related link from Roti

Tuesday, March 28, 2006

Javascript Favelet

Bookmarklet ของดี
Javascript Object Tree Favelet
(พึ่งเคยได้ยินคำว่า Favelet นี่แหล่ะ
favelet == bookmarklet)

ช่วยให้เราใล่ javascript ได้ง่ายขึ้น
เพราะมันช่วยกรอง source code ที่เราไม่ต้องการดูออกไปได้

Related link from Roti

Implement Scheme with Haskell

พึ่งรู้เกร็ดว่า scheme48 (implementation หนึ่งของ scheme)
ได้เลข 48 มาจาก การที่มันถูกเขียนขึ้นภายใน 48 ชั่วโมง
ในปี 1996 โดยใช้ common lisp เขียน
(scheme syntax มัน minimalist มากเลย)

มาปีนี้ 2006
implementation ที่เป็น java ก็มีแล้ว (JScheme)
ถึงคราวของ haskell บ้าง
ใครที่ถึกพอ ขอแนะนำ
write yourself a scheme in 48 hours
(ใครที่อยากเห็น monads ตัวเป็นๆ ไม่ควรพลาด)

เมื่อคืนผมลองไปบ้างแล้ว
เจอแบบฝึกหัดชุดที่ 3.3 เข้าไป ก็ตัดสินใจสั่ง shutdown แล้วปิดไฟนอน

Related link from Roti

Monday, March 27, 2006

Copy/Paste from command line (Mac OS X)

pbcopy, pbpaste
เผื่อจะช่วยลดการใช้ mouse ได้อีกหน่อย

Related link from Roti