50.4. 응답과 예외 매핑

50.4.1. 개요

WebApplicationException 예외를 throw하는 것이 비현실적이거나 불가능한 경우가 있습니다. 예를 들어 가능한 모든 예외를 catch하고 이를 위해 WebApplicationException을 만들 필요가 없습니다. 애플리케이션 코드에서 더 쉽게 작업할 수 있도록 하는 사용자 지정 예외를 사용할 수도 있습니다.

이러한 경우를 처리하기 위해 JAX-RS API를 사용하면 클라이언트로 보낼 Response 개체를 생성하는 사용자 지정 예외 공급자를 구현할 수 있습니다. 사용자 지정 예외 공급자는 ExceptionMapper<E> 인터페이스를 구현하여 생성됩니다. Apache CXF 런타임에 등록하면 E 유형의 예외가 throw될 때마다 사용자 지정 공급자가 사용됩니다.

50.4.2. 예외 매퍼를 선택하는 방법

예외 매퍼는 다음 두 가지 경우에 사용됩니다.

  • 예외 또는 해당 하위 클래스 중 하나가 throw되면 런타임은 적절한 예외 매퍼를 확인합니다. 예외 매퍼는 throw된 특정 예외를 처리하면 선택됩니다. throw된 특정 예외에 대한 예외 매퍼가 없는 경우 예외의 가장 가까운 수퍼 클래스에 대한 예외 매퍼가 선택됩니다.If there is not an exception mapper for the specific exception that was thrown, the exception mapper for the nearest superclass of the exception is selected.
  • 기본적으로 WebApplicationException은 기본 매퍼, WebApplicationExceptionMapper 로 처리됩니다. 추가 사용자 지정 매퍼가 등록되어 있어도 WebApplicationException 예외(예: 사용자 지정 RuntimeException 매퍼)를 처리할 수 있는 경우 사용자 지정 매퍼가 사용되지 않고 WebApplicationExceptionMapper 가 대신 사용됩니다.

    그러나 Message 개체에서 default.wae.mapper.least.specific 속성을 true 로 설정하여 이 동작을 변경할 수 있습니다. 이 옵션이 활성화되면 기본 WebApplicationExceptionMapper 가 가장 낮은 우선 순위로 리버스되어 사용자 지정 예외를 사용하여 WebApplicationException 예외를 처리할 수 있습니다. 예를 들어 이 옵션이 활성화된 경우 사용자 지정 RuntimeException 매퍼를 등록하여 WebApplicationException 예외를 catch할 수 있습니다. “WebApplicationException에 대한 예외 매퍼 등록” 을 참조하십시오.

예외에 대한 예외 매퍼를 찾을 수 없는 경우 예외를 ServletException 예외로 래핑되고 컨테이너 런타임에 전달됩니다. 그러면 컨테이너 런타임에서 예외를 처리하는 방법을 결정합니다.

50.4.3. 예외 매퍼 구현

예외 매퍼는 javax.ws.rs.ext.ExceptionMapper<E> 인터페이스를 구현하여 생성됩니다. 예 50.5. “예외 매퍼 인터페이스” 에 표시된 대로 인터페이스에는 원래 예외를 매개 변수로 사용하고 Response 개체를 반환하는 단일 메서드인 toResponse() 가 있습니다.

예 50.5. 예외 매퍼 인터페이스

public interface ExceptionMapper<E extends java.lang.Throwable>
{
  public Response toResponse(E exception);
}

예외 매퍼에서 생성한 Response 오브젝트는 다른 Response 오브젝트와 마찬가지로 런타임에서 처리합니다. 소비자에 대한 결과 응답에는 Response 오브젝트에 캡슐화된 상태, 헤더 및 엔티티 본문이 포함됩니다.

예외 매퍼 구현은 런타임을 통해 공급자로 간주됩니다. 따라서 @Provider 주석으로 장식되어야 합니다.

예외 매퍼가 Response 개체를 빌드하는 동안 예외가 발생하면 런타임에서 500 Server Error 상태의 응답을 소비자에게 보냅니다.

예 50.6. “응답에 예외 매핑” Spring AccessDeniedException 예외를 가로채는 예외 매퍼를 표시하고 403 Forbidden 상태 및 빈 엔터티 본문을 사용하여 응답을 생성합니다.

예 50.6. 응답에 예외 매핑

import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;

import org.springframework.security.AccessDeniedException;

@Provider
public class SecurityExceptionMapper implements ExceptionMapper<AccessDeniedException>
{

  public Response toResponse(AccessDeniedException exception)
  {
    return Response.status(Response.Status.FORBIDDEN).build();
  }

}

런타임은 모든 AccessDeniedException 예외를 포착하고 엔티티 본문 및 상태 403 이 없는 Response 개체를 만듭니다. 그런 다음 런타임은 Response 오브젝트를 일반 응답과 마찬가지로 처리합니다. 그 결과 소비자가 상태가 403 인 HTTP 응답을 수신합니다.

50.4.4. 예외 매퍼 등록

JAX-RS 애플리케이션에서 예외 매퍼를 사용하려면 먼저 예외 매퍼를 런타임에 등록해야 합니다. 예외 매퍼는 애플리케이션의 구성 파일에 jaxrs:providers 요소를 사용하여 런타임에 등록됩니다.

jaxrs:providers 요소는 jaxrs:server 요소의 하위이며 빈 요소 목록 포함합니다. 각 빈 요소는 하나의 예외 매퍼를 정의합니다.

예 50.7. “런타임을 사용하여 예외 매퍼 등록” 사용자 지정 예외 매퍼, SecurityExceptionMapper 를 사용하도록 구성된 JAX-RS 서버를 보여줍니다.

예 50.7. 런타임을 사용하여 예외 매퍼 등록

<beans ...>
  <jaxrs:server id="customerService" address="/">
    ...
    <jaxrs:providers>
      <bean id="securityException" class="com.bar.providers.SecurityExceptionMapper"/>
    </jaxrs:providers>
  </jaxrs:server>
</beans>

50.4.5. WebApplicationException에 대한 예외 매퍼 등록

WebApplicationException 예외에 대한 예외 매퍼는 기본 WebApplicationException Mapper 에서 자동으로 처리되기 때문에 특별한 경우입니다. 일반적으로 WebApplicationException 을 처리 할 것으로 예상되는 사용자 정의 매퍼를 등록하더라도 기본 WebApplicationExceptionMapper 로 계속 처리됩니다. 이 기본 동작을 변경하려면 default.wae.mapper.least.specific 속성을 true 로 설정해야 합니다.

예를 들어 다음 XML 코드는 JAX-RS 끝점에서 default.wae.mapper.least.specific 속성을 활성화하는 방법을 보여줍니다.

<beans ...>
  <jaxrs:server id="customerService" address="/">
    ...
    <jaxrs:providers>
      <bean id="securityException" class="com.bar.providers.SecurityExceptionMapper"/>
    </jaxrs:providers>
    <jaxrs:properties>
      <entry key="default.wae.mapper.least.specific" value="true"/>
    </jaxrs:properties>
  </jaxrs:server>
</beans>

다음 예와 같이 인터셉터에서 default.wae.mapper.least.specific 속성을 설정할 수도 있습니다.

// Java
public void handleMessage(Message message)
{
    m.put("default.wae.mapper.least.specific", true);
    ...