Spring-boot: failed convert data to JSON when using data-rest

Created on 14 Jul 2017  Â·  8Comments  Â·  Source: spring-projects/spring-boot

Build spring boot demo with spring-boot-starter-data-rest,when I request http://localhost:8080/dicts via GET, it complain:

2017-07-14 08:43:15.628  WARN 8736 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: java.lang.String cannot be cast to java.lang.Integer; nested exception is com.fasterxml.jackson.databind.JsonMappingException: java.lang.String cannot be cast to java.lang.Integer (through reference chain: org.springframework.hateoas.PagedResources["_embedded"]->java.util.Collections$UnmodifiableMap["dicts"]->java.util.ArrayList[0]->org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$PersistentEntityResourceSerializer$1["content"]->com.etongdai.hotleave.domain.Dict["name"])
2017-07-14 08:43:15.628  WARN 8736 --- [nio-8080-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: java.lang.String cannot be cast to java.lang.Integer; nested exception is com.fasterxml.jackson.databind.JsonMappingException: java.lang.String cannot be cast to java.lang.Integer (through reference chain: org.springframework.hateoas.PagedResources["_embedded"]->java.util.Collections$UnmodifiableMap["dicts"]->java.util.ArrayList[0]->org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$PersistentEntityResourceSerializer$1["content"]->com.etongdai.hotleave.domain.Dict["name"])

My efforts

  • when I change the field order of Dict class, it will cause other class cast error

  • when I change the type of sortNumber to String, it will be OK

Env

spring-boot version: 2.0.0.M2
jdk version: jdk 1.8.0_111
OS: win 10 home edition

Sample Code

Entity

package com.etongdai.hotleave.domain;

import javax.persistence.*;

/**
 * Created by hotleave on 2017/7/13.
 */
@Entity
@Table(name = "T_DICT")
public class Dict {
    @Id
    @GeneratedValue
    private Long id;

    @Column(nullable = false, length = 20)
    private String category;

    @Column(length = 20, nullable = false)
    private String code;

    @Column(length = 50, nullable = false)
    private String name;

    @Column(nullable = false)
    private Integer sortNumber;

    private String description;

    public Dict() {
    }

    public Dict(String category, String code, String value, Integer sortNumber) {
        this.category = category;
        this.code = code;
        this.name = value;
        this.sortNumber = sortNumber;
    }

    public Dict(String category, String code, String value, Integer sortNumber, String description) {
        this(category, code, value, sortNumber);

        this.description = description;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getSortNumber() {
        return sortNumber;
    }

    public void setSortNumber(Integer sortNumber) {
        this.sortNumber = sortNumber;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

Repository

package com.etongdai.hotleave.domain;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;

/**
 * Created by hotleave on 2017/7/13.
 */
@Repository
public interface DictRepository extends JpaRepository<Dict, Long>, JpaSpecificationExecutor<Dict> {
}

data.sql

insert into T_DICT (id, category, code, name, sort_number, description) values (1, 'gender', 'male', '男', 1, '性别-男');
insert into T_DICT (id, category, code, name, sort_number, description) values (2, 'gender', 'female', '女', 2, '性别-女');

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.etongdai.hotleave</groupId>
    <artifactId>springbootdemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>springbootdemo</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.0.M2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
        <pluginRepository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>


</project>
invalid

Most helpful comment

This issue was caused by a downstream change in Jackson 2.9 (see FasterXML/jackson-databind#1664). We were able to work around this with the fix for DATAREST-1060, which will be included in all maintained Spring Data releases, which in turn means that both Boot 1.5 (assuming you're using that with Jackson 2.9 in the first place) and 2.0 will automatically pick up the fix.

All 8 comments

Thanks for getting in touch, but it feels like this is a question that would be better suited to Stack Overflow. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements. Feel free to update this issue with a link to the re-posted question (so that other people can find it) or add some more details if you feel this is a genuine bug.

Actually, chatting with @wilkinsona, that looks like a bug in spring-data-rest. Perhaps @olivergierke has more insight about it?

@hotleave rather than pasting the whole content of your sample project in text, can you please share the url to a repo (or a zip) that we can extract and run? In order to reproduce your issue, we'll have to do all of that anyway.

Sorry for the long time response.

Here is the project
springbootdemo.zip

mvn package -DskipTests=true
cd target
java -jar springbootdemo.jar

curl http://localhost:8080/dicts

Hi @hotleave

Just wondering if you got a solution for this issue?

Thank you
Damien

@hotleave Thanks for the sample. I've reproduced the problem with Spring Boot 2.0.0.M2. Upgrading to Spring Boot 2.0.0 snapshots (and therefore Spring Data Kay snapshots) resolves the issue.

I receive this response:

$ curl localhost:8080/dicts
{
  "_embedded" : {
    "dicts" : [ {
      "category" : "gender",
      "code" : "male",
      "name" : "ç”·",
      "sortNumber" : 1,
      "description" : "性别-男",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/dicts/1"
        },
        "dict" : {
          "href" : "http://localhost:8080/dicts/1"
        }
      }
    }, {
      "category" : "gender",
      "code" : "female",
      "name" : "女",
      "sortNumber" : 2,
      "description" : "性别-女",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/dicts/2"
        },
        "dict" : {
          "href" : "http://localhost:8080/dicts/2"
        }
      }
    } ]
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/dicts{?page,size,sort}",
      "templated" : true
    },
    "profile" : {
      "href" : "http://localhost:8080/profile/dicts"
    }
  },
  "page" : {
    "size" : 20,
    "totalElements" : 2,
    "totalPages" : 1,
    "number" : 0
  }
}

Hi @wilkinsona

This also resolved the issue for me.
Just wondering is there any other issues created that we can follow to ensure this item gets fixed in a future build?

Thanks
Damien

This issue was caused by a downstream change in Jackson 2.9 (see FasterXML/jackson-databind#1664). We were able to work around this with the fix for DATAREST-1060, which will be included in all maintained Spring Data releases, which in turn means that both Boot 1.5 (assuming you're using that with Jackson 2.9 in the first place) and 2.0 will automatically pick up the fix.

OK, thank you for your feedback, I will waiting for 2.0 release

Was this page helpful?
0 / 5 - 0 ratings