10

I try create web API with XML and JSON with Springboot 2.2.4.RELEASE + JDK11 and java 8 compilation.

my model:

@XmlRootElement
public class DataModel {

    private List<String> columns;

    private List<Row> rows;

    public List<String> getColumns() {
        return columns;
    }

    public void setColumns(List<String> columns) {
        this.columns = columns;
    }

    public List<Row> getRows() {
        return rows;
    }

    public void setRows(List<Row> rows) {
        this.rows = rows;
    }

}

my controller:

@RequestMapping(value = "/{model}/columns", method = RequestMethod.GET, consumes = MediaType.ALL_VALUE, produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<DataModel> getColumnsModel(@PathVariable String model) {
    LOGGER.info("getColumnsModel : model[{}]", model);
    DataModel dataModel = modelService.getColumns(model);
    return Optional.ofNullable(dataModel).map(result -> new ResponseEntity<>(result, HttpStatus.OK)).orElse(new ResponseEntity<>(HttpStatus.NO_CONTENT));
}

I use a curl:

curl -s -v --header "Accept: application/xml" http://localhost:8084/api/foo/columns

On my computer (windows 10) the result is OK.

* TCP_NODELAY set
* Connected to localhost (::1) port 8084 (#0)
> GET /noraui/api/hello/columns HTTP/1.1
> Host: localhost:8084
> User-Agent: curl/7.67.0
> Accept: application/xml
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: application/xml
< Transfer-Encoding: chunked
< Date: Tue, 03 Mar 2020 08:38:20 GMT
<
{ [254 bytes data]
* Connection #0 to host localhost left intact

My error on Unix plateform (travis-ci):

Resolved [org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class com.github.noraui.data.rest.DataModel] with preset Content-Type 'null']

< HTTP/1.1 500 
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Length: 0
< Date: Tue, 03 Mar 2020 08:41:28 GMT
< Connection: close
< 
* Closing connection 0
Stéphane GRILLON
  • 11,140
  • 10
  • 85
  • 154

8 Answers8

4

I have solved this problem by adding below dependency:

<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-xml</artifactId>
  <version>2.12.3</version>
</dependency>
Akshma Mittal
  • 69
  • 1
  • 5
2

I had a similar error but with JSON.

My problem happened because the POJO that I tried to convert to JSON had to properties with the same name

@JsonProperty("my_property")
[...]
@JsonProperty("my_property")  // duplicated property name in the same POJO.

After fixing the duplication,the object could be converted correctly.

Tk421
  • 6,196
  • 6
  • 38
  • 47
1

In my case, I was working on an existing api that was producing a PDF and had to change the response to JSON. I had forgot remove produces = "application/pdf"from the @GetMapping annotation.

Mohammed Siddiq
  • 477
  • 4
  • 16
0

Can you perform a test with Postman? I just did a test with Postman and worked fine. However, check the header of your request twice and make sure that it is right.

P.S.: I checked the project at github.com/NoraUi/noraui-datas-webservices and performed tests with the dependencies mentioned (jaxb-runtime and xerces) and those dependencies were not necessary at all. The @XmlRootElement annotation should be enough. I just submitted a personal project to my GitHub account. It is a cleaner example. Please, check it out: https://github.com/DavidGuimaraes/spring-security-basic

0

in my own special case, I was getting this error while trying to run integration tests for a Spring Boot controller class. I had suspicions that probably this happens because something is messed up with the runtime libraries / classloading because of the mocked Spring context - but I couldn't understand what is missing exactly.. I still cannot, and I wish someone could shed more light on this issue. I tried to convert to JSON myself and return a String, inside the body of the ResponseEntity, and this worked, given that I had to specify Jackson's ObjectMapper as one of the classes in SpringBootTest(classes = {...})..

so this worked:

ResponseMessage m = new ResponseMessage("haha");
ResponseEntity r = ResponseEntity.status(HttpStatus.OK).body(objectMapper.writeValueAsString(m));

but this didn't in the first place (which was my problem):

ResponseMessage m = new ResponseMessage("haha");
ResponseEntity r = ResponseEntity.status(HttpStatus.OK).body(m); // exception happens further while being processed by Spring

Exception:

mo.s.w.s.m.s.DefaultHandlerExceptionResolver.logException - Resolved [org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class gr.unisystems.ethemisid.view.model.response.ResponseMessage] with preset Content-Type 'null'] 
mo.s.t.w.s.TestDispatcherServlet.logResult - Completed 500 INTERNAL_SERVER_ERROR
hello_earth
  • 1,442
  • 1
  • 25
  • 39
  • Hi @hello_earth, I am currently facing the same issue. were you able to find the solution – The Reedemed77 Mar 01 '22 at 04:56
  • @TheReedemed77 i am uncomfortable to say, but my answer is no.. maybe setting the content type somehow on the ReponseEntity, apart from the status and body, would help? went on to other matters, since a workaround was found. – hello_earth Mar 01 '22 at 08:27
  • 1
    thank you. I ended up finding the solution. I was facing the issue in my test. I am using the Spock framework. The only change I made was to use WebMvcTest(SomeClassName) instead of SpringBootTest(SomeClassName). I'm also using SpringBean to inject the mock of other dependencies in this class – The Reedemed77 Mar 04 '22 at 04:34
0

This error can also occur sometimes when you try to return an entity but not the DTO of the entity which you might have created to act as say, the XMLRootElement for your actual entity, from your RestController method.

Either return nothing (void), or return the instance of the class which is properly annotated from the RestController's method.

I understand that this exception for the OP arose due to his lack of the proper dependency in his pom file. Nevertheless, the trick mentioned above is one of the ways you can counter this problem. Or perhaps, it was only me who had this careless problem. :'D

Your final code for the method can perhaps look something like this:

    @ResponseBody
    @ResponseStatus(HttpStatus.CREATED)
    @PostMapping(value = "/xml",
            consumes = MediaType.APPLICATION_XML_VALUE,
            produces = MediaType.APPLICATION_XML_VALUE)
    public void addPaymentXml(@RequestBody String paymentXml)
            throws IOException, SAXException {
        paymentService.createPaymentXml(paymentXml);
    }
0

Adding the 'toString()' method in the model class worked for me. (I used @Data Lombok annotation for this)

shiva
  • 2,535
  • 2
  • 18
  • 32
-1

Sometimes the problem is related to the object you want to return as JSON. Maybe you are missing constructors or some methods like getters, and so on. A Lombok @Data annotation on the returning class most probably fix the problem.

m.semnani
  • 637
  • 5
  • 10