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

1.8k Views Asked by At

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?

2

There are 2 best solutions below

1
Karel Maesen On BEST ANSWER

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).

0
slambeth On

There is a common exchange format, GeoJSON. You would likely have to code JTS to do this, or PostGIS has functions to generate GeoJSON directly from your DB objects.

Another somewhat simpler approach is to convert your objects to WKT and return them in a String. Both PostGIS, and JTS can generate and convert from WKT. This may or may not be easier for other services to consume depending on the system making the call. The only annoying thing about WKT, is the SRID is assumed. I've created my services to have a parameter to request the SRID the client would like (this of course requires that you can convert to the SRID requested), or, make your services always return data in a de facto standard, like 4326.