Sreerej r.k
Sreerej r.k

Reputation: 41

Get both Mapping and Pain Json text in Spring Boot Restful webService

i am trying to parse json body request coming in for a post request using Spring Boot. I would like to map the body to fields on vehicle class and also to store plain json body to some variable as well for future use. But i am always getting stream closed exception when trying to access plain json body. Can someone help me out on this. Thanks In Advance

Code

@RequestMapping(value = "/GetDriverDetails", method = RequestMethod.POST)
public ResponseEntity<Vehicle> GetVehicleDetails(@RequestBody Vehicle vehicle, HttpServletRequest request) {
    System.out.println(vehicle);
    String json;
    if ("POST".equalsIgnoreCase(request.getMethod())) 
    {
      try {
          ContentCachingRequestWrapper request1 = new ContentCachingRequestWrapper(request);
        String collect = request1.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
        System.out.println(collect);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    }
    
    return new ResponseEntity<Vehicle>(HttpStatus.OK);
}

Json request Body

{
    "vehicleName": "Brio",
    "vehicleModel": "fisrtClass",
    "drivers": [
        {
            "name": "rej",
            "licenseNumber": "KLLicense1"
        },
        {
            "name": "Dan",
            "licenseNumber": "KLLicense2"
        },
        {
            "name": "bala",
            "licenseNumber": "KLLicense3"
        },
        {
            "name": "vijay",
            "licenseNumber": "KLLicense4"
        },
        {
            "name": "aravind",
            "licenseNumber": "KLLicense5"
        },
        {
            "name": "sathya",
            "licenseNumber": "KLLicense6"
        }
    ]
}

Exception

java.io.IOException: Stream closed at org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:359) ~[tomcat-embed-core-9.0.38.jar:9.0.38] at org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:132) ~[tomcat-embed-core-9.0.38.jar:9.0.38] at org.springframework.web.util.ContentCachingRequestWrapper$ContentCachingInputStream.read(ContentCachingRequestWrapper.java:254) ~[spring-web-5.2.9.RELEASE.jar:5.2.9.RELEASE] at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:297) ~[na:na] at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:339) ~[na:na] at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:188) ~[na:na] at java.base/java.io.InputStreamReader.read(InputStreamReader.java:181) ~[na:na]

Upvotes: 0

Views: 497

Answers (2)

silentsudo
silentsudo

Reputation: 6973

Can you try following code:

The solution to your main problem, since you are using @RequestBody, contents are already read and mapped to pojo class hence stream is utlized and closed in this case you do not want to use @RequestBody at all. Please find my implementation below:

 @PostMapping(path = "update-vehicle-details", consumes = MediaType.ALL_VALUE)
        public VehicleDriver updateVehicleDetails(HttpServletRequest request) throws IOException {
            ContentCachingRequestWrapper request1 = new ContentCachingRequestWrapper(request);
            String collect = request1.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
            System.out.println(collect);
            final VehicleDriver vehicleDriver = new ObjectMapper().readValue(collect, VehicleDriver.class);
            return vehicleDriver;
        }

Otherwise, use a simple approach, read the value from application json content type parses in requestbody and converts that body to string and return the same result

@RestController
    public static class TestController {

        @PostMapping(path = "update-vehicle-details", consumes = MediaType.APPLICATION_JSON_VALUE)
        public String updateVehicleDetails(@RequestBody VehicleDriver vehicleDriver) throws JsonProcessingException {
            final StringBuilder stringBuilder = new StringBuilder(vehicleDriver.vehicleName);
            List<String> driverDetails = Optional.ofNullable(
                    vehicleDriver.drivers)
                    .map(Collection::stream)
                    .orElse(Stream.empty())
                    .map(d -> "name=: " + d.name + ", license number:" + d.licenseNumber)
                    .collect(Collectors.toList());
            stringBuilder.append("\n");
            stringBuilder.append(driverDetails);
            String stringRepresentationOfBody = new ObjectMapper().writeValueAsString(vehicleDriver);
//            return stringBuilder.toString();
            return stringRepresentationOfBody;
        }

    }

    public static class VehicleDriver {
        public String vehicleName;
        public String vehicleModel;
        public List<Driver> drivers;
    }

    public static class Driver {
        public String name;
        public String licenseNumber;
    }

Upvotes: 1

Heena Tabassum
Heena Tabassum

Reputation: 128

Try using Object Mapper for converting your vehicle object to json string and in that case you would not be needing request in method argument. And you are using post request method then if condition is not needed.

Upvotes: 0

Related Questions