2012-07-18 10 views
6

El padre:Tengo una clase principal con @ExceptionHandler y una subclase con su propia versión. Recibo un error de método ambigua

@ExceptionHandler(NoUserException.class) 
protected ModelAndView handleException(NoUserException e) { 
    Map<String, Object> model = new HashMap<String, Object>(); 

    model.put(ModelKeys.HOST_KEY, "message"); 

    return new ModelAndView("noAccess",model); 
} 

El niño:

@ExceptionHandler(NoUserException.class) 
protected void handleException(NoUserException e, HttpServletRequest request, HttpServletResponse response) throws IOException { 
    logger.error("Invalid user."); 
    respond(CLIENT_USER_ERROR,response); 
} 

Sí, ellos no necesitan tener diferentes parámetros y salidas.

+0

¿qué quieres decir? Es un código en la clase principal ... es simplemente una nueva generación NoUserException() –

+0

¿no es así? está sucediendo cuando lo ejecuto. no puede decidir qué método usar. –

+0

Probablemente porque se definen dos '@ExceptionHandler's, uno heredado de la superclase y el nuevo definido en la subclase. No estoy seguro de cómo anularlo, no sucederá automáticamente porque los métodos no tienen la misma firma. – purtip31

Respuesta

8

No puede tener dos métodos con el mismo controlador de excepciones, lo siento, simplemente no es compatible. El código que los resuelve no distingue entre superclases y considera que la subclase es "más específica". El código está en org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver si te interesa. No sería difícil hacer su propia implementación de AbstractHandlerExceptionResolver basada en la que considera que un método directamente en el controlador tiene un resultado más específico que un método heredado.

editar: comentario personal, he descubierto que con el tiempo es mejor para mí suprimir el impulso de usar "herencia como herramienta de plantillas" cuando hago controladores accionados por anotaciones Spring MVC. El código de vista es intrínsecamente torpe y de procedimiento a veces, por eso hacemos una "capa de vista" separada en primer lugar. Un enfoque excesivamente micro para DRY y "reutilización" no le sirve aquí. Si viola el Principio de sustitución de Liskov, no lo hago. YMMV por supuesto.

1

¿Por qué no simplemente delegar la implementación de handleException() a otro método?

// superclass 
protected ModelAndView handleExceptionImpl(
     NoUserException e, 
     HttpServletResponse response) { 
    Map<String, Object> model = new HashMap<String, Object>(); 
    model.put(ModelKeys.HOST_KEY, "message"); 
    return new ModelAndView("noAccess",model); 
} 

@ExceptionHandler(NoUserException.class) 
protected ModelAndView handleException(
     NoUserException e, 
     HttpServletResponse response) { 
    return handleExceptionImpl(e, response); 
} 

// subclass 
@Override 
protected ModelAndView handleExceptionImpl(
     NoUserException e, 
     HttpServletResponse response) { 
    logger.error("Invalid user."); 
    respond(CLIENT_USER_ERROR,response); 
} 
Cuestiones relacionadas