1

I am trying to implement a simple geometry (GIS) controller with PostGIS database in Spring-Boot 2.2.1.

When I try to de-serialize my task entity which contains the Point Geometry I am getting error:

There was an unexpected error (type=Internal Server Error, status=500).
Could not write JSON: org.locationtech.jts.geom.Point cannot be cast to com.vividsolutions.jts.geom.Geometry; nested exception is com.fasterxml.jackson.databind.JsonMappingException: org.locationtech.jts.geom.Point cannot be cast to com.vividsolutions.jts.geom.Geometry `enter code here`(through reference chain: java.util.ArrayList[0]->com.example.depdev.entity.Task["location"])

My task entity is :

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import com.bedatadriven.jackson.datatype.jts.serialization.GeometryDeserializer;
import com.bedatadriven.jackson.datatype.jts.serialization.GeometrySerializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.locationtech.jts.geom.Point;

@Entity
@Table(name = "task")
public class Task {

public Task () {
};

@Id
private Long id;
private String title;
@Column(columnDefinition = "geometry(Point,4326)")
@JsonSerialize(using = GeometrySerializer.class)
@JsonDeserialize(using = GeometryDeserializer.class)
private Point location;

// trimmed

I have tried to define location as both a point and a geometry but the error is the same.

My controller is able to persist a new task, but I get the previously posted error when I try to de-serialize it:

@GetMapping("/alltasks")
@ResponseBody
public List allTasks() throws JsonProcessingException {

    GeometryFactory gf = new GeometryFactory();
    Double y = -36.829;
    Double x = 174.896;

    Task testTask = new Task();
    testTask.setId(new Long(01));
    testTask.setTitle("Test Task");
    Point p = gf.createPoint(new Coordinate(x, y));
    p.setSRID(4326);
    testTask.setLocation(p);
    taskRepository.save(testTask);

    List<Task> listTasks = new ArrayList<>();
    listTasks = taskService.findAll();
    return listTasks;

I did have the recursion error that is posted here - but adding the JacksonConfig class has fixed this error.

For the sake of completeness here is the Jackson config class:

import com.bedatadriven.jackson.datatype.jts.JtsModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JacksonConfig {
    @Bean
    public JtsModule jtsModule() {
        return new JtsModule();
    }
}

My dependencies in my build.gradle is:

dependencies {
implementation 'org.hibernate:hibernate-spatial'
compile group: 'org.locationtech.jts', name: 'jts-core', version: '1.16.0'
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.10.0'
compile group: 'com.bedatadriven', name: 'jackson-datatype-jts', version: '2.4'
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-data-ldap'
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'org.postgresql:postgresql'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
    exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
testImplementation 'org.springframework.security:spring-security-test'

What do I need to do to get the task entity to JSON without this error?

UPDATE

There is no reference in my code to vividsolutions:

enter image description here

Al Grant
  • 2,102
  • 1
  • 26
  • 49
  • To me it looks like you are mixing locationtech and JTS geometries. Is this deliberate? Check bedatadriven JTS. It looks like that it transitively still uses the outdated JTS jar and namespace – Georg Heiler Dec 11 '19 at 18:33
  • Indeed not in hour code. But most likely in the library you are using. – Georg Heiler Dec 11 '19 at 19:38

3 Answers3

2

As other pointed out there is a dependency still using the old version of point geometry (vividsolutions.geom rather than the newer locationtech).

Fortunately someone has branched jackson-databind. This branch will work with location tech :

https://mvnrepository.com/artifact/com.graphhopper.external/jackson-datatype-jts/0.10-2.5-1

Al Grant
  • 2,102
  • 1
  • 26
  • 49
  • This is a valid answer, it just helped me to fix my project that was using the old jackson-datatype-jts package which was working with vividsolutions JTS but not with locationtech JTS. – Karl.S Feb 26 '20 at 21:31
  • I had to switch from `org.opengeo:geodb` to `org.orbisgis:h2gis` because `repo.boundlessgis.com` doesn't work anymore, and because the latest version of `h2gis` uses `org.locationtech` instead of `com.vividsolutions` was running into this problem. This answer got the latest version of `h2gis` working for me in Spring Boot/Hibernate – Benjamin Vogler Apr 12 '20 at 02:37
0

The 3-rd party library which contains custom JTS Jackson serializers is still transitively using the old version.

As the vividsolutions namespace was translated to locationtech you get the runtime exception.

Consider to create a custom serializer which accepted the new locationtech geometries.

Georg Heiler
  • 16,916
  • 36
  • 162
  • 292
0

In 2020 for me this was the only solution for Hibernate 2.4 + locationtech + spring boot 2.2.6. Go back hibernate version like this post Spring data JPA and Geometry type

Jesromled
  • 31
  • 3