Skip to content

@ExceptionHandler on CGLib-proxied controller is ineffectual [SPR-5959] #10627

Closed
@spring-projects-issues

Description

@spring-projects-issues

William Ashley opened SPR-5959 and commented

Here is a condensed example of the problem I'm encountering:

Controller:

package com.test;

import java.io.PrintWriter;

import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@Transactional( readOnly=true )
public class Test
{
	@ExceptionHandler
	public void exception( Throwable t )
	{
		System.out.println( "In exception handler" );
	}
	
	@RequestMapping( "/" )
	public void get()
	{
		throw new RuntimeException( "foo" );
	}
}

Dispatcher servlet config:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
	
	<tx:annotation-driven transaction-manager="transactionManager"/>
	<bean id="transactionManager" class="com.test.MockTransactionManager"/>
	
	<context:component-scan base-package="com.test"/>
	
</beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd"
	version="2.5">
	
	<servlet>
		<servlet-name>action</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>action</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
	
</web-app>

The exception handler is never invoked when the controller is proxied by CGLib (removing @Transactional removes the proxy and restores the exception handler). A little digging led me to org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver where there is this iteration over methods of the controller

		ReflectionUtils.doWithMethods(handlerType, new ReflectionUtils.MethodCallback() {
			public void doWith(Method method) {
				method = ClassUtils.getMostSpecificMethod(method, handlerType);
[snip]
			}
		});

which does arrive eventually at the proper exception handler method of my controller class, but because of the call to ClassUtils.getMostSpecificMethod() it winds up back at the overridden method on the CGLib-generated class (which from what I noticed it had already visited). I haven't researched enough to say this is the problem though.

@RequestMapping annotations appear to work normally through a proxied controller (and the @Transactional annotation does function correctly), so I'm hoping this can be fixed.


Affects: 3.0 M3

Issue Links:

1 votes, 2 watchers

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)status: duplicateA duplicate of another issue

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions