หน้าเว็บ

วันพุธที่ 4 ธันวาคม พ.ศ. 2556

manage transaction ใน service spring เอง

        ปกติเวลาเราเขียน service ของ spring ขึ้นมา  เราจะใช้ AOP (Aspect Oriented Programming) ช่วยในการ manage transaction ให้  เพียงแค่ใส่ annotation @Transactional  (org.springframework.transaction.annotation.Transactional) ไว้บน class หรือ method ที่ต้องการ  เมื่อ spring ทำ reflection มาเจอ มันก็จะเช็คว่า method ไหนต้องการให้มี transaction บ้าง มันก็จะ begin / commit transaction ให้  โดยผ่านทาง proxy method  แล้ว proxy method ก็ค่อยไปเรียก method จริงๆ อีกที  การทำแบบนี้ถือว่าสะดวกมาก  เพราะเราไม่ต้อง manage transaction เอง (spring จัดการให้แล้ว)  ซึ่งก็ช่วยลด code ที่ซ้ำซ้อนและไม่สำคัญทาง business logic ออกไปได้ในระดับหนึ่งครับ

        แต่การใช้ AOP มันมีเงื่อนไขอยู่ว่า service instance นั้นจะต้องถูกสร้างขึ้นมาจาก  spring เท่านั้น (เราจะ new instance เองไม่ได้) เพราะ spring จะต้องเอาไปครอบด้วย proxy method (ทำ AOP) อีกทีครับ 

        จากเงื่อนไขการใช้ AOP  ข้อนี้ทำให้มีบางเหตุการณ์ที่เราไม่สามารถใช้ transaction จาก AOP ได้  เช่น  การเรียกใช้งาน method นั้นๆ โดยตรง โดยไม่ผ่าน proxy method  ประมาณนี้

วันอังคารที่ 26 พฤศจิกายน พ.ศ. 2556

call store procedure inside SELECT statement : oracle

ต้องการวน loop ใน table เพื่อเรียกใช้งาน store procedure ที่เราเขียนไว้
begin
    for record in (select columnA, columnB, columnC from TEST_TABLE) loop
        -- 
        -- call store procedure in store package
        -- and pass variable (columnA, columnB and columnC) into store procedure
        --
        store_package.store_procedure(record.columnA, record.columnB, record.columnC);
    end loop;
end;
วันนี้ผมเจอกับเหตุการณ์นี้ครับ  คือพอดีผมเขียนคำสั่ง sql ขึ้นมา
แล้วปล่อยให้มันทำงานไปตามเงื่อนไขที่มีอยู่ใน table  ซึ่งมีอยู่เกือบๆ 1,000 เงื่อนไข
ผมก็คิดว่า  เดี๋ยวปล่อยให้มัน commit ในทีเดียวเลยแล้วกัน   ไม่น่าจะมีปัญหาอะไร
เพราะตอนที่ test นั้น ข้อมูลผมมีอยู่นิดเดียว  เลย run เสร็จภายในไม่กี่นาทีครับ

แต่พอเอา code ไป run จริงๆ มันก็ run ไม่ผ่านทุกที  เพราะข้อมูลจริงๆ ที่มีอยู่นั้น มีปริมาณมหาศาลมาก เมื่อต้องทำกับ 1,000 เงื่อนไขที่ผมใส่เข้าไป

ถ้าจะให้ run SQL จริงๆ run ทั้งวันก็ run ไม่เสร็จครับ  แต่กรณีนี้ตายตั้งแต่ 3 ชั่วโมงแรกแล้ว
นั่นเป็นเพราะ DBA (database administrator) เขาตั้งเวลา (timeout) เอาไว้ว่าถ้า run code แล้วยังไม่ commit ใน 3 ชม.  ให้ถือว่าคำสั่งนั้น fail ไปโดยปริยายครับ

โจทย์ที่ผมได้รับมาวันนี้คือ  ต้อง  run SQL ให้เสร็จ (commit) ภายใน 3 ชั่วโมง

ก็เลยต้องเอา code กลับมาแก้ใหม่  โดยย้าย code ที่ต้อง run ในแต่ละเงื่อนไขเข้าไปไว้ใน store procedure  เมื่อมันทำเงื่อนไขนึงเสร็จแล้ว  ก็ให้มัน commit ใน store procedure ทันทีครับ

แล้วเราจะส่งทุกเงื่อนไขเข้าไปใน store procedure ยังไง?

เลยเป็นที่มาของบทความนี้ครับ  โดยให้มันวน loop เพื่อส่งเงื่อนไขเข้าไปทีละเงื่อนไขนั่นเอง

วันจันทร์ที่ 25 พฤศจิกายน พ.ศ. 2556

AutoCloseInputStream : java

        บางครั้งเราต้องเจอกับสถานการณ์ที่เวลาเขียนโปรแกรมไปแล้ว  ไม่สามารถปิด InputStream ได้ในทันที  เพราะเมื่อเราทำการปิด  InputStream ก็เท่ากับว่า เราตั้งใจที่จะไม่ใช้งาน InputStream นั้นอีกต่อไป แล้วเราจะแก้ปัญหานี้ยังไง  ปิดก็ใช้งานไม่ได้  ไม่ปิดก็ไม่ได้ เดี๋ยวเกิด Resource Lock (ในกรณีที่เป็น FileInputStream) หรือ memory เต็มอีก (ในกรณีที่เป็น ByteArrayInputStream) สรุปแล้วคือต้องปิดครับ  แล้วเราจะปิดยังไงล่ะ?

ก็เลยเป็นที่มาของบทความวันนี้ครับ ว่าเราจะทำยังไงให้มันปิด InputStream เองโดยอัตโนมัติเมื่อมันทำงานเสร็จ

วิธีแก้ปัญหา โดยการสร้าง class AutoCloseInputStream ขึ้นมาจัดการกับปัญหานี้  โดยหน้าที่ของ class นี้คือจะห่อหุ้ม หรือ wrap InputStream อีกที  เมื่อมีการอ่านข้อมูลจาก stream เสร็จแล้ว (in.read คืนค่าเป็น -1) AutoCloseInputStream ก็จะทำการ close stream นั้นให้เองโดยอัตโนมัติ  แค่นี้ก็หมดปัญหาเรื่อง auto close ไปแล้วครับ

AutoCloseInputStream.java
package com.blogspot.na5cent.io.util;

import java.io.IOException;
import java.io.InputStream;

/**
 * for wrap InputStream then Automatic close
 */
public class AutoCloseInputStream extends InputStream {

    private final InputStream in;
    private boolean closed;

    public AutoCloseInputStream(InputStream in) {
        this.in = in;
    }

    private int autoClose(int x) throws IOException {
        if (x < 0) {
            close();
        }
        return x;
    }

    @Override
    public void close() throws IOException {
        if (!closed) {
            in.close();
            closed = true;
        }
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        return closed ? -1 : autoClose(in.read(b, off, len));
    }

    @Override
    public int read(byte[] b) throws IOException {
        return closed ? -1 : autoClose(in.read(b));
    }

    public int read() throws IOException {
        return closed ? -1 : autoClose(in.read());
    }
}
แต่ยังมีอีกปัญหาตามมาครับ ปัญหาใหญ่เลยแหล่ะ คำถามคือ  แล้วถ้ามันเกิด Exception ขึ้นมาก่อนที่ InputStream จะทำงานเสร็จล่ะ  มันก็ไม่ปิดสิ!!!

Apache common แก้ปัญหานี้ด้วยการสร้าง ProxyInputStream ขึ้นมาครอบอีกชั้นครับ แล้วส่ง InputStream เข้าไปปิดข้างในอีกที  ซึ่งถ้ามันเกิด Exception ในระหว่างการอ่านข้อมูล แล้วมีการ throw Exception ออกมา  มันก็รับประกันได้ว่า InputStream นั้นจะถูกปิดเสมอ  ไม่ว่าจะด้วยกรณีใดๆ ก็ตามครับ

AutoCloseImputStream Apache Common Document API : http://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/input/AutoCloseInputStream.html

วันอาทิตย์ที่ 24 พฤศจิกายน พ.ศ. 2556

การติดตั้ง apache hadoop 1.2.1 (multi-node cluster) บน ubuntu 12.04 server


คำศัพท์

Hadoop - เป็น Application (Framework) ที่ถูกเขียนขึ้นด้วยภาษา java ใช้สำหรับประมวลผลข้อมูลขนาดใหญ่ (ยักษ์) บน cluster (ใช้คอมพิวเตอร์หลายเครื่องในการประมวลผลร่วมกัน)  มีความสามารถในการ scale out คือสามารถเพิ่มจำนวนเครื่องคอมพิวเตอร์ที่ใช้ในการประมวลผลร่วมกันได้หลายๆ เครื่อง (จากร้อยเครื่องไปเป็นพันๆ เครื่อง) มีความสามารถในการตรวจสอบและแก้ปัญหาเครื่องคอมพิวเตอร์ที่ทำงานผิดพลาดได้เองโดยอัตโนมัติ มีการจัดเก็บข้อมูลด้วย Hadoop Distribute File System ซึ่งเป็นการจัดเก็บข้อมูลแบบกระจาย โดยอาศัยแนวคิดของ Google File System ซึ่งถูกคิดค้นโดย Google มีความสามารถในการประมวลผลด้วย MapReduce Programming ซึ่งเป็น Programming Model หนึ่งที่ถูกคิดค้นขึ้นโดย Google อีกเช่นเดียวกัน

MapReduce - อธิบายแบบสั้นๆ เป็นกระบวนการที่ใช้สำหรับการแบ่ง input data ให้มีขนาดเล็กลง แล้วส่งไปประมวลผลยัง node อื่นๆ ที่อยู่ใน cluster เมื่อประมวลเสร็จแล้วจึงนำผลลัพธ์ที่ได้กลับมาลดขนาด ได้เป็น output data แล้วค่อยส่ง output data นั้นกลับออกไปครับ

อธิบายแบบยาวขึ้นมานิดนึง  เป็นกระบวนการที่ใช้สำหรับการแบ่ง input data ให้มีขนาดเล็กลง แล้วส่งไปประมวลผลยัง node อื่นๆ ที่อยู่ใน cluster

  • ซึ่งแต่ละ node จะทำการแปลง input data ที่ถูกแบ่งแล้วให้อยู่ในรูปของ key-value (Map) ตาม Mapper class ที่ได้เขียนเอาไว้  (แล้วแต่เราจะ map ยังไง)
  • จากนั้นจึงทำการยุบรวม (ผสม)  key value ใน Combiner class (แล้วแต่เราจะยุบรวมยังไง)
  • เมื่อยุบรวม  key value ที่ Combiner เสร็จแล้ว ก็จะทำการจัดเรียง หรือ sort  key value ใหม่ (แล้วแต่เราจะ sort ยังไง)
  • แล้วนำผลลัพธ์ที่ได้กลับมาลดขนาด (Reduce) ตามคำสั่งที่ถูกเขียนไว้ใน Reducer class (แล้วแต่เราจะ reduce ยังไง)
  • จากนั้นจึงค่อยส่ง output data ที่ได้กลับออกไปครับ

วันจันทร์ที่ 18 พฤศจิกายน พ.ศ. 2556

การ disabled ipv6 linux ubuntu

1. เข้าไปแก้ไข file /etc/sysctl.conf  ในที่นี้ใช้ vi editor


2. เพิ่มคำสั่งดังต่อไปนี้ ต่อท้าย file (ซึ่งปกติแล้วจะไม่มี)  จากนั้นทำการบันทึก file