Friday, November 11, 2005

DWR

DWR - Direct Web Remoting
คือ framework ที่ช่วยให้เราสามารถ acesss
Java Object ที่อยู่บน Server ได้จาก javascript โดยตรง
ซึ่ง feature ที่น่าสนใจก็คือ มันสามารถใช้กับ spring bean ได้ด้วย

ลองดูตัวอย่าง
สมมติเรามี Bean ที่ทำหน้าที่ค้นหาชื่อลูกค้า

public class CustomerSvr {
.. // hibernate stuff

public List findCustomerByName(String name) {
...
}

}

public class CustomerDao {
private long id;
private String name;

.. // setter & getter here
}



ถ้าเราต้องการให้ DWR expose CustomerSvr
ก็ต้อง config ดังนี้
เริ่มจาก add DWR Servlet ก่อน

<servlet>
<servlet-name>dwr-invoker</servlet-name>
<display-name>DWR Servlet</display-name>
<servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>

<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>

จากนั้นก็ต้อง config DWR ว่ามี Bean อะไรที่ expose function
ให้ javascript เห็นได้บ้าง

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
"http://www.getahead.ltd.uk/dwr/dwr10.dtd">

<dwr>
<allow>
<convert
converter="bean"
match="service.*"/>

<create
creator="spring"
javascript="customerSvr">
<param name="beanName" value="customerSvr"/>
</create>
</allow>
</dwr>

โดยเราสามารถกำหนด
  • method อะไรที่ต้องการให้เห็นบ้าง
  • วิธีการ convert ผลลัพท์ที่ได้
    เท่าที่เห็นคร่าวๆ ก็มี
    • Bean converter
    • Hibernate converter
      ต่างกับ bean converter ตรงที่ทำ lazy loaded properties ได้
    • JDom Converter


ให้สังเกตุว่าเราใช้ creator="spring"
เป็นการบอกว่าให้ไป lookup หา bean จาก spring context

ถ้า config ไว้ถูกต้อง เราก็จะสามารถทดสอบการทำงานเบื้องต้นได้โดย
ใช้ browser เปิด url http://server:port/dwr/
DWR servlet จะแสดงหน้าจอที่ใช้ในการทดสอบการทำงานของ Bean เรา



ที่นี้ลองดูที่ฝั่ง javascript บ้าง
ถ้าต้องการที่จะ call CustomerSvr
ที่ฝั่ง javascript จะเขียนดังนี้

เริ่มจากให้ include generated script ก่อน

<script type='text/javascript' src='/dwr/interface/customerSvr.js'></script>
<script type='text/javascript' src='/dwr/engine.js'></script>
<script type='text/javascript' src='/dwr/util.js'></script>


ส่วน script ที่เรียกใช้งาน หน้าตาดังนี้

<script>

function findCustomerName(name) {
customerSvr.findByName(name, displayCustomerName);
}

function displayCustomerName(customers) {
var x = $("custName");

var text = 'Customers: <br><ul>';
for(i = 0; i < customers.length; i++) {
text += '<li>';
text += customers[i].name;

text += ' (';
text += customers[i].id;
text += ')';
text += '</li>';
}
x.innerHTML = text;
}

</script>

มีที่น่าสังเกตุคือ เราเรียกใช้ bean โดยอ้างถึงชื่อที่เรา config ใน dwr.xml ได้เลย
ในที่นี้ก็คือประโยค customerSvr.findByName
แต่ต้องเพิ่ม callback function เข้าไปใน parameters ที่ส่งให้ findByName ด้วย

ส่วนใน callback function จะเห็นว่า
เราใช้ $('xxx') ซึ่งเป็น util function
ที่เรา include เข้ามาจาก DWRUtil.js
โดย function นี้ใช้ในการ access DHTML Element

สุดท้ายก็คือ html element ที่เรียกใช้งาน

<body>
<input type="text" onBlur="findCustomerName(this.value)"/><br/>
<span id="custName">Name<span>
</span>
</body>


ข้อดีของ DWR
จะเห็นว่า DWR ซ่อนรายละเอียดต่างๆไว้เบื้องหลังหมด
เราแค่รู้ชื่อ service กับชื่อ method ตลอดจน return structure เท่านั้นเอง

ข้อเสียเท่าที่เห็น ก็มี
เนื่องจาก object ที่ส่งกลับ ต้องมีการทำ serialize กับ deSerialize
ดังนั้น object ที่ DWR support สามารถใช้ได้ก็จะมีจำกัด
ส่งผลให้บางครั้ง เราต้องเพิ่ม method ที่ให้ผลลัพท์แบบที่ DWR สามารถ convert ได้
ทำให้มี method ที่ redundant ใน business layer เพิ่มขึ้นจำนวนหนึ่ง

อ่านเพิ่มเติมได้ที่นี่
Ajax with Direct Web Remoting

Related link from Roti

No comments: