After the postgis package was introduced, an HttpMessageConversionException exception occurred in the business code. After being handled by the unified exception, the json format of the output parameter was incorrect
pom.xml
<?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>2.7.13-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>resultError</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>resultError</name>
<description>resultError</description>
<properties>
<java.version>1.8</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-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>net.postgis</groupId>
<artifactId>postgis-jdbc</artifactId>
<version>2021.1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</pluginRepository>
</pluginRepositories>
</project>
TestController
package com.example.result.controller;
import com.alibaba.fastjson.JSON;
import com.example.result.test.Result;
import net.postgis.jdbc.PGgeometry;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* test
*
* @author Lin
* @version 3.3.0
* @since 2023-06-19 11:08:48
*/
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/1")
public Result<PGgeometry> test1() {
String geomJSON = "{\"geoType\":5,\"geometry\":{\"dimension\":2,\"empty\":false,\"firstPoint\":{\"dimension\":2,\"firstPoint\":{\"$ref\":\"@\"},\"haveMeasure\":false,\"lastPoint\":{\"$ref\":\"@\"},\"m\":0.0,\"measured\":false,\"srid\":4545,\"type\":1,\"typeString\":\"POINT\",\"value\":\"(518545.4160000002 2500445.7579999994)\",\"x\":518545.4160000002,\"y\":2500445.7579999994,\"z\":0.0},\"haveMeasure\":false,\"lastPoint\":{\"dimension\":2,\"firstPoint\":{\"$ref\":\"@\"},\"haveMeasure\":false,\"lastPoint\":{\"$ref\":\"@\"},\"m\":0.0,\"measured\":false,\"srid\":4545,\"type\":1,\"typeString\":\"POINT\",\"value\":\"(518629.8839999996 2500523.7479999997)\",\"x\":518629.8839999996,\"y\":2500523.7479999997,\"z\":0.0},\"lines\":[{\"dimension\":2,\"empty\":false,\"firstPoint\":{\"$ref\":\"$.geometry.firstPoint\"},\"haveMeasure\":false,\"lastPoint\":{\"$ref\":\"$.geometry.lastPoint\"},\"measured\":false,\"points\":[{\"$ref\":\"$.geometry.firstPoint\"},{\"$ref\":\"$.geometry.lastPoint\"}],\"srid\":4545,\"type\":2,\"typeString\":\"LINESTRING\",\"value\":\"(518545.4160000002 2500445.7579999994,518629.8839999996 2500523.7479999997)\"}],\"measured\":false,\"srid\":4545,\"type\":5,\"typeString\":\"MULTILINESTRING\",\"value\":\"((518545.4160000002 2500445.7579999994,518629.8839999996 2500523.7479999997))\"},\"null\":false,\"type\":\"geometry\",\"value\":\"SRID=4545;MULTILINESTRING((518545.4160000002 2500445.7579999994,518629.8839999996 2500523.7479999997))\"}";
PGgeometry pGgeometry = JSON.parseObject(geomJSON, PGgeometry.class);
return Result.ok(pGgeometry);
}
@GetMapping("/2")
public Result<PGgeometry> test2() {
return Result.ok(new PGgeometry());
}
@GetMapping("/3")
public Result<Map<String, Object>> test3() {
String geomJSON = "{\"geoType\":5,\"geometry\":{\"dimension\":2,\"empty\":false,\"firstPoint\":{\"dimension\":2,\"firstPoint\":{\"$ref\":\"@\"},\"haveMeasure\":false,\"lastPoint\":{\"$ref\":\"@\"},\"m\":0.0,\"measured\":false,\"srid\":4545,\"type\":1,\"typeString\":\"POINT\",\"value\":\"(518545.4160000002 2500445.7579999994)\",\"x\":518545.4160000002,\"y\":2500445.7579999994,\"z\":0.0},\"haveMeasure\":false,\"lastPoint\":{\"dimension\":2,\"firstPoint\":{\"$ref\":\"@\"},\"haveMeasure\":false,\"lastPoint\":{\"$ref\":\"@\"},\"m\":0.0,\"measured\":false,\"srid\":4545,\"type\":1,\"typeString\":\"POINT\",\"value\":\"(518629.8839999996 2500523.7479999997)\",\"x\":518629.8839999996,\"y\":2500523.7479999997,\"z\":0.0},\"lines\":[{\"dimension\":2,\"empty\":false,\"firstPoint\":{\"$ref\":\"$.geometry.firstPoint\"},\"haveMeasure\":false,\"lastPoint\":{\"$ref\":\"$.geometry.lastPoint\"},\"measured\":false,\"points\":[{\"$ref\":\"$.geometry.firstPoint\"},{\"$ref\":\"$.geometry.lastPoint\"}],\"srid\":4545,\"type\":2,\"typeString\":\"LINESTRING\",\"value\":\"(518545.4160000002 2500445.7579999994,518629.8839999996 2500523.7479999997)\"}],\"measured\":false,\"srid\":4545,\"type\":5,\"typeString\":\"MULTILINESTRING\",\"value\":\"((518545.4160000002 2500445.7579999994,518629.8839999996 2500523.7479999997))\"},\"null\":false,\"type\":\"geometry\",\"value\":\"SRID=4545;MULTILINESTRING((518545.4160000002 2500445.7579999994,518629.8839999996 2500523.7479999997))\"}";
PGgeometry pGgeometry = JSON.parseObject(geomJSON, PGgeometry.class);
Map<String, Object> pipelineMap = new HashMap<>();
pipelineMap.put("geom", pGgeometry);
return Result.ok(pipelineMap);
}
}
demo file
Comment From: shivraj-web
Hi, can i take this?
Comment From: linwumingshi
Hi, can i take this?
Of course
Comment From: wilkinsona
@Lin222 thanks for the sample but I'm afraid I don't understand what the problem is. You have said that "the json format of the output parameter was incorrect". In what way is it incorrect? In the screenshot you have highlighted "z": 0.0
but this looks correct to me based on the json in your test controller. Can you please provide examples, in text rather than screenshots, of the responses that you expect to receive?
Comment From: linwumingshi
@Lin222 thanks for the sample but I'm afraid I don't understand what the problem is. You have said that "the json format of the output parameter was incorrect". In what way is it incorrect? In the screenshot you have highlighted
"z": 0.0
but this looks correct to me based on the json in your test controller. Can you please provide examples, in text rather than screenshots, of the responses that you expect to receive?
Thank you for your reply. In the first example, jackson serializes the object PGgeometry with an error. In this case, the expected output should be like this. (It works in SpringBoot 2.3.12.RELEASE)
{
"success": false,
"code": "9999",
"message": "error result",
"data": null
}
But now the output is
{
"success": true,
"code": "0000",
"message": "success!",
"data": {
"type": "geometry",
"value": "SRID=4545;MULTILINESTRING((518545.4160000002 2500445.7579999994,518629.8839999996 2500523.7479999997))",
"geometry": {
"dimension": 2,
"haveMeasure": false,
"type": 5,
"srid": 4545,
"lines": [
{
"dimension": 2,
"haveMeasure": false,
"type": 2,
"srid": 0,
"points": [
{
"dimension": 2,
"haveMeasure": false,
"type": 1,
"srid": 0,
"x": 518545.4160000002,
"y": 2500445.7579999994,
"z": 0.0,
"m": 0.0
}
]
}
]
}
}
}{
"success": false,
"code": "9999",
"message": "error result",
"data": null
}
Comment From: wilkinsona
Thanks. I understand the problem now. A partial successful response is being written to the response body before the exception occurs. An additional unsuccessful response is then written using the exception handler's return value.
You can avoid the problem by resetting the response in the exception handler:
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.OK)
public Result<Object> handleException(HttpServletResponse response, Exception e) {
if (!response.isCommitted()) {
response.reset();
}
return Result.failed("error result");
}
I've been discussing this with @rstoyanchev and it may be possible for Spring MVC to perform this reset automatically. We'll transfer this issue to the Framework team so that they can take a further look.
Comment From: linwumingshi
Thanks. I understand the problem now. A partial successful response is being written to the response body before the exception occurs. An additional unsuccessful response is then written using the exception handler's return value.
You can avoid the problem by resetting the response in the exception handler:
java @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.OK) public Result<Object> handleException(HttpServletResponse response, Exception e) { if (!response.isCommitted()) { response.reset(); } return Result.failed("error result"); }
I've been discussing this with @rstoyanchev and it may be possible for Spring MVC to perform this reset automatically. We'll transfer this issue to the Framework team so that they can take a further look.
Thank you!
Comment From: bclozel
Closing in favor of #31104.