Search code examples
quarkusquarkus-panachequarkus-reactivequarkus-hibernate-reactive

Hibernate Reactive in Quarkus 3.2.4 give me "java.lang.ClassCastException: " in Geometry ORM mapping


I use Quarkus 3.2.4 hibernate reactive panache to define a Entity like this:

import io.quarkus.hibernate.reactive.panache.PanacheEntityBase;
import jakarta.persistence.*;
import org.locationtech.jts.geom.Point;

@Entity
@Table(name = "location")
public class Location extends PanacheEntityBase {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long id;

    public String name;

    @Column(columnDefinition = "geometry")
    public Point geom;

}

and when i try to fetch all records like this, it's give me below error:

  @GET
    public Uni<List<Location>> getAll() {
        return Location.listAll();
    }

short error:

Caused by: java.lang.ClassCastException: class io.vertx.mysqlclient.data.spatial.Point cannot be cast to class io.vertx.core.buffer.Buffer (io.vertx.mysqlclient.data.spatial.Point and io.vertx.core.buffer.Buffer are in unnamed module of loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @6e38921c)

long error:

2023-08-20 14:09:03,846 ERROR [io.qua.ver.htt.run.QuarkusErrorHandler] (vert.x-eventloop-thread-1) HTTP Request to /location failed, error id: 322c35e4-1f91-4236-9793-172bc74237c6-1: org.hibernate.HibernateException: Unable to extract JDBC value for position `2`
        at org.hibernate.reactive.sql.exec.spi.ReactiveValuesResultSet.lambda$readCurrentRowValues$2(ReactiveValuesResultSet.java:148)
        at java.base/java.util.concurrent.CompletableFuture.uniApplyNow(CompletableFuture.java:684)
        at java.base/java.util.concurrent.CompletableFuture.uniApplyStage(CompletableFuture.java:662)
        at java.base/java.util.concurrent.CompletableFuture.thenApply(CompletableFuture.java:2168)
        at java.base/java.util.concurrent.CompletableFuture.thenApply(CompletableFuture.java:144)
        at org.hibernate.reactive.sql.exec.spi.ReactiveValuesResultSet.readCurrentRowValues(ReactiveValuesResultSet.java:139)
        at java.base/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1150)
        at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510)
        at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2147)
        at io.vertx.core.Future.lambda$toCompletionStage$3(Future.java:536)
        at io.vertx.core.impl.future.FutureImpl$3.onSuccess(FutureImpl.java:141)
        at io.vertx.core.impl.future.FutureBase.emitSuccess(FutureBase.java:60)
        at io.vertx.core.impl.future.FutureImpl.tryComplete(FutureImpl.java:211)
        at io.vertx.core.impl.future.PromiseImpl.tryComplete(PromiseImpl.java:23)
        at io.vertx.sqlclient.impl.QueryResultBuilder.tryComplete(QueryResultBuilder.java:88)
        at io.vertx.sqlclient.impl.QueryResultBuilder.tryComplete(QueryResultBuilder.java:32)
        at io.vertx.core.Promise.complete(Promise.java:66)
        at io.vertx.core.Promise.handle(Promise.java:51)
        at io.vertx.core.Promise.handle(Promise.java:29)
        at io.vertx.core.impl.future.FutureImpl$3.onSuccess(FutureImpl.java:141)
        at io.vertx.core.impl.future.FutureBase.lambda$emitSuccess$0(FutureBase.java:54)
        at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174)
        at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:167)
        at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569)
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.ClassCastException: class io.vertx.mysqlclient.data.spatial.Point cannot be cast to class io.vertx.core.buffer.Buffer (io.vertx.mysqlclient.data.spatial.Point and io.vertx.core.buffer.Buffer are in unnamed module of loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @6e38921c)
        at io.vertx.sqlclient.Tuple.getBuffer(Tuple.java:592)
        at org.hibernate.reactive.adaptor.impl.ResultSetAdaptor.getBytes(ResultSetAdaptor.java:154)
        at org.hibernate.spatial.dialect.mysql.MySQLGeometryJdbcType$2.doExtract(MySQLGeometryJdbcType.java:93)
        at org.hibernate.type.descriptor.jdbc.BasicExtractor.extract(BasicExtractor.java:44)
        at org.hibernate.reactive.sql.exec.spi.ReactiveValuesResultSet.lambda$readCurrentRowValues$2(ReactiveValuesResultSet.java:145)
        ... 28 more

full code is in this repository demo

when i swith mysql to pgsql, it seems ok, so is this a bug?

Thanks!

I give a test code. you can start server by:

./mvnw compile quarkus:dev

and when i want to call the get resource. the program show that error:

curl http://localhost:8080/location

what i expecting is execute without error.


Solution

  • Currently Hibernate Reactive does not support Hibernate Spatial.
    Hibernate Reactive uses Vert.x SQL clients, in this case vertx-mysql-client. This client has built-in codec for geometry types, so the result set will contain a sub-type of io.vertx.mysqlclient.data.spatial.Geometry instead of a byte buffer (byte array) which is excepted by Hibernate Spatial's MySQLGeometryJdbcType type contributor.