ClientExceptionMapper.java
package io.extact.rms.client.api.adaptor.remote.rest;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import jakarta.annotation.Priority;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
import io.extact.rms.client.api.adaptor.remote.auth.SecurityConstraintClientException;
import io.extact.rms.client.api.exception.BusinessFlowClientException;
import io.extact.rms.client.api.exception.UnknownClientException;
import io.extact.rms.client.api.exception.ValidateClientException;
import io.extact.rms.client.api.exception.ValidateClientException.ValidationErrorMessage;
@Priority(Priorities.USER)
public class ClientExceptionMapper implements ResponseExceptionMapper<RuntimeException> {
private static final String RMS_EXCEPTION_HEADER = "Rms-Exception";
private static final String SERVER_VALIDATION_ERROR = "ConstraintViolationException";
private static final List<Integer> SECURITY_ERROR_STATUS =
List.of(
Status.UNAUTHORIZED.getStatusCode(),
Status.FORBIDDEN.getStatusCode()
);
private static final Map<String, Function<String, RuntimeException>> DEFAULT_EXCEPTION_MAPPING =
Map.of(
"BusinessFlowException", BusinessFlowClientException::new
);
private static final Function<String, RuntimeException> UNKNOWN_ERROR_HANDLER = UnknownClientException::new;
@Override
public boolean handles(int status, MultivaluedMap<String, Object> headers) {
return headers.containsKey(RMS_EXCEPTION_HEADER)
|| SECURITY_ERROR_STATUS.contains(status);
}
@Override
public RuntimeException toThrowable(Response response) {
// StatusCodeが401か403だったらセキュリティエラー
if (SECURITY_ERROR_STATUS.contains(response.getStatus())) {
return toSecurityException(response);
}
// 例外クラス名がConstraintViolationExceptionならバリデーションエラー
var causeClassName = response.getHeaderString(RMS_EXCEPTION_HEADER);
if (SERVER_VALIDATION_ERROR.equals(causeClassName)) {
return toValidationException(response);
}
// デフォルトマッピングのエラー
return toDefualtMappingException(response);
}
private SecurityConstraintClientException toSecurityException(Response response) {
return new SecurityConstraintClientException(response);
}
private ValidateClientException toValidationException(Response response) {
ValidationErrorMessage errorMessage = response.readEntity(ValidationErrorMessage.class);
return new ValidateClientException(errorMessage);
}
private RuntimeException toDefualtMappingException(Response response) {
String causeClassName = response.getHeaderString(RMS_EXCEPTION_HEADER);
String causeMessage = response.readEntity(new GenericType<Map<String, String>>() {}).get("errorMessage");
return DEFAULT_EXCEPTION_MAPPING.getOrDefault(causeClassName, UNKNOWN_ERROR_HANDLER).apply(causeMessage);
}
}