To write Response data directly in Spring

There was a request to write directly to HttpServletResponse, so I investigated how to do it.

manner

Just define HttpServletResponse as an argument of Controller and write to it.

HelloController.java


@Controller
public class HelloController {

  @RequestMapping(value="/", method=RequestMethod.GET)
  public void hello(HttpServletResponse response) throws Exception {
    response.getWriter().write("hogehoge");
  }
}

I want to branch the pattern to write the response and the pattern to return the View name

The return value is a String. If you write directly to the response, null will be returned.

HelloController.java


@Controller
public class HelloController {

  @RequestMapping(value="/{param}", method=RequestMethod.GET)
  public String hello(HttpServletResponse response, @PathVariable String param) throws Exception {
    if(Objects.equals("param", param)){
      response.getWriter().write("hogehoge");
      return null;
    }
    return "hello";
  }
}

I was complained that I got an error when I returned null

There was a report that an error log appeared when I returned null. When I checked the log, I went looking for JSP but couldn't find it.

So when I checked the source code, it looked like the following.

HelloController.java


@Controller
public class HelloController {

  @Inject
  HttpServletResponse response

  @RequestMapping(value="/{param}", method=RequestMethod.GET)
  public String hello(@PathVariable String param) throws Exception {
    if(Objects.equals("param", param)){
      response.getWriter().write("hogehoge");
      return null;
    }
    return "hello";
  }
}

Certainly, when implemented like this, it seemed to look for a JSP and get an error. That is, the render process of View is being executed. By the way, I thought that HttpServletResponse can be injected, but it's not the main story, so it's through.

Let's check the contents of the framework

What are the conditions for the render process not to be executed?

When I check the DispatcherServlet, I am running the HandlerAdapter to get the ModelAndView. At this time, if the return value is null, render processing by View will not be executed. If you are writing the Response directly, this behavior is expected. (DoDispatch, processDispatchResult, etc.)

Then, what is the condition for the return value of HandlerAdapter to be null?

Looking at the processing of RequestMappingHandlerAdapter, null is returned when isRequestHandled of ModelAndViewContainer becomes true. (GetModelAndView etc.)

So what are the conditions for this to be true?

There are various conditions, but in this case, it is a condition that HttpServletResponse is in the argument of the Controller method and the return value from Controller is null. The source where the error occurred uses the HttpServletResponse defined in the field, so the return value of the HandlerAdapter did not become null.

For reference, the behavior when the View name is null

If you follow the process from applyDefaultViewName of DispatcherServlet, you can see that the requested URL is applied as the View name.

Solution

Let's add HttpServletResponse as an argument. If you can't do that, let's set the return type of Controller to ModelAndView as follows.

HelloController.java


@Controller
public class HelloController {

  @Inject
  HttpServletResponse response

  @RequestMapping(value="/{param}", method=RequestMethod.GET)
  public ModelAndView hello(@PathVariable String param) throws Exception {
    if(Objects.equals("param", param)){
      response.getWriter().write("hogehoge");
      return null;
    }
    return new ModelAndView("hello");
  }
}

You can see why this works by reading ModelAndViewMethodReturnValueHandler.

Recommended Posts

To write Response data directly in Spring
Create API to send and receive Json data in Spring
How to use Lombok in Spring
How to use Spring Data JDBC
[Rails] How to write in Japanese
Write test code in Spring Boot
[How to install Spring Data Jpa]
Spring Data JPA: Write a query in Pure SQL in @Query of Repository
How to get date data in Ruby
Convert request parameter to Enum in Spring
How to include Spring Tool in Eclipse 4.6.3?
Exists using Specification in Spring Data JPA
Null support cache in Spring Data Redis
How to write Spring AOP pointcut specifier
How to overwrite Firebase data in Swift
How to assemble JSON directly in Jackson
[JavaFX] How to write Eclipse permissions in build.gradle
Output request and response log in Spring Boot
How to add a classpath in Spring Boot
Map GET requests to complex objects in Spring.
How to hide null fields in response in Java
An introduction to Spring Boot + in-memory data grid
Jackson is unable to JSON serialize hibernateLazyInitializer in Spring Data JPA with error
How to bind to property file in Spring Boot
How to define multiple orm.xml in Spring4, JPA2.1
How to write Java String # getBytes in Kotlin?
Notes on how to write comments in English
[Spring Batch] Output table data to CSV file
How to clear all data in a particular table
How to write a unit test for Spring Boot 2
How to create a Spring Boot project in IntelliJ
I tried to get started with Spring Data JPA
How to create a data URI (base64) in Java
How to write a date comparison search in Rails
How to store Rakuten API data in a table
How to use CommandLineRunner in Spring Batch of Spring Boot
Make the where clause variable in Spring Data JPA
How to test file upload screen in Spring + Selenium
[Swift] Use UserDefaults to save data in the app
Write byte array image data to outputstream using ImageIO
Introduce swagger-ui to REST API implemented in Spring Boot
How to write an external reference key in FactoryBot
Be able to write Hamcrest Matchers in lambda expressions
How to use In-Memory Job repository in Spring Batch
How to write a core mod in Minecraft Forge 1.15.2
How to write Rails
How to write in Model class when you want to save binary data in DB with PlayFramework
How to use the same Mapper class in multiple data sources with Spring Boot + MyBatis
To debug in eclipse
Use Interceptor in Spring
Spring Data JDBC Preview
How to write Mockito
Microservices in Spring Cloud
How to write migrationfile
Get cookies in Spring
spring data dynamodb trap
How to change application.properties settings at boot time in Spring boot
How to use JSON data in WebSocket communication (Java, JavaScript)
How to call and use API in Java (Spring Boot)
Flow until output table data to view with Spring Boot
[IOS14] How to get Data type image data directly from PHPickerViewController?