Skip to content

When a @RequestMapping Returns a Sublclass of ResponseEntity It Is Returning Header and StatusCode Along with the Body [SPR-10046] #14680

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

Closed
spring-projects-issues opened this issue Nov 27, 2012 · 6 comments
Assignees
Labels
status: invalid An issue that we don't feel is valid

Comments

@spring-projects-issues
Copy link
Collaborator

Julian Builes opened SPR-10046 and commented

When subclassing ResponseEntity that returns a JSON response, the body in the resulting response is also including 'headers' and 'statusCode fields.

        class MyClass {      
            public String field;            
            public MyClass(String field1) {
                this.field = field1;
            }
        }
        
        class MyClassResponse extends ResponseEntity<MyClass> {
            public MyClassResponse(MyClass body, HttpHeaders headers, HttpStatus statusCode) {
                super(body, headers, statusCode);
            }
        }
        
        @RequestMapping(value = "aaa", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
        @ResponseBody
        public ResponseEntity<MyClass> dummy() {

            HttpHeaders headers = new HttpHeaders();
            headers.add("some-header", "some header value");
            headers.add("another-header", "another header value");

            return new MyClassResponse(new MyClass("this is the response body"), headers, HttpStatus.CREATED);
        }

Is returning:

{
"headers": {
"some-header": [(1)
"some header value"
],-
"another-header": [(1)
"another header value"
]-
},-
"body": {
"field": "this is the response body"
},-
"statusCode": "CREATED"
}

Considerations:

  • This appears to be a regression introduced between 3.1.2 and 3.1.3.
  • We are using Jackson to convert the JSON

Affects: 3.1.3

1 votes, 4 watchers

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

You don't need @ResponseBody when returning ResponseEntity. Just remove the annotation and it should work.

@spring-projects-issues
Copy link
Collaborator Author

Julian Builes commented

Rosen, I am not sure if I am missing something trivial here, but if I remove the @ResponseBody, I receive the following exception:

javax.servlet.ServletException: Could not resolve view with name '<some path>' in servlet with name '<servlet name>'.

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

@ResponseBody instructs Spring MVC to write the returned value to the response. ResponseEntity is a special return value that provides Spring MVC with all the information it needs to prepare the response -- body, headers, status. When you put @ResponseBody on a method that returns ResponseEntity, the former takes precedence and leads to unwanted results. What may have changed in 3.1.3 is the order in which these two are looked at. Regardless, it was never intended to have both at the same time. Here are some examples from the spring-mvc-showcase.

@spring-projects-issues
Copy link
Collaborator Author

Shelley J. Baker commented

This doesn't work for ResponseEntity subclasses, though. In particular, the HttpEntityMethodProcessor's supportsReturnType method explicitly looks for ResponseEntity/HttpEntity classes, not whether they are assignable from those classes:

public boolean supportsReturnType(MethodParameter returnType) {
	Class<?> parameterType = returnType.getParameterType();
	return HttpEntity.class.equals(parameterType) || ResponseEntity.class.equals(parameterType);
}

Changing this method to the following seems to do the trick:

public boolean supportsReturnType(MethodParameter returnType) {
    Class<?> parameterType = returnType.getParameterType();
    return HttpEntity.class.isAssignableFrom(parameterType);
}

(Or as a temporary workround, you can add a custom HandlerMethodReturnValueHandler which overrides this method.)

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

I think it'd be best to open a new issue. The original description here mixes @ResponseBody with ResponseEntity, which is not a valid combination. Your last comment is a legitimate issue. Thanks!

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Jan 22, 2013

Shelley J. Baker commented

#14840 has been logged for this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: invalid An issue that we don't feel is valid
Projects
None yet
Development

No branches or pull requests

2 participants