@@ -154,11 +154,24 @@ private void handleBatch(HttpServletResponse resp, JsonNode rootNode, int maxRes
154154
155155 ArrayNode batchResult = MAPPER .createArrayNode ();
156156 int accumulatedSize = 2 ; // "[]"
157+ boolean overflow = false ;
157158
158159 for (int i = 0 ; i < rootNode .size (); i ++) {
160+ JsonNode subRequest = rootNode .get (i );
161+
162+ if (overflow ) {
163+ // Notifications (no "id") do not get a response even on overflow.
164+ if (subRequest .has ("id" )) {
165+ batchResult .add (buildErrorNode (JsonRpcError .RESPONSE_TOO_LARGE ,
166+ "Response exceeds the limit of " + maxResponseSize + " bytes" ,
167+ subRequest .get ("id" )));
168+ }
169+ continue ;
170+ }
171+
159172 byte [] subBody ;
160173 try {
161- subBody = MAPPER .writeValueAsBytes (rootNode . get ( i ) );
174+ subBody = MAPPER .writeValueAsBytes (subRequest );
162175 } catch (JsonProcessingException e ) {
163176 writeJsonRpcError (resp , JsonRpcError .INTERNAL_ERROR , "Internal error" , null , true );
164177 return ;
@@ -178,12 +191,14 @@ private void handleBatch(HttpServletResponse resp, JsonNode rootNode, int maxRes
178191 continue ; // notification — no response
179192 }
180193
181- // comma separator between array elements
194+ // comma(,) separator between array elements
182195 int addition = responseBytes .length + (!batchResult .isEmpty () ? 1 : 0 );
183196 if (maxResponseSize > 0 && accumulatedSize + addition > maxResponseSize ) {
184- writeJsonRpcError (resp , JsonRpcError .RESPONSE_TOO_LARGE ,
185- "Response exceeds the limit of " + maxResponseSize + " bytes" , null , true );
186- return ;
197+ overflow = true ;
198+ batchResult .add (buildErrorNode (JsonRpcError .RESPONSE_TOO_LARGE ,
199+ "Response exceeds the limit of " + maxResponseSize + " bytes" ,
200+ subRequest .get ("id" )));
201+ continue ;
187202 }
188203 accumulatedSize += addition ;
189204
@@ -197,6 +212,13 @@ private void handleBatch(HttpServletResponse resp, JsonNode rootNode, int maxRes
197212 batchResult .add (responseNode );
198213 }
199214
215+ // JSON-RPC 2.0 §6: MUST NOT return an empty Array when there are no response objects.
216+ if (batchResult .isEmpty ()) {
217+ resp .setStatus (HttpServletResponse .SC_OK );
218+ resp .setContentLength (0 );
219+ return ;
220+ }
221+
200222 byte [] finalBytes = MAPPER .writeValueAsBytes (batchResult );
201223 resp .setContentType ("application/json; charset=utf-8" );
202224 resp .setStatus (HttpServletResponse .SC_OK );
@@ -215,8 +237,7 @@ private byte[] readBody(InputStream in) throws IOException {
215237 return buffer .toByteArray ();
216238 }
217239
218- private void writeJsonRpcError (HttpServletResponse resp , JsonRpcError error , String message ,
219- JsonNode id , boolean isBatch ) throws IOException {
240+ private ObjectNode buildErrorNode (JsonRpcError error , String message , JsonNode id ) {
220241 ObjectNode errorObj = MAPPER .createObjectNode ();
221242 errorObj .put ("jsonrpc" , "2.0" );
222243 ObjectNode errNode = errorObj .putObject ("error" );
@@ -227,6 +248,12 @@ private void writeJsonRpcError(HttpServletResponse resp, JsonRpcError error, Str
227248 } else {
228249 errorObj .putNull ("id" );
229250 }
251+ return errorObj ;
252+ }
253+
254+ private void writeJsonRpcError (HttpServletResponse resp , JsonRpcError error , String message ,
255+ JsonNode id , boolean isBatch ) throws IOException {
256+ ObjectNode errorObj = buildErrorNode (error , message , id );
230257 byte [] bytes ;
231258 if (isBatch ) {
232259 ArrayNode arr = MAPPER .createArrayNode ();
0 commit comments