javaspring-bootpostgishibernate-spatial

org.postgresql.util.PSQLException: ERROR: Invalid endian flag value encountered


I have consulted a lot of questions and I still can't find the solution to my problem.

I am doing an application and some of the classes have attributes of the geometry or point type, but when doing persistence tests, everything goes well until I try to save a point.

I want to add that I need to use this type of geometry (import org.locationtech.jts.geom.Point;) and all the solutions I find is with the type (import com.vividsolutions.jts.geom.Point;)

I think the problem is when it comes to serializer, I have one that should work fine but a function gives me an error.

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    <repositories>
        <repository>
            <id>osgeo</id>
            <name>Geotools repository</name>
            <url>http://download.osgeo.org/webdav/geotools</url>
        </repository>
    </repositories>

    <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-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-spatial</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.locationtech.jts</groupId>
            <artifactId>jts-core</artifactId>
            <version>1.16.1</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-geojson</artifactId>
            <version>2.7.3</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>



</project>

aplication.properties

    ## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url=jdbc:postgresql://localhost:5432/demo
spring.datasource.username= asi
spring.datasource.password= asi

# The SQL dialect makes Hibernate generate better SQL for the chosen database
#spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect

#hibernate.dialect=org.hibernate.spatial.dialect.postgis.PostgisDialect
spring.jpa.properties.hibernate.dialect=org.hibernate.spatial.dialect.postgis.PostgisDialect
#spring.jpa.properties.hibernate.dialect=org.hibernate.spatial.dialect.postgis.PostgisPG95Dialect

spring.jpa.hibernate.ddl-auto = create
spring.datasource.driverClassName=org.postgresql.Driver
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
spring.jpa.show-sql = true

"Test" the dao works fine cause only fails at geometry types.

Location l = new Location();
        Point p = geometryFactory.createPoint(new Coordinate(2,4));
        p.setSRID(SRID);
        l.setPosition(p);
        daol.create(l);

Location Class

import java.util.Calendar;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;

import org.locationtech.jts.geom.Point;

import es.udc.fic.model.util.CustomGeometryDeserializer;
import es.udc.fic.model.util.CustomGeometrySerializer;


@Entity
public class Location {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "loc_generator")
    @SequenceGenerator(name = "loc_generator", sequenceName = "loc_seq")
    private Long id;

    private String provider;

    private Calendar time;

//  @JsonSerialize(using = CustomGeometrySerializer.class)
//  @JsonDeserialize(using = CustomGeometryDeserializer.class)
    @Column(columnDefinition = "geometry(Point,4326)")
    private Point position;

This serializer is supposed to work, but it gives me an error in the function mentioned (The method write (Geometry, Object) in the type GeometryJSON is not applicable for the arguments (Geometry, StringWriter))

 import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;

import org.geotools.geojson.geom.GeometryJSON;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.locationtech.jts.geom.Geometry;

public class CustomGeometrySerializer extends JsonSerializer<Geometry> {

    private static GeometryJSON gjson = new GeometryJSON(8);

    public String serialize(Geometry value) {

        StringWriter writer = new StringWriter();
        /*
         try {
            gjson.write(value, writer);
        } catch (IOException e) {
        }*/
        return writer.toString();

    }

    @Override
    public void serialize(Geometry value, JsonGenerator gen, SerializerProvider serializers)
            throws IOException, JsonProcessingException {

        StringWriter writer = new StringWriter();
        // gjson.write(value, writer);
        gen.writeRawValue(writer.toString());
    }
}

Error trace

org.postgresql.util.PSQLException: ERROR: Invalid endian flag value encountered.
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2440) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2183) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:308) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:441) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:365) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:143) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:120) ~[postgresql-42.2.5.jar:42.2.5]
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61) ~[HikariCP-3.2.0.jar:na]
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java) ~[HikariCP-3.2.0.jar:na]
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:175) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3174) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3688) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:90) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:478) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:356) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1453) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:510) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3282) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2478) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:473) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]
at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:178) ~[hibernate-core-5.3.9.Final.jar:5.3.9.Final]


Solution

  • Finally I have not found the solution for locationtech geometry, maybe it is because it is newer than vividsolutions and with vividsolutions everything works correctly so my solving was using vividsolutions instead of locationtech.

    Another fact that I have found and was wrong is that the serializer (which does not fail to change to vividsolutions) has nothing to do with the database, that is what hibernate is exclusively responsible for.