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

@ResponseStatus documentation incorrect #30305

Closed
Tibotanum opened this issue Apr 9, 2023 · 1 comment
Closed

@ResponseStatus documentation incorrect #30305

Tibotanum opened this issue Apr 9, 2023 · 1 comment
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: documentation A documentation task
Milestone

Comments

@Tibotanum
Copy link

Tibotanum commented Apr 9, 2023

I think the documentation of @ResponseStatus in spring-web 6.0.7 is not correct. It says:

"The status code is applied to the HTTP response when the handlermethod is invoked and overrides status information set by other means,like ResponseEntity or "redirect:"."

However, when the following method is called in a @Controller class it does not return the HttpStatus.I_AM_A_TEAPOT status (418) but the HttpStatus.INTERNAL_SERVER_ERROR (500):

@RequestMapping("/hello")
@ResponseStatus(HttpStatus.I_AM_A_TEAPOT)
ResponseEntity<List<String>> doHello() {
    return ResponseEntity.internalServerError().body(Arrays.asList("hello", "goodbye"));
}

So, effectively the status set on the ResponseEntity is returned which is the opposite of what the documentation says.

When debugging, at some point the following method is called:

org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor.handleReturnValue(Object, MethodParameter, ModelAndViewContainer, NativeWebRequest)

Here, the ServletServerHttpResponse outputMessage initially contains the code 418 but later this is overwritten by the status of the ResponseEntity. It appears a ResponseEntity is also created within the method if the return value of the controller method is a ProblemDetail or ErrorResponse which could mean that a status on these types also overwrites the status defined by the @ResponseStatus.

The following controller method returns the expected status code 418:

@RequestMapping("/responseStatus")
@ResponseStatus(HttpStatus.I_AM_A_TEAPOT)
@ResponseBody
String doResponseStatus() {
    return "hello";
}

My POM.xml looks as follows:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.0.5</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demo</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>17</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

My main class:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

}

And my controller class:

package com.example.demo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;

import org.springframework.http.HttpStatus;
import org.springframework.http.ProblemDetail;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.ErrorResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.WebRequest;

import jakarta.servlet.http.HttpServletRequest;

@Controller
public class HelloController {

	@RequestMapping("/hello")
	@ResponseStatus(HttpStatus.I_AM_A_TEAPOT)
	ResponseEntity<List<String>> doHello() {
		return ResponseEntity.internalServerError().body(Arrays.asList("hello", "goodbye"));
	}
	
	@RequestMapping("/responseStatus")
	@ResponseStatus(HttpStatus.I_AM_A_TEAPOT)
	@ResponseBody
	String doResponseStatus() {
		return "hello";
	}

}
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Apr 9, 2023
@rstoyanchev
Copy link
Contributor

rstoyanchev commented Apr 17, 2023

That seems to have been updated in 55db4ae for #18019, which was intended to clarify the use of @ResponseStatus with HTML redirect views. However, even in that case it doesn't seem to override an explicit status in RedirectView.

I need to have a closer look to double check this, but documentation certainly needs an update, and indeed the annotation is not expected to override the same from ResponseEntity.

@rstoyanchev rstoyanchev added the in: web Issues in web modules (web, webmvc, webflux, websocket) label Apr 17, 2023
@poutsma poutsma added the type: documentation A documentation task label May 9, 2023
@poutsma poutsma self-assigned this May 9, 2023
@poutsma poutsma added this to the 6.0.9 milestone May 9, 2023
@poutsma poutsma removed the status: waiting-for-triage An issue we've not yet triaged or decided on label May 9, 2023
@poutsma poutsma closed this as completed in b674906 May 9, 2023
poutsma added a commit that referenced this issue May 9, 2023
This commit documents that the ResponseStatus annotation does not
override the status set through other means.

Closes gh-30305
See gh-18019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: documentation A documentation task
Projects
None yet
Development

No branches or pull requests

4 participants