@TOC

1, the background

A few days ago, the project went online, is to change the MVC framework from Spring MVC to Restlet, and then the customer said that the original TXT file export function reported 500, and there was no error log on the production, and behind more customers said that some TXT file export function is feasible. After scene reappearance, it is finally deduced that the TXT function is normal to export large files, and small files will fail.

After layer upon layer of stack analysis, the Restlet framework uses ServletOutputStream to write messages. The function class exported by TXT uses PrintWriter object to write, while in the definition of Response object, only one way can be used to write Response information. The ServletOutputStream uses the byte stream BB array of OutputBuffer and PrintWriter uses the cb array of OutputBuffer, so the two methods cannot be used together.

2. Cause search

2.1 Small File Failed

Let’s look at the two methods that a Response object uses to get PrintWriter and ServletOutputStream

As you can see, these two methods are mutually exclusive, and their specific data processing is delegated to the OutputBuffer object. For details, see CoyoteOutputStream and CoyoteWriter’s write methods.

CoyoteWriter’s Wrtie method:

Wrtie method for CoyoteOutputStream:

Ob here refers to OutputBuffer, and then we trace it to OutputBuffer, and finally find that it uses two different data to store these two methods respectively

We won’t go into the details of what OutputBuffer does when it writes data, but we can clearly see that ServletOutputStream and PrintWriter cannot be used together because they use different data buffer objects. In Restlet framework design, he uses a ServletCall

2.2 Large files are feasible

If the size of the OutputBuffer is larger than the size of the OutputBuffer, the OutputBuffer sends a response to the Client through the SocketOutputStream in advance

As you can see in the write method, it checks to see if the CB buffer is full, and if it is, it flushes out the content in advance. Therefore, when the exported file is larger than the buffer size, it can be exported normally.

conclusion

Therefore, when using PrintWriter object and ServletOutputStream object of Response object, it must be noted that they cannot be used at the same time to avoid such bugs