หน้าเว็บ

วันอังคารที่ 30 กรกฎาคม พ.ศ. 2562

ตัวอย่างการเขียน Java Spring-boot Reactive (WebFlux)


ผมได้ทำตัวอย่างการเขียน Java Spring-boot WebFlux ซึ่งเป็นการเขียน Spring-boot แบบ Non-Blocking I/O หรือ Asynchronous หากใครสนใจสามารถเข้าไปศึกษาได้ที่

https://github.com/jittagornp/spring-boot-webflux-example

วันพุธที่ 12 มิถุนายน พ.ศ. 2562

ถึงคนอ่าน Blog และผู้ติดตามทุกคนน่ะครับ

Blog นี้ผมไม่ได้เขียนมาซักระยะนึงแล้ว 
จริง ๆ ต้องเรียกว่านานมาก ๆ เลยแหล่ะ (เกือบ 4 ปีได้ ฮ่าๆๆๆ)

ตอนนี้ผมย้ายไปเขียนบน platform อื่น ๆ
หลัง ๆ มาก็มี เขียนบ้าง ไม่ได้เขียนบ้าง 
เพราะมีหน้าที่รับผิดชอบที่เยอะขึ้น เลยไม่ค่อยได้มีเวลาเขียน Blog ครับ
บวกกับตอนนี้มีความสนใจ เรื่องใดเรื่องนึงเป็นพิเศษ เลยไม่ได้มีเวลามาทำตรงนี้

ถ้าผู้อ่าน เพื่อน ๆ พี่ ๆ น้อง ๆ คนไหนยังอยากติดตามอยู่ สามารถติดตามได้ตาม link นี้ครับ

ขอบคุณครับ

วันจันทร์ที่ 25 พฤษภาคม พ.ศ. 2558

maven ทำ jar file ให้ double click run program ได้ : java

ในที่นี้ผมจะยกตัวอย่างด้วย Netbeans IDE น่ะครับ

1. สร้าง maven project เป็น Java Application


วันอาทิตย์ที่ 24 พฤษภาคม พ.ศ. 2558

ฝึก recursive ด้วยโจทย์ความน่าจะเป็น


       โจทย์นี้เป็นโจทย์ที่ผมใช้ฝึกวิธีคิด  การแก้ปัญหา  ซึ่งอาจมีคนคิด  หรือสร้าง tools สำเร็จรูปเอาไว้แล้ว  บางคนมาเห็นโพสต์นี้ อาจจะคิดว่าทำไมไม่ใช้เครื่องมือที่คนอื่นทำไว้แล้วล่ะ  จะมามัวเสียเวลาสร้างเองทำไม  ของคนอื่นอาจจะดีกว่าด้วยซ้ำ

        ครับ!!! ผมเคยได้ยินประโยคแบบนี้มานักต่อนักล่ะ  บางคนบอกว่าผมไม่รู้จักใช้เครื่องมือให้เกิดประโยชน์
        คุณกำลังเข้าใจผิดกับคำว่า  "การเลือกใช้เครื่องมือ"  กับ  "การฝึกทักษะการแก้ปัญหา"
ที่ผมเขียนเอง เพราะผมต้องการฝึก skill เพื่อให้เกิดความคล่องตัว เมื่อเราเจอโจทย์ปัญหาลักษณะนี้  เราจะแก้มันได้รึเปล่า ลองใช้ความคิดของเราดูสิ
        skill มันส่งต่อผ่านประสบการณ์กันไม่ได้  ต่อให้มีคนพยายามเล่าประสบการณ์ทั้งชีวิตของเขาให้คุณฟัง  คุณก็ทำแบบเขาไม่ได้ คุณต้องฝึก ฝึก ฝึก ลงมือทำด้วยตัวคุณเองครับ

ปัญหา

        โดยทั่วไป การหาความน่าจะเป็นหรือความเป็นไปได้ของสมาชิกทั้งหมดภายในเซต S ซึ่งมีสมาชิกจำนวน n ตัว
คุณจะต้องวนลูปทั้งหมด n รอบ และลึก n ชั้น ถึงจะได้ค่าทั้งหมดออกมา  เช่น

S = {'A', 'B', 'C'}
n = 3 ตัว
จำนวนความเป็นไปได้ทั้งหมดคือ 3 x 3 x 3 = 27 ค่า

การเขียนโปรแกรมแบบง่ายๆ จะได้
for (var i = 0; i < S.lenght; i++){
    for (var j = 0; j < S.lenght; j++){
        for (var k = 0; k < S.lenght; k++){
               print(S[i] + ',' + S[j] + ',' + S[k]);
        }
    }
}

A,A,A
A,A,B
A,A,C
A,B,A
A,B,B
...
...
...
C,B,C
C,C,A
C,C,B
C,C,C
แล้วถ้าเขาต้องการให้คุณเขียน code ที่รองรับ S ที่มี size ขนาดใดก็ได้ คุณจะเขียนยังไง?
แน่นอน loop ใช้ไม่ได้ล่ะ เพราะมัน fixed ตายตัว
แล้วอะไรที่เราเอามาใช้แทน loop ได้ แถมยังเป็นแบบ dynamic อีก

คำตอบคือ Recursive ครับ

วันเสาร์ที่ 18 เมษายน พ.ศ. 2558

angularjs enumeration : javascript

Enum Factory
var mapApp = ...

myApp.factory('Enumerate', function () {

    return function (list, fnc) {

        var Enumerate = function (ctx) {
            if (angular.isObject(ctx)) {
                angular.forEach(ctx, function (val, key) {
                    this[key] = val;
                }, this);
            } else if (angular.isString(ctx)) {
                this.name = ctx;
            } else {
                throw new Error('incorrect arguments.');
            }
        };

        Enumerate.values = [];

        Enumerate.valueOf = function (ctx) {
            var obj = null;
            angular.forEach(Enumerate.values, function (item) {
                if (item.name === ctx) {
                    obj = item;
                    return false;
                }
            });

            if (!obj) {
                obj = new Enumerate(ctx);
                Enumerate.values.push(obj);
            }

            return obj;
        }

        Enumerate.prototype.toString = function () {
            return this.name;
        };

        fnc && angular.forEach(fnc, function (val, key) {
            Enumerate.prototype[key] = val;
        });

        angular.forEach(list, function (item) {
            Enumerate[
                    angular.isObject(item)
                    ? item.name
                    : item
            ] = Enumerate.valueOf(item);
        });

        return Enumerate;
    };
});
Using
myApp..factory('StandardColumn', [
    'Enumerate',
    function (Enumerate) {

        var StandardColumn = function () {

        };

        /* define enum */
        StandardColumn.Format = Enumerate([
            {name: 'STRING', description: 'ตัวหนังสือ'},
            {name: 'NUMBER', description: 'ตัวเลข'},
            {name: 'STUDENT', description: 'นักเรียน'}
        ]);

        StandardColumn.Format.fromDescription = function (desc) {
            var obj = null;
            angular.forEach(StandardColumn.Format.values, function (item) {
                if (item.description === desc) {
                    obj = item;
                    return false;
                }
            })

            return obj;
        };

        StandardColumn.Operation = Enumerate([
            'SUM',
            'AVERAGE'
        ]);

        StandardColumn.prototype = {
            id: null,
            name: null,
            sequence: 1,
            format: StandardColumn.Format.STRING,
            operation: null,
            operateWith: null
        };

        return StandardColumn;
    }
]);

วันจันทร์ที่ 9 มีนาคม พ.ศ. 2558

พีระมิต (pyramid) : java

วันนี้นั่งแย่งโจทย์น้องฝึกงานเล่นครับ
package com.blogspot.na5cent.learning;

import java.util.Scanner;

/**
 * @author redcrow
 */
public class Pyramid {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int size = n * (n + 1) / 2;
        int bigSpace = (n - 1) / 2;

        for (int i = 1; i <= size; i++) {
            int numb = i % n;
            int space = bigSpace - i / n;

            boolean star = numb > space && numb <= (n - space);
            System.out.print(star ? "*" : " ");
            System.out.print(numb == 0 ? "\n" : "");
        }
    }
}

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

Spring security bypass authen : java


        บางครั้งเราต้องการให้ระบบ bypass authen (กระโดดข้ามการ authen) ด้วย username password
เราสามารถทำแบบนี้ได้ครับ  spring จะไม่ check username password เรา
เราแค่จับ ข้อมูล user (user details) ยัดเข้าไปใน spring context security เลย

ทำไมต้อง bypass

        เนื่องจากการ authen แบบเดิม  เราต้องรู้ username และ clean password เพื่อ authen เข้าใช้งาน
มันเกิดปัญหาว่า  ระบบที่ผมทำ  ผมไม่ได้เก็บ password ของผู้ใช้เป็น clean text ไว้  ผมเข้ารหัส password ไว้ตั้งแต่แรก (เพื่อความปลอดภัย) เพราะฉะนั้น  ผมจึงใช้วิธี authen แบบเดิมไม่ได้ (authen แบบเดิม  จะเอา password มา encrypt check กับ encrypt  password ที่มีอยู่ ว่า matches กันมั้ย)

        ปัญหาต่อมา  คือ  ผมทำระบบที่สามารถ login ด้วยบัญชีผู้ใช้ facebook  แน่นอนว่ามันไม่มี password  เพราะ facebook ใช้ token  แล้วผมจะ  authen เข้าสู่ระบบที่ผมทำยังไง?

        คิดอยู่สักพัก  ก็เกิดคำถามขึ้นมาในหัว  เราสามารถ bypass มันได้มั้ย ?
ก็เลยเป็นที่มาของบทความวันนี้ครับ

วันอังคารที่ 3 กุมภาพันธ์ พ.ศ. 2558

oracle sql order by multiple point string

ปัญหา

ถ้าเรา order by string แบบธรรมดาๆ  เราจะเจอปัญหาแบบนี้



การ order by string  10 จะมาก่อน 2  เพราะรหัส ASCII ของ 1 อยู่ก่อน 2

วิธีแก้

เปลี่ยนมา order by ด้วย sql function ที่ผมเขียนขึ้นมาใหม่  ได้เป็น

วันพฤหัสบดีที่ 29 มกราคม พ.ศ. 2558

Oracle SQL แยกหัวข้อ ออกจากข้อความ


code
select data.*,
       trim(replace(data.old_name, (numb), '')) new_name
from(
  select name old_name, 
         regexp_substr(name, '^[0-9ก-ฮ\.]+\)*\s') numb
  from MY_TABLE
) data

วันอังคารที่ 27 มกราคม พ.ศ. 2558

วันพุธที่ 21 มกราคม พ.ศ. 2558

แก้ปัญหา multiple values sql IN : oracle

คำสั่ง IN เป็นคำสั่งที่ใช้สำหรับตรวจสอบว่า  ค่าที่เลือกมานั้น  มีอยู่ใน IN หรือไม่  เช่น
...
...
SELECT code
FROM ...
WHERE code IN('AAA', 'BBB', 'CCC')
...
...
ซึงเราสามารถตรวจสอบได้เพียง ครั้งละ 1 ค่าเท่านั้น (single value)
ในที่นี้ field code สามารถเป็น AAA หรือ BBB หรือ CCC ได้เท่านั้น (ถึงจะ match กัน)
ไม่สามารถเป็น multiple values เช่น 'AAA, BBB' หรือ 'BBB, CCC' ได้ เพราะมันจะไม่ตรงกับตัวไหนใน IN เลย

 'AAA, BBB' ไม่ match กับ 'AAA'
 'AAA, BBB' ไม่ match กับ 'BBB'
 'AAA, BBB' ไม่ match กับ 'CCC'

แล้วถ้าเราต้องการให้มัน match กันละ  เราจะทำยังไง?
เพราะตามความเป็นจริงแล้ว  'AAA, BBB' มันควรจะ match กับทั้ง  'AAA' และ 'BBB'

มาดูแนวคิด วิธีแก้ของผมกันครับ

วันจันทร์ที่ 19 มกราคม พ.ศ. 2558

Split String to rows : Oracle SQL

บางครั้งเราอาจเจอโจทย์ที่ต้องแยก String ออกเป็นหลายๆ rows ครับ


SELECT trim(regexp_substr('String1,String2,String3', '[^,]+', 1, LEVEL)) str_2_tab
FROM dual
CONNECT BY LEVEL <= regexp_count('String1,String2,String3', ',')+1
thank you : http://stackoverflow.com/questions/14328621/oracle-10g-splitting-string-into-multiple-rows

วันศุกร์ที่ 9 มกราคม พ.ศ. 2558

แก้ปัญหา Oracle SQL LISTAGG not support

LISTAGG เป็น aggregate function ที่เอาไว้ join multiple row ให้เป้น single row  เช่น




ถ้าเรา run SQL นี้ไม่ได้ (เนื่องจาก version ไม่ support)
select gp, LISTAGG(name, ', ') WITHIN GROUP (ORDER BY name) name
from(
  select 'A' gp, 1 name from dual
  UNION
  select 'A' gp, 2 name from dual
  UNION
  select 'A' gp, 3 name from dual
  UNION
  select 'A' gp, 4 name from dual
   UNION
  select 'B' gp, 5 name from dual
  UNION
  select 'B' gp, 6 name from dual
  UNION
  select 'B' gp, 7 name from dual
  UNION
  select 'B' gp, 8 name from dual
)

group by gp
ลอง run แบบนี้ดูครับ
select gp, RTRIM (XMLAGG (XMLELEMENT (e, name || ', ')).EXTRACT ('//text()'), ', ') name
from(
  select 'A' gp, 1 name from dual
  UNION
  select 'A' gp, 2 name from dual
  UNION
  select 'A' gp, 3 name from dual
  UNION
  select 'A' gp, 4 name from dual
   UNION
  select 'B' gp, 5 name from dual
  UNION
  select 'B' gp, 6 name from dual
  UNION
  select 'B' gp, 7 name from dual
  UNION
  select 'B' gp, 8 name from dual
)

group by gp
ถ้าทำแล้วมันมี string ที่ซ้ำกันแล้วเราต้องการลบตัวที่ซ้ำ ใช้ ตัวนี้ช่วยครับ
...
... /* replace YOUR_STRING */
...
REGEXP_REPLACE(REGEXP_REPLACE(regexp_replace( YOUR_STRING ,'([^,]+)(, \1)+', '\1'),',{2,}',','),'^,|,$','')
...
...
Thank you : http://stackoverflow.com/questions/468990/how-can-i-combine-multiple-rows-into-a-comma-delimited-list-in-oracle

วันอังคารที่ 6 มกราคม พ.ศ. 2558

Excel Object Mapping

        บางครั้งเราอาจเจอโปรเจ็คที่ลูกค้าต้องการ  ให้ import ข้อมูลจาก excel เข้าไปในฐานข้อมูล
แต่มันไม่ได้ง่ายขนาดที่ว่า  เอา excel มายัดลงข้อมูลได้เลย  เนื่องจากรูปแบบข้อมูลที่แต่ละคนกำหนดมา  ไม่เหมือนกัน (วาง column ไม่ตรง  pattern ข้อมูลไม่ถูกต้อง)  และต้องการให้เรา validate ข้อมูลก่อนนำเข้า  จึงเป็นที่มาของการเขียนโปรแกรม เพื่ออ่านข้อมูลจาก excel file ไปเป็น java object

        ทำครั้งแรกครั้งที่ 2 ก็ไม่เท่าไหร่  แต่ทำซ้ำไปซ้ำมา  รู้สึกว่า  มันเริ่มไม่โอเคล่ะ  เขียน code เดิมๆ ไม่ได้ความรู้อะไรใหม่ขึ้นมาเลย  เริ่มจะไม่อยากยุ่งกับมันล่ะ  ก็เลยคิดว่าทำไมเราไม่เขียนเป็น library ไว้ใช้เลยล่ะ  โปรเจ็คหน้า  ก็เอาตัวนี้ไปใช้ได้เลย  ง่ายๆ  สะดวกดี

        ผมจึงตัดสินใจ  เขียน lib Excel Object Mapping สำหรับ Map Excel file ไปเป็น Java Object ให้อัตโนมัติครับ  โดยเราแค่ตั้งชื่อ excel แถวแรก  ให้ตรงตามชื่อ column ใน java class ที่เราต้องการให้ map ไป  แค่นี้มันก็ map ให้แล้วครับ

https://github.com/jittagornp/excel-object-mapping

อนาคต ผมอาจเพิ่มการ validate ข้อมูลที่ซับซ้อนขึ้นไปอีก  เพื่อให้ตอบโจทย์กับสิ่งที่เรากำลังทำอยู่ :)

วันเสาร์ที่ 22 พฤศจิกายน พ.ศ. 2557

แก้ปัญหา time zone ด้วยการ set JVM Time Zone : java

ปัญหา

       เนื่องจากผมทำการพัฒนา java web application และได้ทำการเช่า cloud server (VPS : Virtual Private Server) อยู่ที่ต่างประเทศ  ปัญหาที่เจอคือเรื่องของเวลา  ที่ไม่ตรงกัน  ระหว่าง client (browser) และ server  ทำให้การบันทึกข้อมูลลง database มีความผิดเพี้ยนไปจากความเป็นจริง

วิธีแก้

        ผมลอง search หาข้อมูลเพื่อแก้ไขปัญหาดังกล่าว  มีคนนึงแนะนำว่า  ลอง set time zone ให้ JVM ดู น่าจะแก้ได้  ผมเลยลองทำตาม  ปรากฎว่าได้จริงๆ ครับ  ซึ่ง set ค่าให้ JVM ดังนี้

วันศุกร์ที่ 21 พฤศจิกายน พ.ศ. 2557

BottomScrollFixer : javascript


        บางที element ของเรา อาจจะยาวมากๆ  จนล้นหน้าจอ (window) แล้ว element นั้น  ก็เกิด bottom overflow (overflow-x เป็น scroll หรือ auto) ด้วย

ปัญหา

        ปัญหาที่เจอก็คือ  เราต้องเลื่อน scroll ของ window ลงมาข้างล่างสุดของ element นั้นก่อน  เราถึงจะสามารถเลื่อน scroll X ของ element นั้นได้ (เพราะ element มันล้นจอ)

วิธีแก้

        ผมเลยทำการเขียน javascript ขึ้นมาเพื่อแก้ปัญหานี้  โดยให้มันทำการคำนวนและ fixed bottom scroll ให้โดยอัตโนมัติ  โดยที่เราไม่ต้องเลื่อน window scroll ลงไปข้างล่าง  มันจะ fixed ให้ทันทีที่เราเลื่อน scroll ไปถึง element นั้นตามขนาดที่เราได้ fixed ไว้  (withFixedHeight) โดยไม่จำเป็นต้องเลือนลงไปยังข้างล่างสุดของ element bottom scroll จะเลื่อนตามเราไปเรื่อยๆ  จนกว่าจะพ้น element นั้นๆ

วันพุธที่ 12 พฤศจิกายน พ.ศ. 2557

age computation oracle sql

code
select trunc(months_between(sysdate,dob)/12) year,
    trunc(mod(months_between(sysdate,dob),12)) month,
    trunc(sysdate-add_months(dob,trunc(months_between(sysdate,dob)/12)*12+trunc(mod(months_between(sysdate,dob),12)))) day
from (
    Select to_date('15122000','DDMMYYYY') dob 
    from dual
);
output
year      month      day
13        10             29

วันพุธที่ 22 ตุลาคม พ.ศ. 2557

เขียน Service Glassfish Server บน Linux Ubuntu

        server นี้ผมได้ทำการ set GLASSFISH_HOME ไว้ใน $PATH ของ file ~/.bashrc แล้วน่ะครับ  จึงทำให้สามารถเรียก asadmin ได้เลย  โดยไม่ต้องใช้ path เต็มครับ

1. ไปที่ /etc/init.d/ ด้วยคำสั่ง
$ cd /etc/init.d/
2. สร้าง file service glassfish ด้วยคำสั่ง
$ sudo vi glassfish
3. เขียนชุดคำสั่ง
#!/bin/sh
#

# define service function
start(){
    asadmin start-domain >/dev/null  
}

stop(){
    asadmin stop-domain >/dev/null  
}

restart(){
    asadmin restart-domain >/dev/null  
}

#detect service argument
case "$1" in
    start)
        start
    ;;
    stop)
        stop
    ;;
    restart)
        restart
    ;;
*)

echo $"Usage: $0 {start|stop|restart}"
exit 1
esac

exit 0
4. สั่งงาน
$ service glassfish start
หรือ
$ /etc/init.d/glassfish start