Menu

Showing posts with label exception. Show all posts
Showing posts with label exception. Show all posts

Monday, June 28, 2021

[Java - Spring Boot] Exception Handler ใน Spring Boot
[Java - Spring Boot] Exception Handler in Spring Boot

สำหรับ Exception Handler เราจะสร้าง class ที่ใช้ @ControllerAdvice ดังนี้
package com.example.exception;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import java.util.LinkedHashMap;

@ControllerAdvice
public class CustomExceptionHandler   {

    @ExceptionHandler(value = {ExceptionWrapper.class})(value = {exception_class.class})
    public ResponseEntity<Object> exceptionHandler(exception_class ex) {
    	// Handle specific exception then return ResponseEntity
        return new ResponseEntity(ex,HttpStatus.BAD_REQUEST);
    }
}
      
โดยที่ exception_class เป็นชื่อของ Exception Class ที่ต้อง handle 

คำอธิบายเพิ่มเติม
  • @ControllerAdvice - อนุญาตให้เรา apply เทคนิคใน class ข้างใต้มันกับทุกๆ controller ของเรา (อ่านเพิ่มเติมที่ ControllerAdvice)
  • @ExceptionHandler - ใช้เพื่อระบุว่า method ข้างใต้มันเป็น Exception handling methods (อ่านเพิ่มเติมที่ ExceptionHandler)

Monday, August 3, 2020

[Android - Espresso] การจัดการ System Animation ของ Emulator
[Android - Espresso] Managing Emulator System Animations

การรัน Espresso โดยเปิด system animation เอาไว้ จะทำให้เกิด exception ดังนี้
androidx.test.espresso.PerformException: Error performing 'single click' on view 'Animations or transitions are enabled on the target device.
วิธีแก้ไข exception นี้ คือ ต้องปิด system animation ก่อนรัน Espresso Test

วิธีที่ง่ายที่สุดสำหรับการปิด system animation คือ รันคำสั่งต่อไปนี้ใน Terminal (Powershell สำหรับ Windows)
adb shell settings put global window_animation_scale 0.0
adb shell settings put global transition_animation_scale 0.0
adb shell settings put global animator_duration_scale 0.0
นอกจากการปิด system animation แล้ว ยังมีการตั้งค่าอื่นสำหรับ UI test automation อีก สามารถอ่านเพิ่มเติมได้ที่ https://testyour.app/blog/emulator

หมายเหตุ กรณีที่ทดสอบใน device จริง สามารถใช้คำสั่งข้างต้นเพื่อปิด system animation ได้เช่นกัน แต่ต้องเชื่อมต่อ device เข้ากับเครื่องที่รัน Espresso เสียก่อน

Monday, September 9, 2019

[Laravel - Exception] วิธีการแสดง Validation Errors บนหน้าเว็บ
[Laravel - Exception] How to Display Validation Errors on Web Page

เนื่องจากใช้ฟังก์ชั่น validate ตาม code ข้างล่าง
public function update()
    $this->validate($this->request, [
        'ids' => 'required|array',
        'ids.*' => 'required|integer',
    ]);
    return 'test';
}
ทำให้เวลาที่ Validate request ไม่ผ่าน มันจะ throw ValidationException โดยอัตโนมัติ ซึ่งวิธีการ Handle มี 3 วิธีดังนี้
  1. ใช้ try...catch ครอบ code ส่วน validation เพื่อ handle ValidationException ที่เกิดขึ้นในแต่ละ function ของ controller
  2. เพิ่มการ handle ใน Handler class เพื่อเป็น handle กลางสำหรับ ValidationException ที่ไม่ถูก handle จากข้อแรก
  3. ข้ามข้อ 1 และ 2 แล้วนำ ValidationException มาแสดงผลบนหน้าเว็บ เนื่องจากเวลาเกิด ValidationException ระบบจะ redirect กลับไปหน้าก่อนหน้าพร้อมกับตัวแปรชื่อ $errors
สำหรับวิธีการแสดง Validation Error บนหน้าเว็บ ให้ใส่ code ด้านล่างนี้ในส่วนของ Blade template
@foreach ($errors->all() as $error)
    <div>{{$error}}</div>
@endforeach
หมายเหตุ  ตัวแปร $errors ข้างต้นไม่สามารถตรวจสอบได้ โดยการ inspect ดู Network ของ browser และการเรียกดูจาก request ใน controller

Thursday, August 29, 2019

[Laravel - Exception] ระวังข้อผิดพลาด "Prepared statement contains too many placeholders" หากมีการ Bulk Insert ข้อมูลจำนวนมาก
[Laravel - Exception] Warning: "Prepared statement contains too many placeholders" Exception if Bulk Insert Large Data

การทำ bulk insert หรือการ insert ข้อมูลทีละเยอะๆ สามารถช่วยลดจำนวนการยิง query หลายๆรอบได้ ซึ่งส่งผลให้เวลาในการทำงานลดลงอย่างเห็นได้ชัด โดยเฉพาะอย่างยิ่ง เมื่อ Database อยู่คนละเครื่อง Server

แต่... อย่าเพิ่งคิดนะครับว่า เราจะยิงข้อมูลเป็นก้อนใหญ่ๆไปเลยทีเดียวได้

เพราะว่ามันก็มี limit ในเรื่องของ placeholder อยู่เหมือนกัน ซึ่งถ้าหากเราส่งข้อมูลก้อนใหญ่เกินไปก็จะได้ error นี้กลับมา
PDOException: SQLSTATE[HY000]: General error: 1390 Prepared statement contains too many placeholders in /var/www/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:77
แล้ว placeholder มาจากไหน?

Monday, May 27, 2019

[Laravel - Exception] ข้อควรระวัง: โปรดระวังการใช้ Exception class ใน catch เมื่อใช้ try...catch
[Laravel - Exception] Warning: Using Wrong Exception Class in catch when Using try...catch

try...catch ถูกใช้ในการ handle exception

อย่างไรก็ตาม มีบางกรณีที่ทำให้ exception ไม่ถูก handle ในส่วนของ catch และถูก throw ออกไปโดยไม่มีการ handle ใดๆ

ผมจะใช้โค้ดตัวอย่างเพื่อแสดงว่า โค้ดส่วนใดที่คุณต้องระวังเป็นพิเศษ

โค้ดทั้งสองตัวอย่างเป็น Laravel commands ที่สามารถเรียกใช้งาน โดยรันคำสั่งใน console ดังนี้
php artisan test-exception

Thursday, April 4, 2019

[Laravel - Exception] วิธีการแก้ไข exception หลังจากพลาดรันคำสั่ง php artisan config:cache
[Laravel - Exception] How to Fix Exception after Running php artisan config:cache Command

คำอธิบายของคำสั่ง config:cache คือ สร้าง cache file สำหรับการโหลดค่า config ที่เร็วขึ้น (คุณสามารถรันคำสั่ง php artisan ใน console เพื่อดูคำอธิบายของแต่ละคำสั่งได้)

อย่างไรก็ตาม ผลกระทบจากการรัน  php artisan config:cache อาจจะประกอบด้วย
  1. Website/APIs ของคุณจะตอบกลับด้วย error code 500 Internal Server Error เสมอ โดยไม่มี log ใดๆใน laravel.log
  2. ทุกคำสั่งที่รันด้วย php artisan จะ throw exception ตามภาพด้านล่าง
  3. ทุกคำสั่งที่รันด้วย composer จะรันได้ตามปกติ

วิธีแก้ไข exception นี้ คือ การลบ cache file ที่ถูกสร้างขึ้นมา ซึ่งสำหรับ Laravel 5.6 cache file ดังกล่าวจะอยู่ที่ bootstrap/cache/config.php

Tuesday, February 5, 2019

[Laravel - Command] วิธีการเรียกใช้ command ที่ถูกต้อง จากอีก command นึงใน Laravel
[Laravel - Command] How to Call Laravel Command from Other Commands

บางครั้งเราต้องการสร้าง command เพื่อเรียกใช้ชุด command ที่ได้สร้างไว้ก่อนหน้าแล้ว

สมมติว่า มี 2 commands คือ command A และ B แล้วเราสร้าง command C มาอีกตัว เพื่อเรียกใช้ 2 commands นี้

ถ้าหากเป็นการเรียกรัน command จาก controller ปกติ ก็จะใช้คำสั่งดังนี้
Artisan::call('A');
Artisan::call('ฺB');

แต่สำหรับการเรียกรัน command จากอีก command นึง ห้ามใช้ Artisan::call โดยเด็ดขาด เนื่องจากถ้าหากเกิด exception ขึ้น มันจะไม่ throw exception ออกมายัง command C ทำให้ command C สามารถรันต่อจนเสร็จได้ ถึงแม้จะเกิด exception ใน command A หรือ B ซึ่งเราจะไม่สามารถรู้ได้เลยว่า มันทำงานเสร็จแล้วจริงๆหรือมันเกิด exception ขึ้น ถ้าเราไม่ดูจาก error logs

ในความเป็นจริงแล้ว เราควรจะรู้ว่า command ใดเกิด exception ขึ้น และไม่มีความจำเป็นที่ต้องรัน command อื่นๆต่อไป ในกรณีที่ exception ได้เกิดขึ้นแล้ว ดังนั้นให้ใช้ $this->call แทนดังนี้
$this->call('A');
$this->call('ฺB');

อ่านเพิ่มเติม: https://laravel.com/docs/5.7/artisan#calling-commands-from-other-commands