Search code examples
javaspringpostgisjtshibernate-spatial

How to send PostGiS Geometry and Point data types through Spring Boot Rest API


I have an query that returns an interface OverlayDTO that I get from a native query. center is PostGIS point and geometry as you might have guessed it is geometry

@Query("SELECT " +
        "o.geometry as geometry, " +
        "o.center as center, " +
        "FROM Overlay o " +
        "WHERE  o.layer.id = :layerId")
List<OverlayDTO> getAllOverlays(long layerId);

Interface:

import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Point;

public interface OverlayDTO {
    Geometry getGeometry();
    Point getCenter();
}

I want to send it through REST API like this (if possible) (it should call a service and do some more logic, but this is the basic gist of it)

    @GetMapping(value="{layerId}")
public ResponseEntity<List<OverlayDTO>> getCompanyLayers(@PathVariable Long layerId) {
    List<OverlayDTO> overlays = mapRepository.getAllOverlays(layerId);
        
    return ResponseEntity.ok(overlays);
}

However, I get an error that Jackson was unable to map due to recursion.

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]->org.locationtech.jts.geom.Polygon["envelope"]

How could I fix this issue? Should I query data differently, or should I build my own DTO class and just send a POJO? Or do I need to build some serializer/deserializer?


Solution

  • You need to register a Jackson Module that provides appropriate serializers and deserializers for JTS Geometry objects. A good candidate is jackson-datatype-jts.

    If you want an example on how to do this, you could check out this blog post. (I wrote it using an alternative geometry library, but the approach should work with JTS and the jackson-datatype-jts module).