เรื่องประหลาดๆ ของการนับปีใน Java

ลืมหัวข้อ blog นี้ไปก่อนนะครับ แล้วลองพยายามเดาดูว่าโค้ด Java ข้างล่างนี้พยายามทำอะไร มันก็ดูตรงไปตรงมาใช่มั้ยครับ แล้วถ้ารันออกมาสมมติวันนี้วันที่ 1 ธันวาคม 2021 สิ่งที่ function นี้คืนกลับมาก็ เป็น 2020-12-01 ใช่มั้ยครับ ถ้าเราเขียน Unit test ไว้ เทสนี้ก็น่าจะผ่านได้ง่ายๆ ปกติไม่มีอะไร เรื่องมันมีอยู่ว่า ถ้าสมมติวันนี้เป็นวันที่ 31 ธันวาคม 2021 แล้วโค้ดชุดนี้เอาไว้บอกว่าควรจะจ่ายเงินเดือนเราตอนวันที่เท่าไร ลองทายดูมั้ยครับว่าจะเกิดอะไรขึ้น รู้จักกับ DateTimeFormatter กันก่อน ผมสังเกตุเห็น อย่างน้อยก็ใน Codebase ที่ผมทำงานด้วยอยู่ว่า Java Developer ส่วนใหญ่จะยังคุ้นเคยกับ Date API ที่มีมาตั้งแต่ Java 1.0 หน้าตาประมาณโค้ดข้างล่างครับ ซึ่ง จะเห็นได้ว่า Date API ตัวเก่าของ Java นั้นมีปัญหาเยอะมาก อย่างเช่นการที่จะปั้นเวลาซักอย่างก็เริ่มที่ปี 1900 แล้วบวกไปเอาหรือเดือนที่เริ่มที่ index ที่ 0 ซึ่งไม่ใช่ว่าทางทีมพัฒนา Java จะไม่พยายามแก้ปัญหานี้นะครับ ความพยายามแรกคือ Calendar class ที่ออกมาใน Java 1.1 แต่ก็ยังมีปัญหาหลายๆ อย่างอยู่ จน Java Developer หลายคนเลือกที่จะไปใช้ 3rd Party Library อย่าง Joda-Time แทน ซึ่งหลังจาก Oracle ได้ยึด Java ไปก็เลยเกิด Date/Time API ตัวใหม่ขึ้นมาใน Java 8 ซึ่งมีพื้นฐานหลายๆ อย่างมาจาก Joda-Time ครับ ...

December 1, 2021 · 2 min

Spring ก็เร็วได้! มาเรียก Method ใน Spring แบบ Parallel ด้วย @Async กันเถอะ

สมมติว่าเรามีโจทย์ที่ต้องยิง HTTP Request เพื่อดึง resource มาจาก Web service อื่นหลายๆ ที่ ถ้าเราไม่คิดอะไรเราก็อาจจะเขียนโค้ดให้ ยิงทีละตัวแบบ Synchronous ไปได้ แต่ถ้าแต่ละ Request ไม่ได้ขึ้นต่อกัน เราจะมีตัวเลือกมากขึ้นผ่านการยิงแบบ Asynchronous ครับ ซึ่งผมเพิ่งรู้ว่า Java มันทำได้ Example สมมติว่าเรามี Service ที่ไว้ยิง HTTP Request ไปที่ API อื่นแบบง่ายๆ หน้าตาประมาณนี้ @Service public class ActivityService { RestTemplate restTemplate = new RestTemplate(); public ResponseSecond getEndpointOne() { String url = "http://localhost:8000/1"; ResponseSecond response = restTemplate.getForObject(url, ResponseSecond.class); return response; } } และมี Controller ที่เรียกใช้ Service นี้หน้าตาประมาณนี้ ...

January 12, 2021 · 3 min

แชร์ประสบการณ์ Config ตัว Amazon ElastiCache ให้ใช้งานกับ Spring Boot

Story 2 - 3 วันที่ผ่านมาพยายามต่อ Redis บน ElastiCache แล้ว Error ตลอดเวลาเรียกใช้ จะมี Log ขึ้นประมาณข้างล่างนี้ แล้วแก้จนมันใช้ได้แล้วเอาขึ้น Server ไปละ นี่คือเรื่องของมัน org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to ███████-cache.███████.com:6379 Caused by: io.lettuce.core.RedisConnectionException: Unable to connect to ███████-cache.███████.com:6379 e Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem Caused by: java.security.cert.CertificateException: No subject alternative DNS name matching ███████-cache.███████.com found. สันนิษฐานแรกคือน่าจะเกี่ยวกับ In-Transit Encryption feature ของ ElastiCache’s Redis ซึ่งถูกเลือกไว้แล้ว แล้วหลังจาก Research ไปซักระยะเลยเจอว่า ElastiCache’s Redis allow ให้ Connect ผ่าน VPC เท่านั้น ...

December 24, 2020 · 3 min

บันทึกวิธีใช้ liquibase ทำ database migration ให้ Spring boot

Installation ลง Liquibase ใน pom.xml <dependencies> <dependency> <groupId>org.liquibase</groupId> <artifactId>liquibase-core</artifactId> <version>3.6.2</version> </dependency> </dependencies> เพิ่ม configuration ให้ liquibase ใน application.properties ## Liquibase spring.liquibase.enabled=true spring.liquibase.parameters.EnumDataType=ENUM('VALUE1', 'VALUE2', 'VALUE3') spring.liquibase.contexts=local ตัวสำคัญคือ spring.liquibase.contexts ตัวนี้เหมือนคอยบอกว่าเรารัน Spring โหมดอะไรอยู่ แล้วทำให้เราใช้ connection database ที่เราเซตไว้ใน spring ได้ด้วย อีกจุดนึงคือ spring.liquibase.parameters อันนี้เป็น custom parameter ที่เราเอาไว้ใช้ใน Changeset ซึ่งบางครั้งของ database คนละแบบจะต่างกันอย่างเช่น type ENUM ของ H2 เก็บเป็น enum ได้เลย แต่ PostgreSQL ตัว spring จะแปลงเป็น INT เลยต้องมาประกาศไว้ด้วย Usage เพิ่มไฟล์ ChangeLog master ไฟล์นี้เป็นเหมือนไฟล์หลักไว้บอกว่ามี migration step อะไรบ้างผ่าน property ชื่อ include.file ไฟล์กับชื่อจะอยู่ที่ /resources/db/changelog/db.changelog-master.yaml ตัวนี้สามารถตั้งค่าให้ไปอยู่ที่อื่น ชื่ออื่นได้ แต่อันนี้คือชื่อ default หน้าตาของไฟล์จะประมาณ databaseChangeLog: - include: file: db/changelog/001-add-user-table.yaml สร้าง ChangeSet ตัวนี้ไว้บอกว่าใน migration นี้มี change อะไรเกี่ยวกับ database บ้าง ตัวอย่างเช่นของ user databaseChangeLog: - changeSet: id: 001-add-user-table author: man changes: - createTable: columns: - column: constraints: nullable: false primaryKey: true primaryKeyName: user_pkey name: id type: UUID - column: constraints: nullable: false name: name type: VARCHAR(250) - column: constraints: nullable: false name: type type: ${EnumDataType} - column: name: is_admin type: BOOLEAN - column: name: created_at type: TIMESTAMP tableName: user ใน changeSet ต้องบอกว่ามันเป็น changeSet ซึ่งมี property หลักๆ ที่ใช้คือ ...

October 27, 2020 · 3 min