Archive for June, 2009

แกะ Spring JavaConfig ภาค 1

June 18th, 2009

เคยเขียนเรื่อง Spring JavaConfig ไปแล้วหนึ่งตอนแต่ไม่ได้ลงมือทำเพราะมันไปบ้า Spring Dynamic Module
แต่อ่านไปอ่านมาตัวอย่างมันมี bug เลยขี้เกียจอ่านต่อ เลยไปรื้อ Spring JavaConfig ออกมาใหม่
พบว่าเอกสารเขียนก้าวหน้าไปได้เยอะมากและที่สำคัญ มีตัวอย่างแล้วนั่นคือ PetClinic นั่นเองอย่ารอช้า checkout ออกมาดู
“อ่านไม่รู้เรื่อง” สิ่งแรกที่แว๊บมาในหัว เนื่องจากไม่รู้จะเริ่มจากตรงไหนดี เนื่องจากสมัยก่อนจะไปเปิดดู Application-Context.xml ก่อน
แต่ตอนนี้มันไม่มีแล้ว
แกะอยู่หลายนาทีก็พอคลำได้ แต่พบว่ามันใช้ Annotation แบบพิการไม่สุดตามวิธี Spring คือไม่ยอมใช้ Hibernate Annotation เพราะ
ไม่อยากทำให้ Domain class แปดเปื้อน (แต่ที่อื่นนี่ เละไปด้วย Annotation และ abstract method) นี่ถือเป็นโอกาสที่ดีของผมครับ ที่จะรื้อ
มันออกมาเป็นชิ้นๆ แล้วประกอบเข้าไปใหม่(Japanese Way) เพราะถ้าเราอยากเข้าใจการทำงานของมันก็ต้องลองประกอบเองด้วยมือ
*** สามารถ download sourcecode มาสั่ง unit test ได้ครับที่ http://code.google.com/p/petclinic-java-config/
เรามาเริ่มเรียน Spring JavaConfig กันเลยดีกว่าครับด้วยการ ถอดประกอบตัวอย่าง
ข้อแรกผมต้องหาให้เจอก่อนว่า กระบวนการโหลด Application Context ของมันเริ่มจากตรงไหน ดังนั้นที่ที่ดีที่สุดที่จะไปดูคือ Unit Test (ประโยชน์ข้อแรก
ของการเขียน Unit Test) พบว่ามี Annotation อยู่หนึ่งตัวที่ทำให้ผมพอเดาออก ผมเลยเอามาเขียนใหม่เป็นที่ของผม

@ContextConfiguration(locations = "org.spring66.petclinic.config.JpaPetclinicApplicationConfig", loader = JavaConfigContextLoader.class)

Annotation ตัวนี้จะบอกว่าที่เก็บ Config พื้นฐานของเราทั้งหมดอยู่ที่คลาส “org.spring66.petclinic.config.JpaPetclinicApplicationConfig” และกราจะใช้
JavaConfigContextLoader เป็นตัวโหลด Context ขึ้นมาให้เรา ดังนั้นเราก็ต้องไล่ต่อไปว่าเจ้า JpaPetClinicApplicationConfig ต้องทำอะไรบ้าง

package org.spring66.petclinic.config;
import ... ประมาณสามล้าน อัน

@Configuration
@Import({PetclinicApplicationConfig.class, ExternalDataSourceConfig.class})
@PropertiesValueSource(locations = "classpath:db/jdbc.properties")
public abstract class JpaPetclinicApplicationConfig extends ConfigurationSupport {
    // Each of the following @ExternalValues are provided by db/jdbc.properties
    abstract @ExternalValue("jpa.showSql") boolean showJpaSql();
    abstract @ExternalValue("jpa.database") String databaseType();
    abstract @ExternalValue("hibernate.show_sql") boolean showSql();
    abstract @ExternalValue("hibernate.hbm2ddl.auto") String hbm2ddlAuto();
    abstract @ExternalValue("hibernate.generate_statistics") boolean generateStatistics();
    abstract @ExternalValue("hibernate.dialect") String databasePlatform();
    /** Provided by {@link EmbeddedDataSourceConfig#dataSource()} */
    abstract @ExternalBean DataSource dataSource();

    public @Bean Clinic clinic() {
        return new EntityManagerClinic();
    }

    public @Bean EntityManagerFactory entityManagerFactory() {
        Properties jpaProperties = new Properties();
        jpaProperties.put("hibernate.dialect", databasePlatform());
        jpaProperties.put("hibernate.show_sql", showSql());
        jpaProperties.put("hibernate.generate_statistics", generateStatistics());
        jpaProperties.put("hibernate.hbm2ddl.auto", hbm2ddlAuto());

        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setJpaProperties(jpaProperties);
        em.setDataSource(dataSource());
        em.setJpaVendorAdapter(jpaVendorAdapter());
        em.setLoadTimeWeaver(loadTimeWeaver());
        return this.getObject(em, EntityManagerFactory.class);
    }

    public @Bean JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setShowSql(showJpaSql());
        adapter.setDatabasePlatform(databasePlatform());
        return adapter;
    }

    public @Bean LoadTimeWeaver loadTimeWeaver() {
        return new InstrumentationLoadTimeWeaver();
    }

    public @Bean PlatformTransactionManager transactionManager() {
        JpaTransactionManager txManager = new JpaTransactionManager();
        txManager.setEntityManagerFactory(entityManagerFactory());
        return txManager;
    }
}

อ้วกเป็นเลือดแต่เราคือโปรแกรมเมอร์มืออาชีพเราต้องอย่าเพิ่งเข้าใจมันหมด เอาที่คุ้นๆก่อน แล้วตรงไหนล่ะ? เริ่มตั้งแต่ตัวแรกเลยละกัน

@Configuration
บอกให้โลกรู้ว่าคลาสนี้จะถูกใช้สำหรับ JavaConfig เพื่อกำหนดและประกาสรายละเอียดเกี่ยวกับ bean ที่เราต้องใช้
@Import
ในกรณีที่เรามี @Configuration มากกว่าหนึ่งคลาสและต้องการใช้งานบีนข้ามไปมาเราสามารถทำได้ด้วยการใช้ @Import ตัวอย่างนี้คือการ
เรียกใช้ bean ชื่อ dataSource() ซึ่งไม่มีอยู่ใน JpaPetclinicApplicationConfig แต่จะถูกประกาสไว้ที่ ExternalDataSourceConfig ครับ
ซึ่งเราก็ Import เข้ามาเรียบร้อยแล้วครับ วิธี Import นี่ดูขัดๆกับแนวคิดแบบเก่าพิกล แต่ก็ช่วยได้เยอะเรื่อง NameSpace ครับ
@PropertiesValueSource
ใช้ในกรณีที่เราต้องการโหลดข้อมูลบางอย่างมาจาก properties ไฟล์เพราะเราไม่ต้องการให้ข้อมูลเหล่านั้นฝังไว้ในคลาสที่นี้เราจะไปอ่านที่
(locations = “classpath:db/jdbc.properties”)
@ExternalValue
จะบอกว่าเราจะเอาค่าจาก properties ตัวไหนมาใส่ให้ property(เป็น abstract method) เราครับ

ต่อไปตัวสำคัญ @Bean แน่นอนเดาไม่ออกสมควรตายมันคือการประกาส bean แบบใหม่แต่ให้ดูการสร้าง EntityManager ของ JPA ก่อนนะครับว่าเขียนแบบใหม่
กับแบบเก่าทำอย่างไร

 <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="dataSource" ref="dataSource"/>
  <property name="loadTimeWeaver">
    <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
  </property>
 </bean>

แบบใหม่จะเขียนแบบนี้ครับพี่น้อง ผมไม่รู้ว่ามันดูดีกว่าเดิมหรือดูน่ากลัวกว่าเดิมอันนี้แล้วแต่คนนะครับ

    public @Bean EntityManagerFactory entityManagerFactory() {
	...
	...
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setJpaProperties(jpaProperties);
        em.setDataSource(dataSource());
        em.setJpaVendorAdapter(jpaVendorAdapter());
        em.setLoadTimeWeaver(loadTimeWeaver());
        return this.getObject(em, EntityManagerFactory.class);
    }

เริ่มชินกันแล้วใช่ไหมครับ ตอนต่อไปจะเป็นเรื่องของการ วนออกไปดูฝั่ง EntityManager จริงๆว่ามี Annoation แปลกอะไรให้เราดูกันบ้างครับ

เริ่มต้นกับ Spring Roo

June 17th, 2009

สำหรับคนที่ใช้ spring framework เคยรู้สึกเหนื่อยใจมั้ย ตอนที่จะขึ้น project ซักอันนึงต้อง config มากมายมหาศาลกว่า จะเริ่มลงมือเขียนโปรแกรมได้ โดยส่วนตัวผมวิธีที่ลัดขั้นตอนที่สุดก็คือ copy จากโปรเจ็คเดิมมาแล้วก็มาแก้ config ให้เข้ากับโปรเจ็คใหม่ แต่ก็นั่นแหละ ถ้าแก้ไม่ดีมันก็เหมือนวางยาตัวเองเข้าไปอีก แต่ตอนนี้เริ่มมีแสงสว่างปลายอุโมงค์ให้เห็นเพราะ spring source ได้ออก tool ตัวใหม่ชื่อ Roo มาให้เราๆท่านๆได้ใช้

แล้ว Roo คือ?

“Interactive, lightweight, user customizable tooling, that enables rapid delivery of high performance enterprise Java applications”

ทั้งหมดทั้งปวงนี้คือคำจำกัดความที่ Rod johnson พูดถึง Spring Rooในงาน springOne ซึ่งก็ถือได้ว่า เป็นการเปิดตัวอย่างเป็นทางการของ Roo หลังจาก ปล่อยให้ download มาลองใช้อยู่พักใหญ่ » Read more: เริ่มต้นกับ Spring Roo

สงครามระหว่าง SpringSource กับ Red Hat เริ่มเปลี่ยนแปลง

June 10th, 2009

เป็นที่รู้กันมานานหลายปีแล้วว่า hibernate กับ spring ไม่ค่อยจะกินเส้นกันมานาน จนกระทั่งความไม่ลงรอยกันลามไปถึงขั้นแตกหักเมื่อ มีการด่าทอกันด้วยคำพูดที่รุนแรงในเวบบอร์ดของทั้งสองฝั่ง สุดท้ายทุกๆ thread ที่เกี่ยวกับ spring บนเวบบอร์ด hibernate ถูกลบทิ้ง ==”

นั่นคือจุดเริ่มต้นหลังจากนั้น hibernate เข้าไปอยู่ภายใต้ร่มเงาของ Jboss และแน่นอน hibernate ย่อมได้เปรียบและหลังจากนั้นไม่นานทางทีมพัฒนา hibernate ได้ออก full stack web framework ชื่อ seam ออกมา(ไม่ใช่อื่นใด เพื่อลบ spring ออกจากแผนที่โลก)แต่สงครามไม่จบง่ายๆเนื่องจาก seam ออกตัวช้าไปนิดถึงแม้ว่าจะมีไอเดียที่ดีกว่าในบางมุม แต่ spring ล้ำหน้าไปไกลกว่านั้นแล้ว

ล่าสุด Spring ปล่อย Product ตัวใหม่ออกมาอีกสมตัวคือ Spring Tools, Spring TM Server และ Spring Monitoring(Hyperic HQ) ทำให้แนวรบของสองบริษัทขยายออกเต็มรูปแบบเนื่องจาก TM Server คือ Product ในแนวเดียวกับเรือธงของ JBoss ก็คือ JBoss Application Server นั่นเอง แต่แนวโน้มการตอบรับ TM Server ดูจะแรงมากเนื่องจากตัวมันถูกสร้างอยู่บน Servlet Container ยอดนิยมอย่าง Tomcat นั่นเอง

สิ่งนี้ทำให้ RedHat ต้องปรับกลยุทธ์ทางการตลาดใหม่ด้วยการทำการ RePackage Product ใหม่ออกมาในชื่อ JBoss Open Choice แต่ถ้าวิเคราะห์กันให้ถ่องแท้ ตอนนี้ SpringSource ได้รับการยอมรับแล้วว่าเป็นผู้นำตลาด Java EE(ทางเลือก) อย่างแท้จริงโดยสามารถดูได้จากภาพด้านล่าง

เพื่อให้ได้อารมณ์มากขึ้นต้องอ่าน quote นี้ครับจาก Rod Johnson

We’re pleased to see Red Hat follow our lead, and we encourage JBoss customers and prospective customers to look at what they are really building their stacks on and compare the offerings from Red Hat and SpringSource on merit. Clearly Red Hat is deeply worried about SpringSource; it’s time for JBoss customers to come and learn why.

Nuxeo Enterprise content management ภาคเตรียม intro

June 9th, 2009

ไม่แน่ใจว่าเรื่องนี้จะ มาอยู่ถูกที่ หรือเปล่าแต่ก็ เอาหล่ะในเมื่อ เป็นชาว spring66 ก็ไม่รูจะลงไว้ที่ไหนหล่ะครับ

ว่าด้วยเรื่องของ Enterprise content management (ECM) กันก่อนเลย
ก็ไม่รู้จะยังไง แปลตรงตัวกันเลยแล้วกัน มันก็คือ ระบบในการบริหารจัดการ content นั่นเอง โดยเมื่อพูดถึง ECM มันก็มี

function การทำงานหลักๆ ดังนี้

- document management (DM)
- collaboration (or collaborative software, groupware),
- web content management (WCM) (including web portals),
- records management (RM) (archive and filing management systems on long-term storage media), and
- workflow/business process management (BPM).

จริงแล้วตัวมันมีฟังชั่นการทำงานทั้งหมดที่ ECM ควรจะมีและเพิ่มอะไรต่างๆ นานาเข้าไปอีกมากมาย ถ้าจะพูดถึงการนำมาใช้
มันก็สามารถรองรับระบบต่างๆ ได้หลายแนวเช่น เอามาทำระบบ Knowledge Management (KM), Document Management (DM)
และตัวที่ผมเอามันใช้ตอนนี้คือ Configulation Management tool ครับโดย cover ตาม CMMi
อย่างที่บอกว่ามันก็เป็นแค่หลักๆ ส่วนย่อยๆ จะมีอะไรอีกบ้างมันก็คือลูกเล่นที่แต่ละ product จะแต่งแต้มสีสันเข้าไป
ครั้งนี้ขอยกสักตัวนะครับ มันคือ
Nuxeo DM ตัวของ Nuxeo เองตอนนี้ลาสุดเวอชั่น 5.2 ครับ โดยคร่าวๆมันเป็น Opensource ECM ถ้าเราลองลงลึกไปอีกมันพัฒนาบน Java Platform ครับ

ถ้าลึกลงไปอีกนิ๊ส มันใช้ OSGi โดยใช้ Equinox ครับ เอาหล่ะตบเข้าเรื่อง OSGi เอาหล่ะอยู่ spring66 ได้อย่างสบายใจ
ถ้าใครอดใจไม่ไหวลองเข้าไปอ่านเพิ่มเติมได้ครับ หรือลองเอาลงมาเล่นดูได้โดย default จะรวม JBOSS มาให้เลยครับ
ที่นี่ครับ
Nuxeo ECM
ภาคต่อไป ค่อยว่ากันในรายละเอียดเริ่มกันที่ แนวคิดของตัว ECM ก่อนนะครับ