หน้าเว็บ

แสดงบทความที่มีป้ายกำกับ java แสดงบทความทั้งหมด
แสดงบทความที่มีป้ายกำกับ java แสดงบทความทั้งหมด

วันจันทร์ที่ 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 ครับ

วันจันทร์ที่ 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 มันได้มั้ย ?
ก็เลยเป็นที่มาของบทความวันนี้ครับ

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

วันอังคารที่ 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 ดังนี้

วันอังคารที่ 23 กันยายน พ.ศ. 2557

wrap http servlet response ด้วย HttpServletResponseWrapper

ปัญหา

        อันนี้เป็นปัญหาที่ผมเจอระหว่างการพัฒนาโปรเจ็คที่ใช้ spring mvc ครับ ซึ่ง view ผมเป็น jsp
ความต้องการของผมคือ ผมต้องการ parse jsp ไปเป็น html เอง (manual parse) เพราะผมต้องการ return ผลลัพธ์กลับไปเป็น json ซึ่งห่อหุ้ม html (jsp) อีกที  ก็เลยได้ลองหาข้อมูลใน google อยู่สักพัก  ปรากฏว่ามันไม่น่าจะทำได้

ทุกปัญหาย่อมมีทางออก!
         มันก็มีทางออกอยู่ว่า  ถ้าอยาก parse template เอง  ก็ต้องเปลี่ยนไปเขียน code ที่เป็นพวก template engine แทน jsp เช่น themeleaf, freemarker หรือ velocity อันนี้ได้ชัวร์ 100%  แต่ผมไม่อยากเปลี่ยนนี่สิ  เพราะผมต้องการ feature บางอย่างของ jsp ที่มีมากกว่า template engine พวกนี้
        จนในที่สุด  ผมก็พบทางออก  ลืมไปเลย  ว่ามันมีวิธีนี้อยู่ manual parse ไม่ได้ไม่เป็นไร  งั้นห่อหุ่ม (wrap) ผลลัพธ์แทนแล้วกัน  ซึ่งเป็นที่มาของบทความนี้ครับ

วิธีการ


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

Http status code/message ด้วย http client apache commons : java

maven project

add dependencies (pom.xml)
<dependency>
    <groupId>commons-httpclient</groupId>
    <artifactId>commons-httpclient</artifactId>
    <version>3.1</version>
    <type>jar</type>
</dependency>
เขียน unit test (pass)
package com.pamarin.core.util;

import org.apache.commons.httpclient.HttpStatus;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;

/**
 * @author redcrow
 */
public class ApacheCommonsHttpStatusT {
    
    @Test
    public void test(){
        int ok = HttpStatus.SC_OK;
        assertEquals(200, ok);
        assertEquals("OK", HttpStatus.getStatusText(ok));
    }
}
อธิบาย http status แต่ละตัวครับ http://webdesign.about.com/od/http/a/http_status_codes.htm

วันพุธที่ 17 กันยายน พ.ศ. 2557

การสร้าง maven plugin ขึ้นมาใช้งานเอง

        มาเขียน maven plugin ใช้งานเองกันดีกว่าครับ  เราใช้ของชาวบ้านมาเยอะล่ะ ^^

ปัญหา

        เนื่องจากผมต้องการเครื่องมือที่เอาไว้เข้ารหัส  ลดขนาด resource file หรือการทำ obfuscate ผมเลยค้นหาข้อมูลใน google อยู่สักพักนึง  แล้วก็ได้ลองใช้ maven plugin ที่คนอื่นๆ เขียนขึนมา  ปรากฎว่า  มันยังไม่ค่อยตรงตามความต้องการของผมสักเท่าไหร่  (ผมลองใช้ไปประมาณ 5 plugins)  ไม่ได้ดั่งใจสักอัน เลยตัดสินใจว่าถ้างั้น  เขียน plugin ขึ้นมาใช้งานเองดีกว่า  ก็เลยเป็นที่มาของบทความนี้ครับ  


วิธีการ
สร้าง plugin

1. สร้าง maven project เลือกเป็น Java Application
2. กำหนด artifactId ให้มีรูปแบบเป็น <yourplugin>-maven-plugin เช่น uglifyjs-maven-plugin
3. ที่ pom.xml เปลี่ยน <packaging> จาก jar ไปเป็น maven-plugin
4. เพิ่ม dependencies

วันจันทร์ที่ 8 กันยายน พ.ศ. 2557

Execute class ตอน build maven project : java

1. สร้าง maven project
2. เขียน java class ที่ต้องการให้ execute ขึ้นมา (ผ่าน method main (String[] args) เท่านั้น)


3. ที่ pom.xml ให้เพิ่ม plugins org.codehaus.mojo เข้าไป
  • ตรง <phase> ให้กำหนดเป็น compile (คือ ทำงานตอน compile)
  • <mainClass> ให้ชี้ไปที่ class ที่ต้องการให้ execute
<project>
    ...
    ...
    ...
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.3.2</version>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>java</goal>
                        </goals>
                        <configuration>
                            <mainClass>com.pamarin.learning.executor.CompileExecutor</mainClass>
                            <arguments>
                                <argument>na5cent.blogspot.com</argument>
                            </arguments>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    ...
    ...
    ...
</project>
4. clean and build


วันศุกร์ที่ 5 กันยายน พ.ศ. 2557

Spring Security Manual Login : java

ต่อยอดจากบทความ การทำ Login ด้วย Spring security

        เนื่องจากบางครั้ง  เราต้องการที่จะทำการ login ด้วยตนเอง  โดยไม่ผ่าน service login ของ spring security เช่น  กรณีที่ user ทำการ register ระบบ  แล้วเราต้องการให้ authen ต่อจากการ register นั้นๆ เลย 

มีแต่ code น่ะครับ (สำหรับคนที่คล่อง spring security อยู่แล้ว)
package com.blogspot.na5cent.security;

import com.blogspot.na5cent.util.SpringUtils;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

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

    /**
     * @param username
     * @param password
     * @param request
     */
    public static void login(String username, String password, HttpServletRequest request)  throws UsernameNotFoundException {
        ServletContext servletContext = request.getServletContext();
        SecurityContext securityContext = SecurityContextHolder.getContext();
        AuthenticationManager manager = (AuthenticationManager) SpringUtils.getBean(servletContext, "authenManager");
        UserDetailsService detailsService = SpringUtils.getBean(
                servletContext,
                UserDetailsService.class
        );
        //check authen from user details service
        UserDetails userDetails = detailsService.loadUserByUsername(username);
        Authentication authentication = manager.authenticate(new UsernamePasswordAuthenticationToken(
                userDetails,
                password
        ));
        //keep authentication to security context 
        securityContext.setAuthentication(authentication);
    }
}
code SpringUtils ก็ประมาณนี้ครับ เพียงแต่อันนี้ใช่ร่วมกับ jsf  http://na5cent.blogspot.com/2012/12/jsf-get-service-by-webapplicationcontex.html

หรือจะเขียนอีกแบบ ก็ประมาณนี้ครับ

วันพฤหัสบดีที่ 14 สิงหาคม พ.ศ. 2557

Google OAuth ใช้งาน Google+ : java


1. ขอ API Key

1.1. ไปที่ Google API Console https://code.google.com/apis/console/?noredirect แล้วไปที่เมนู Services


แล้วทำการ enable Google+ API

วันศุกร์ที่ 18 กรกฎาคม พ.ศ. 2557

HessianSerializer : java


        Hessian เป็น library ที่เอาไว้ serialize ข้อมูลจากรูปแบบหนึ่งไปสู่อีกรูปแบบหนึ่ง  ตัวอย่างเช่น การ serialize ข้อมูลที่เป็น object ไปลง file หรือ deserialize จาก file ไปเป็น object อีกทั้งยังมีความสามารถในการ zip / unzip ข้อมูลที่ถูก serialize/deserialize อีกด้วย  สามารถอ่านเพิ่มเติมได้จาก http://www.caucho.com/resin-3.1/examples/hessian-serialize/index.xtp

ที่มาของการใช้ Hessian
        ช่วงนี้ผมต้องพัฒนา web offline ให้กับลูกค้า  โดยตัว offline หรือ client นั้ันเอาไว้แก้ปัญหาในกรณีที่ user ไม่มี internet ใช้ที่บ้าน หรืออินเตอร์เน็ตช้า คีย์ข้อมูลลำบาก เขาก็จะทำการ download (export) ข้อมูลจากระบบ online หรือตัว server เพื่อนำไป import และ คีย์ข้อมูลในระบบ offline  แทน
        ผมก็เลยใช้ hessian ในการ export ข้อมูลทีเป็น object ไปเป็น file แล้วให้ user นำ file นั้นไป import เข้าตัว client จากนั้นก็จะใช้ hessian ในการแปลงกลับจาก file ไปเป็น object ต่อไปครับ

        จากที่ใช้มาหลายงาน  ก็สะดวกดีน่ะครับ วันนี้ก็เลยเอา libraries เล็กๆ น้อยๆ ที่เขียนไว้มาแชร์ครับ :)
ซึ่งปรับแต่งเพิ่มเติมใหม่นิดหน่อย  เพื่อให้ใช้งานได้สะดวกขึ้น

วันอาทิตย์ที่ 15 มิถุนายน พ.ศ. 2557

Lazy Load Selection Primefaces



ต่อยอดจาก code และ บทความ  custom JSF primefaces lazyLoad with Spring data

บทความนี้เป็นการต่อยอด  จากบทความเดิมที่ผมเขียนไว้ครับ
เป็นการแก้ปัญหา  การเก็บ state ของ primefaces table selection (check box)

คือ ผมเจอปัญหาว่า  เวลาใช้งาน primefaces table selection ที่เขาเตรียมมาให้  ร่วมกับ lazy load (paging)
มันไม่ยอมเก็บ state ให้  เมื่อเราเลือกไปที่ page อื่น แล้วกลับมาที่ page เดิม  อันที่เรา select ไว้จะหายไป

ผมจึงต้อง custom lazy load + การเก็บ state check box เอง  ลองมาดู code กันครับ
ซึ่งมี ขึ้นตอนดังต่อไปนี้

5 ขั้นตอน  การเขียน code

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

JSF notification - notify phase : java



        ผมใช้ JSF มาได้ 2 ปี แล้วครับ จึงเกิดความคุ้นเคยในระดับนึง  ใช้ไปใช้มา  ก็เริ่มเห็นข้อบกพร่อง ของ code ที่ตัวเองเขียน  รู้สึกว่าบางอย่าง  มันยังดูซ้ำซ้อน หรือใช้ยากไป  เราสามารถลดมันลงได้อีกมั้ย ทำให้มันง่ายกว่านี้ได้มั้ย ใช้ของเดิมที่เคยมีอยู่แล้วได้มั้ย  ช่วงนี้ผมก็เลยค่อยๆ เริ่มเขียน library สำเร็จรูปเอาไว้ใช้งานภายในบริษัทครับ  อย่างตัวอย่างวันนี้  ผมเขียนตัว notify phase (<p:grlow/> ของ primefaces)  ซึ่งมันจะจัดการ notify กลับไปยัง client (browser) ให้เองโดยอัตโนมัต เมื่อมันทำงานเสร็จ เราไม่ต้องมาคอย check if else ว่าเมื่อ code ทำงานสำเร็จให้แจ้ง success หรือ code ทำงานผิดพลาดให้แจ้ง fail เดี๋ยว notify phase จะจัดการให้เองครับ

Servlet I/O Download File : java


maven dependencies (pom.xml)
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>16.0.1</version>
    <type>jar</type>
</dependency>

วันอังคารที่ 13 พฤษภาคม พ.ศ. 2557

Composite key generator : java

maven dependencies
<dependency>
    <groupId>commons-lang</groupId>
    <artifactId>commons-lang</artifactId>
    <version>2.6</version>
</dependency>
CompositeKeyGenerator.java
package com.blogspot.na5cent.util;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;

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

    private static final String KEY_PATTERN = "\\{\\s*(.*?)\\s*\\}";
    private static final String KEY_SPLITOR = ":";

    public static String generateKey(String prefixName, String... keys) {
        return prefixName + "{" + StringUtils.join(keys, KEY_SPLITOR) + "}";
    }

    private static String selectKey(String text) {
        Pattern patternCompile = Pattern.compile(KEY_PATTERN);
        Matcher matcher = patternCompile.matcher(text);
        if (!matcher.find()) {
            return text;
        }

        return matcher.group(1);
    }

    public static String getKeyIndex(String key, int index) {
        return StringUtils.split(selectKey(key), KEY_SPLITOR)[index];
    }
}