読者です 読者をやめる 読者になる 読者になる

修行@ホーチミン

ホーチミン長期出張の日記です

SpringBoot エラーハンドリング

前書き

今回は、エラーハンドリングを実装しました。

前回の、INSERT用Serviceクラスでは同じIDでリクエストを行うと、そのIDのUPDATE処理となってしまうため、既に存在するIDでリクエストがきた場合はエラーを返すようにしました。

内容

Exceptionクラス

RuntimeException を継承して、独自Exceptionクラスを生成

public class DuplicateException extends RuntimeException {

    private String type;
    private Long id; 
    
}
Repositoryクラス

論理削除(delete_flag=1)のレコードはSELECT時の対象外としているため、 論理削除されたレコードも抽出できるようにクエリを追加

    @Query(value="SELECT * FROM hotel WHERE id = :id ", nativeQuery=true)
    Hotel findHotelById(@Param("id") Long id);
Serviceクラス

既にホテルIDが存在した場合は、先ほど作成したExceptionを投げるように修正

    public HotelInsertResponseBody insertHotels(Hotel hotel) {
        // transform entity information as response as need
        Hotel check = hotelRepository.findHotelById(hotel.getId());
        if(check != null){
            throw new DuplicateException("hotel" ,hotel.getId());
        }
        hotel.setRegisterDatetime(new Timestamp(System.currentTimeMillis()));
        hotel.setRegisterPerson(DenaTravelUtils.API_NAME);
        Hotel res = hotelRepository.save(hotel);
        HotelInfo hotelInfo = new HotelInfo(res.getId(), res.getName(), res.getLatitude(), res.getLongitude());
        return new HotelInsertResponseBody(hotelInfo);
    }
Exception Handlerクラス

@ExceptionHandlerで、ハンドリングしたいクラスを指定します。 さらにハンドリングした際にエラーの詳細情報を作成し、エラーレスポンスとして返すようにします。

    @ExceptionHandler(DuplicateException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ErrorResponse handleException(DuplicateException e) {
        log.error("Request parameter validation failed", e);
        
        String type = e.getType();
        Long id = e.getId();
        HotelError error = HotelError.DUPLICATE_ID_ERROR;
        String detailMessage = type + " id=" + id + " is already exist.";
        return createErrorResponse(
                HttpStatus.BAD_REQUEST, 
                error, detailMessage,
                ErrorInfo.Type.VALIDATION );      
    }
確認
既存レコード (id = 105)
*************************** 1. row ***************************
               id: 105
             name: HIJ Hotel
         latitude: NULL
        longitude: NULL
          address: NULL
     country_code: NULL
        city_code: NULL
            grade: NULL
         facility: NULL
       image_path: NULL
register_datetime: 2016-09-12 16:21:23
  register_person: hotel-engine-training
  update_datetime: NULL
    update_person: NULL
      delete_flag: 1
  delete_datetime: 2016-09-12 17:15:20
    delete_person: hotel-engine-training
リクエスト

既存レコード (id = 105)のINSERTリクエストを投げます。

curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{
  "header": {
    "countryCode": "US",
    "currencyCode": "USD",
    "languageCode": "en",
    "uid": "string",
    "userAgent": "string",
    "userIp": "string"
  },
  "body": {
    "id": 105,
    "name": "HIJ HOTEL"
  }
}' 'http://localhost:8080/hotel/insert'
レスポンス

設定したエラーレスポンスが返ってくることが確認できました。

{
  "status": 400,
  "error": {
    "code": "HTLERR100",
    "message": "Duplicate id error",
    "type": "VALIDATION",
    "detailMessage": "hotel id=105 is already exist.",
    "invalidParameters": null
  }
}