Wednesday, February 20, 2008

GWT กับ Spring

ผม search หาวิธี map GWT เข้ากับ SpringFramework มาพักใหญ่แล้ว
ส่วนใหญ่ที่เห็นก็จะเป็นการเขียน DispatcherServlet ของตัวเองขึ้นมา
เช่น GWT-SL
วิธีการของ GWT-SL จะเป็นดังนี้
  • config servlet ใน web.xml
      <servlet>
    <servlet-name>rpc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
    <servlet-name>rpc</servlet-name>
    <url-pattern>*.rpc</url-pattern>
    </servlet-mapping>

  • config spring context โดยใช้ GWTHandler เข้ามาเป็นตัว wrapper
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

    <beans>
    <bean id="urlMapping" class="org.gwtwidgets.server.spring.GWTHandler">
    <property name="mappings">
    <map>
    <entry key="/wcfb110_jobService.rpc" value-ref="jobService"/>
    </map>
    </property>
    </bean>

    <bean id="jobService" class="wcf.web.fin.gwt.wcfb110.server.JobServiceImpl"/>
    </beans>
    </pre>


ดูก็ง่ายดีแล้ว แต่มาวันนี้เจอตัวอย่าง source code ของ Interface21(เจ้าพ่อ spring) ซึ่ง config spring กับ GWT
(โปรดระวัง เห็นนามสกุลเป็น .zip แต่จริงๆแล้วมันเป็นพวก .tgz)
เห็นแล้วต้องร้อง Wow, ทำไมมัน simple อย่างนี้

เขาใช้วิธีนี้
เริ่มด้วย web.xml ที่ทำเหมือนกันกับข้างบน
แต่ ตัว spring context เขาเปลี่ยนเป็นแบบนี้
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd"
>

<context:component-scan base-package="gwt.server" />

</beans>

แล้วตัว GWT Servlet ของเราก็ใส่ annotation เข้าไปแบบนี้
@Controller
public class NoteServiceImpl extends RemoteServiceServlet implements NoteService, ServletConfigAware {

public void setServletConfig(ServletConfig servletConfig) {
try {
init(servletConfig);
} catch (ServletException e) {
throw new IllegalStateException("Cannot initialise Controller.", e);
}
}

@RequestMapping("/gwt.Example/NoteService.rpc")
public void doRpc(HttpServletRequest request, HttpServletResponse response)
throws Exception {
doPost(request, response);
}

public Note loadNote(String name) {
return new Note(name, "This Note named " + name + " was constructed on the server");
}
}

ง่ายขึ้นเยอะ ลด dependency ของพวก wrapper ไปได้
แต่ข่าวร้ายสำหรับผมก็คือ annotation พวกนี้เป็น feature ของ spring 2.5.x
โชคร้ายที่โปรเจคผมยังใช้ spring 2.0.x อยู่เลย

Related link from Roti