Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hibernate spatial with PostGIS failing when running in native #505

Open
loonis opened this issue Jun 26, 2024 · 1 comment
Open

Hibernate spatial with PostGIS failing when running in native #505

loonis opened this issue Jun 26, 2024 · 1 comment
Labels
enhancement New feature or request

Comments

@loonis
Copy link

loonis commented Jun 26, 2024

Describe the bug

Hibernate spatial is failing when running in native image.

To Reproduce

Create a spring boot 3.3.1 project using hibernate-spatial

<?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>3.3.1</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<groupId>com.test</groupId>
	<artifactId>test</artifactId>


	<version>0.0.1-SNAPSHOT</version>
	<name>test</name>
	<description>Demo project for Spring Boot</description>


	<properties>
		<java.version>21</java.version>
		<org.mapstruct.version>1.5.5.Final</org.mapstruct.version>
		<graphql-java-extended-scalars.version>22.0</graphql-java-extended-scalars.version>
		<hibernate.version>6.5.2.Final</hibernate.version>
	</properties>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>com.google.cloud</groupId>
				<artifactId>spring-cloud-gcp-dependencies</artifactId>
				<version>5.4.1</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<dependencies>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-graphql</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
		</dependency>

		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<scope>runtime</scope>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>

		<dependency>
			<groupId>com.graphql-java</groupId>
			<artifactId>graphql-java-extended-scalars</artifactId>
			<version>${graphql-java-extended-scalars.version}</version>
		</dependency>

		<dependency>
			<artifactId>mapstruct</artifactId>
			<groupId>org.mapstruct</groupId>
			<version>${org.mapstruct.version}</version>
		</dependency>

		<dependency>
			<groupId>org.hibernate.orm</groupId>
			<artifactId>hibernate-spatial</artifactId>
			<version>${hibernate.version}</version>
		</dependency>

		<dependency>
			<groupId>com.google.cloud</groupId>
			<artifactId>spring-cloud-gcp-starter-sql-postgresql</artifactId>
		</dependency>


<!--		TESTS-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webflux</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.graphql</groupId>
			<artifactId>spring-graphql-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>${maven-compiler-plugin.version}</version>
				<executions>
					<execution>
						<id>default-compile</id>
						<phase>compile</phase>
						<goals>
							<goal>compile</goal>
						</goals>
					</execution>
					<execution>
						<id>default-testCompile</id>
						<phase>test-compile</phase>
						<goals>
							<goal>testCompile</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<annotationProcessorPaths>
						<path>
							<artifactId>mapstruct-processor</artifactId>
							<groupId>org.mapstruct</groupId>
							<version>${org.mapstruct.version}</version>
						</path>
						<path>
							<artifactId>lombok</artifactId>
							<groupId>org.projectlombok</groupId>
							<version>${lombok.version}</version>
						</path>

						<path>
							<groupId>org.hibernate.orm</groupId>
							<artifactId>hibernate-jpamodelgen</artifactId>
							<version>${hibernate.version}</version>
						</path>


					</annotationProcessorPaths>
					<source>${java.version}</source>
					<target>${java.version}</target>
				</configuration>
			</plugin>

			<plugin>
				<groupId>io.github.deweyjose</groupId>
				<artifactId>graphqlcodegen-maven-plugin</artifactId>
				<version>1.61.0</version>
				<executions>
					<execution>
						<id>dgs-codegen</id>
						<phase>generate-sources</phase>
						<goals>
							<goal>generate</goal>
						</goals>
						<configuration>
							<schemaPaths>
								<param>src/main/resources/graphql</param>
							</schemaPaths>
							<packageName>com.kc.dto</packageName>
							<addGeneratedAnnotation>true</addGeneratedAnnotation>
							<generateClientApiV2>false</generateClientApiV2>
							<generateDataTypes>true</generateDataTypes>

							<onlyGenerateChanged>false</onlyGenerateChanged>
							<addGeneratedAnnotation>true</addGeneratedAnnotation>
						</configuration>
					</execution>
				</executions>
			</plugin>

			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>build-helper-maven-plugin</artifactId>
				<executions>
					<execution>
						<id>add-dgs-source</id>
						<phase>generate-sources</phase>
						<goals>
							<goal>add-source</goal>
						</goals>
						<configuration>
							<sources>
								<source>${project.build.directory}/generated-sources</source>
							</sources>
						</configuration>
					</execution>
				</executions>
			</plugin>

			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<executions>
					<execution>
						<goals>
							<goal>build-image</goal>
						</goals>
					</execution>
				</executions>



				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>

			<plugin>
				<groupId>org.hibernate.orm.tooling</groupId>
				<artifactId>hibernate-enhance-maven-plugin</artifactId>
				<version>${hibernate.version}</version>
				<executions>
					<execution>
						<configuration>
							<failOnError>true</failOnError>
							<enableLazyInitialization>true</enableLazyInitialization>
						</configuration>
						<goals>
							<goal>enhance</goal>
						</goals>
					</execution>
				</executions>
			</plugin>

			<plugin>
				<groupId>org.graalvm.buildtools</groupId>
				<artifactId>native-maven-plugin</artifactId>
			</plugin>

		</plugins>
	</build>
</project>
spring:
  jpa:
    properties:
      hibernate:
        format_sql=true:
    defer-datasource-initialization: true
    hibernate:
      ddl-auto: none

One of my entity contains a field org.locationtech.jts.geom.Point; which is a PostGIS GEOGRAPHY(POINT, 4326),

I filter my entities based on these gps coordinates

      org.locationtech.jts.geom.GeometryFactory geometryFactory = new GeometryFactory();
      org.locationtech.jts.geom.Point refPoint = geometryFactory.createPoint(new Coordinate(latitude, longitude));
      refPoint.setSRID(4326);

      jakarta.persistence.criteria.Predicate distancePredicate = cb.equal(cb.literal(true), cb.function(
          "ST_DWithin",
          Boolean.class,
          root.get("location"),
          cb.literal(refPoint),
          cb.literal(radiusMeter)
      ));

The native image generation is working, but then running the executable will generate these error log bellow.

Error 1

Caused by: java.lang.NoClassDefFoundError: Could not initialize class org.geolatte.geom.crs.CrsRegistry
        at org.geolatte.geom.jts.JTS.determineCrsFromCoordinatesAndSrid(JTS.java:163) ~[na:na]
        at org.geolatte.geom.jts.JTS.from(JTS.java:126) ~[na:na]
        at org.hibernate.spatial.JTSGeometryJavaType.unwrap(JTSGeometryJavaType.java:102) ~[na:na]
        at org.hibernate.spatial.JTSGeometryJavaType.unwrap(JTSGeometryJavaType.java:37) ~[na:na]

Error2

Caused by: java.lang.InstantiationException: org.geolatte.geom.codec.PostgisWkbDecoder
        at [email protected]/java.lang.Class.newInstance(DynamicHub.java:719) ~[com.kc.KnightclubbersApplication:na]
        at org.geolatte.geom.codec.Wkb.createInstance(Wkb.java:222) ~[na:na]
        ... 64 common frames omitted
Caused by: java.lang.NoSuchMethodException: org.geolatte.geom.codec.PostgisWkbDecoder.<init>()
        at [email protected]/java.lang.Class.checkMethod(DynamicHub.java:1078) ~[com.kc.KnightclubbersApplication:na]
        at [email protected]/java.lang.Class.getConstructor0(DynamicHub.java:1241) ~[com.kc.KnightclubbersApplication:na]
        at [email protected]/java.lang.Class.newInstance(DynamicHub.java:706) ~[com.kc.KnightclubbersApplication:na]
        ... 65 common frames omitted

Error 3

Caused by: java.lang.IllegalStateException: Can't find spatial_ref_sys definitions.
        at org.geolatte.geom.crs.CrsRegistry.createReader(CrsRegistry.java:80) ~

I followed the indication given here: #233 (comment) which solves some problems, but not theses ones.

System Info

OS: Windows 11
GraalVM Version 22
Java Version Java 21 CE
Plugin version: graalvm-reachability-metadata-0.10.2-repository.zip

@loonis loonis added the enhancement New feature or request label Jun 26, 2024
@jma-9code
Copy link

jma-9code commented Jun 30, 2024

You need to create :

  1. src/main/resources/META-INF/native-image/resource-config.json inside your project and add the following content:
{
  "resources": [
    {
      "pattern": "spatial_ref_sys.txt"
    }
  ]
}
  1. src/main/resources/META-INF/native-image/reflect-config.json inside your project and add the following content:
    [ { "condition": { "typeReachable": "org.hibernate.spatial.integration.SpatialInitializer" }, "name":"org.geolatte.geom.codec.PostgisWkbDecoder", "methods":[{"name":"<init>","parameterTypes":[] }] }, { "condition": { "typeReachable": "org.hibernate.spatial.integration.SpatialInitializer" }, "name":"org.geolatte.geom.codec.PostgisWktEncoder", "methods":[{"name":"<init>","parameterTypes":[] }] }, { "condition": { "typeReachable": "org.hibernate.spatial.integration.SpatialInitializer" }, "name": "org.geolatte.geom.crs.CrsRegistry", "allDeclaredConstructors": true, "allDeclaredMethods": true }, { "condition": { "typeReachable": "org.hibernate.spatial.integration.SpatialInitializer" }, "name": "org.geolatte.geom.crs.CoordinateReferenceSystems", "allDeclaredConstructors": true, "allDeclaredMethods": true }, { "condition": { "typeReachable": "org.hibernate.spatial.integration.SpatialInitializer" }, "name":"org.locationtech.jts.geom.Point" }, { "name": "org.hibernate.spatial.HSMessageLogger_$logger", "condition": { "typeReachable": "org.hibernate.spatial.integration.SpatialInitializer" }, "methods": [ { "name": "<init>", "parameterTypes": [ "org.jboss.logging.Logger" ] } ] } ]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants