Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@ResponseBody does not work with @ExceptionHandler [SPR-6902] #11567

Closed
spring-issuemaster opened this issue Feb 24, 2010 · 17 comments

Comments

@spring-issuemaster
Copy link
Collaborator

commented Feb 24, 2010

Florent Ramiere opened SPR-6902 and commented

When this method is executed

@ExceptionHandler
@ResponseBody
public String dummyExceptionHandler(Exception e) {
    return e.getMessage();
}

Spring mvc tries to resolve the view using the method output --> 404.
As the method is annotated with @ResponseBody, it should directly write the method output to the response.


Affects: 3.0.1

Attachments:

Issue Links:

  • #11850 AnnotationMethodHandlerAdapter and AnnotationMethodHandlerExceptionResolver should supports MappingJacksonHttpMessageConverter by default ("is duplicated by")
  • #12476 Add support for @Request-/@ResponseBody to @ExceptionHandler methods ("is duplicated by")
  • #11626 @ResponseStatus does not work with @ExceptionHandler

Referenced from: commits 157623b, 7f8c91a

0 votes, 8 watchers

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 15, 2010

Scott Frederick commented

This is somewhat related to #11359. Is there any chance that #11359 can be addressed sooner than 3.1?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 15, 2010

Simon Wong commented

Could the ResponseErrorHandler (for RestTemplate) get the error message from @ResponseBody in this case? Also, will the @ResponseBody from @ExceptionHandler supports the HttpMessageConversion?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Mar 17, 2010

Simon Wong commented

Add a new issue regarding to my concern
https://jira.springsource.org/browse/SPR-7001

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Apr 5, 2010

Tyler Vallillee commented

I believe this bugfix also addresses #11359

I have the following web controller method:

@ExceptionHandler(MyServiceException.class)
@ResponseBody
public MyServiceException handleException(MyServiceException ex, HttpServletResponse response) {
  response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
  return ex;
}

where MyServiceException is mapped to XML via an XSD file.

I then put in my service-servlet.xml file the following annotation definition:

<!-- When an exception occurs, we support the following output formats -->
<bean id="outboundExceptionAdapter" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver">
    <property name="messageConverters">
        <util:list>
                    <!-- Support XML marshaling -->
            <bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
                <property name="marshaller" ref="xmlMarshaller"/>
                <property name="unmarshaller" ref="xmlMarshaller"/>
            </bean>
                        <!-- Return plain text -->
            <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
        </util:list>
    </property>
</bean>
<bean id="xmlMarshaller" class="org.springframework.oxm.xmlbeans.XmlBeansMarshaller"/>  

And now when an exception occurs, I get nicely rendered XML returned with an HTTP 500 error code.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Apr 6, 2010

Scott Frederick commented

Tyler,

This issue is slightly different than #11359. If you annotate an @ExceptionHandler method with @ResponseBody, then Spring will use a MessageConverter to marshal the returned object to the proper response message (an XML document in your example). The fix for this issue (#11567) should make @ExceptionHandler and @ResponseBody work well together.

If you do not apply the @ResponseBody annotation to an @ExceptionHandler method, then Spring will try to use a View to marshal the returned object instead of a MessageConverter. MarshallingView is a View that can be used to marshal the object to XML (i.e. MarshallingView is the View analog to MarshallingHttpMessageConverter). Fixing #11359 should make this path work as expected, so developers can choose to use MessageConverters or Views to marshal the output.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Dec 1, 2010

Adrian commented

Don't know if this is a regression, but with 3.0.5 I get the following warn message and the exception is thrown as if no handler was defined. Debugging shows that the handler is executed.

WARN : org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver - Could not find HttpMessageConverter that supports return type [class default.W3CGeoLocation] and [application/json, text/javascript, /]

The handler is as follows:

@ExceptionHandler
public @ResponseBody
W3CGeoLocation handleException(IllegalArgumentException exception) {
return new W3CGeoLocation();
}

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Dec 9, 2010

Arjen Poutsma commented

@Adrian:

I am not sure this is related to the issue above. Is W3CGeoLocation a supported object by the JSON message converter?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Dec 9, 2010

Adrian commented

W3CGeoLocation is a simple pojo. I return this object when everything is ok as well (here it is working fine), but when an exception happens I whant to return an empty object since this a Ajax request.

I think this whole thing is related to https://jira.springframework.org/browse/SPR-7637

It would be really nice if exception handler method behaved like normal request handler method plus the feature that they are called when an exception in a request method happens. This would make the controller code much cleaner.
Right now it is not possible to pass a ModelMap to a exception handler method, and also all ModelAttributes get lost somehow. This means if I return the same view with a form in it, the form-tag cannot find the model anymore.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Dec 20, 2010

Arjen Poutsma commented

I cannot reproduce this, using @ResponseBody for @ExceptionHandler works fine for me (also when using a JSON response object).

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Dec 24, 2010

Jack Punt commented

Arjen, given that you cannot reproduce the problem (and many of us are stumbling on this),
Could you include/document the necessary/sufficient conditions to make this work?
What version, what config, or what ever?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jan 10, 2011

Adrian commented

Sorry for not giving peace on this, but this time I made a small test project where you can verify the issue. I was unable to make a junit test for this, so you will have to click this through.

It is really simple. The controller looks like this:

@Controller
public class HomeController {

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String home() {
		return "index";
	}

	@RequestMapping(value = "/data", method = RequestMethod.GET)
	public @ResponseBody
	MyData get(@RequestParam boolean exception) {
		if (exception) {
			throw new IllegalArgumentException();
		}
		else {
			return new MyData();
		}
	}

	@ExceptionHandler(IllegalArgumentException.class)
	public @ResponseBody
	MyData handleException() {
		return new MyData();
	}

}


The corresponding JSP file:

<html>
<head>
<script type="text/javascript" src="resources/jquery-1.4.4.min.js"></script>
<script type="text/javascript">
	function showData(data) {
		alert("got it: " + data);
	}
</script>
</head>
<body>
<button onclick="$.getJSON('data', {exception : false}, showData);">Get Json Data</button>
<p/>
<button onclick="$.getJSON('data', {exception : true}, showData);">Get Json Data with Exception</button>
</body>
</html>

When you click on "Get JSON Data" everything is fine. When you click "Get Json Data with Exception" you get nothing in the browser and there is the following entry in tomcat log:

WARN : org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver - Could not find HttpMessageConverter that supports return type [class de.emaitie.test.MyData] and [application/json, text/javascript, /;q=0.01]

It is running on Springframework 3.0.5.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jan 10, 2011

Adrian commented

Test project

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jan 10, 2011

Arjen Poutsma commented

Thanks Adrian, I will take another look at this now.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jan 10, 2011

Arjen Poutsma commented

Fixed.

The issue was that the MappingJacksonHttpMessageConverter was not registered with the AnnotationMethodHandlerExceptionResolver (which handles @ExceptionHandler methods), only with the AnnotationMethodHandlerAdapter (which handles @RequestMapping methods).

This is now fixed, or at least when you use mvc:annotation-driven/.

Adrian, could you try a recent 3.1 SNAPSHOT (as of tonight), and see if it works for you? If so, we will backport it to 3.0.6.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jan 11, 2011

Adrian commented

Thanks Arjen. I tried it with 3.1.0.BUILD-20110111.020601-120 and its working now.

I was hoping that you could solve it a little bit differently. IMHO the RequestHandler and ExceptionHandler Adapter/Resolver should behave exactly the same, meaning allowing the same input parameters and return values. The only difference should be that the ExceptionHandler methods are called when something breaks in the RequestHandler methods.
This is already requested here: https://jira.springframework.org/browse/SPR-7637

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

commented Jan 11, 2011

Rossen Stoyanchev commented

Arjen, based on the description of the fix #11850 is probably fixed too.

@spring-issuemaster

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.