1

I tried to create a simple application with a geometry persistent layer (Spring boot with hibernate-spatial)

Here is my Entity class :

// Annotations from lombok project
@NoArgsConstructor 
@AllArgsConstructor
@Data 
@Builder
@Entity
@Table(name = "persistent_geometry")
public class PersistentGeometry implements Serializable {
    @Id
    @GeneratedValue(generator = "uuid2")
    @GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator")
    @Column(name = "id", columnDefinition = "VARCHAR(255)")
    private UUID id;

    @JsonSerialize(using = GeometrySerializer.class)
    @JsonDeserialize(using = GeometryDeserializer.class)
    @Column(name = "geometry", columnDefinition = "geometry(Polygon,4326)")
    private Polygon geometry;

}

Here is my repository interface

public interface PersistentGeometryService extends CrudRepository<PersistentGeometry, UUID> {}

Here is my controller class

@RestController public class PersistenGeometryController {

@Autowired
private PersistentGeometryService persistentGeometryService;

@PostMapping(value="/persistentGeometry")
public ResponseEntity createNewGeom(@RequestBody PersistentGeometry persistentGeometry) {
    PersistentGeometry newGeom = persistentGeometryService.save(persistentGeometry);
    var headers = new HttpHeaders();
    headers.add("Location", "/persistentGeometry/" + newGeom.getId().toString() );
    return new ResponseEntity(headers, HttpStatus.CREATED);
}

}

However, when i do a POST request with this payload :

{
"geometry" : "POLYGON((<Some Coordinates here>))"
}

Or its GeoJSON version :

    {
    "geometry" : {"type":"Polygon","coordinates":[[[<Some Coordinates here>]]]}
}

I got this error from my spring app (com.geomdemo.peristentgeometry is my base package name) :

Failed to evaluate Jackson deserialization for type [[simple type, class com.geomdemo.peristentgeometry.model.PersistentGeometry]]:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.bedatadriven.jackson.datatype.jts.serialization.GeometryDeserializer': Unsatisfied dependency expressed through constructor parameter 0;

nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.bedatadriven.jackson.datatype.jts.parsers.GeometryParser<?>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

Failed to evaluate Jackson deserialization for type [[simple type, class com.geomdemo.peristentgeometry.model.PersistentGeometry]]:

com.fasterxml.jackson.databind.JsonMappingException: Class com.bedatadriven.jackson.datatype.jts.serialization.GeometryDeserializer has no default (no arg) constructor

I found a suggestion here to add a @Bean of type JtsModule so I did this :

    @Configuration
    public class JacksonConfig {

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

But it didnt help in my case....It seems clear that SPring boot is looking for a valid Beans of type GeometryParser...But How to implement such a Bean...did not found any documentation or example on how to perform this.

EDIT : Some useful information :

the GeometryDeserializer is a class from package com.bedatadriven.jackson.datatype.jts.serialization package.

And here is the source code of this class :

package com.bedatadriven.jackson.datatype.jts.serialization;

import com.bedatadriven.jackson.datatype.jts.parsers.GeometryParser;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.vividsolutions.jts.geom.Geometry;
import java.io.IOException;

public class GeometryDeserializer<T extends Geometry> extends JsonDeserializer<T> {
    private GeometryParser<T> geometryParser;

    public GeometryDeserializer(GeometryParser<T> geometryParser) {
        this.geometryParser = geometryParser;
    }

    public T deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        ObjectCodec oc = jsonParser.getCodec();
        JsonNode root = (JsonNode)oc.readTree(jsonParser);
        return this.geometryParser.geometryFromJson(root);
    }
}

So from here is clear that it needs an interface of type GeometryParser<T>.

Now here is the interface GeometryParser :

package com.bedatadriven.jackson.datatype.jts.parsers;

import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.vividsolutions.jts.geom.Geometry;

public interface GeometryParser<T extends Geometry> {
    T geometryFromJson(JsonNode var1) throws JsonMappingException;
}

Seems pretty straight forward....but creating this method "geometryFromJson" is not so simple, and even before i think about it, i am quite sure that this is not the way to implement this stuff and there must be an existing implementation somewhere that i missed.

Btw, as asked in comments : here is my pom.xml file.

  • What's in the GeometrySerializer class? Did you include jts jar in your build? – Ian Turton Jun 14 at 18:39
  • @IanTurton : Thanks for your comment. I updated my post with some usefull details. Does this answers to your 2 questions ? – yAzou Jun 14 at 19:02
  • 1
  • @IanTurton Thanks for the link. I already mentionned it in my post (and tried that way) but did not help.... – yAzou Jun 15 at 8:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.