StackOverflowError when executing Hibernate Panache list() static methods

1,982 views
Skip to first unread message

Francesco Marchioni

unread,
Jul 30, 2019, 12:37:41 PM7/30/19
to Quarkus Development mailing list
Hi Quarkus devs,
I've stumbled upon a "RESTEASY008205: JSON Binding serialization error java.lang.StackOverflowError" when executing a REST GET backed by an Hibernate Panache list() query. The list() query contains as parameter an Entity Field which is annotated as @ManyToOne @JoinColumn:

public List<Orders> findAll(Long customerId) {

    return Orders.list("customer.id", Sort.by("item"), customerId);

}


@Entity
public class Orders extends PanacheEntityBase {
    @Id
    @SequenceGenerator(
            name = "orderSequence",
            sequenceName = "orderId_seq",
            allocationSize = 1,
            initialValue = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "orderSequence")
    public Long id;

    @Column(length = 40)
    public String item;

    @Column
    public Long price;

    @ManyToOne
    @JoinColumn(name = "customer_id")
    public Customer customer;


}

2019-07-30 18:28:38,791 ERROR [io.und.req.io] (executor-thread-1) Exception handling request 40436deb-7fee-43d6-bca9-d5dc784e542c-1 to /orders: org.jboss.resteasy.spi.UnhandledException: javax.ws.rs.ProcessingException: RESTEASY008205: JSON Binding serialization error javax.json.bind.JsonbException: Error getting value on: com.packt.quarkus.chapter5.Customer@39b0aa80
    at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:381)
    at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:209)
    at org.jboss.resteasy.core.SynchronousDispatcher.writeResponse(SynchronousDispatcher.java:586)
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:507)
    at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:252)
    at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:153)
    at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:363)
    at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:156)
    at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:238)
    at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:249)
    at io.quarkus.resteasy.runtime.ResteasyFilter$ResteasyResponseWrapper.sendError(ResteasyFilter.java:57)
    at io.undertow.servlet.handlers.DefaultServlet.doGet(DefaultServlet.java:175)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:686)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:791)
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
    at io.quarkus.resteasy.runtime.ResteasyFilter.doFilter(ResteasyFilter.java:28)
    at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
    at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
    at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
    at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
    at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
    at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
    at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
    at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
    at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$8$1$1.call(UndertowDeploymentRecorder.java:483)
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:364)
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
    at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
    at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2011)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1538)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1429)
    at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
    at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:32)
    at java.lang.Thread.run(Thread.java:748)
    at org.jboss.threads.JBossThread.run(JBossThread.java:479)

I have a Test class to reproduce this issue (https://github.com/PacktPublishing/Hands-On-Cloud-Native-Applications-with-Java-and-Quarkus/blob/master/chapter5/hibernate-panache/src/test/java/com/packt/quarkus/chapter5/CustomerEndpointTest.java) as part of a book I'm writing about Quarkus :-)

Is there any issue when using @ManyToOne fields in find() and list() Hibernate Panache static methods?

Thanks
Francesco

Francesco Marchioni

unread,
Jul 31, 2019, 6:49:06 AM7/31/19
to quark...@googlegroups.com

Sorry, it seems the ML was out of the loop. Forwarding......

---------- Forwarded message ---------
From: Francesco Marchioni <fmar...@redhat.com>
Date: Wed, Jul 31, 2019 at 11:48 AM
Subject: Re: [quarkus-dev] StackOverflowError when executing Hibernate Panache list() static methods
To: Emmanuel Bernard <eber...@redhat.com>


Hi Emmanuel,
Although not in the Github source, I've already tried adding @JsonIgnore annotation on without success:

    @ManyToOne
    @JoinColumn(name = "customer_id")
    @JsonIgnore
    public Customer customer;

I still suspect there could be something wrong when building the List using Panache static list, when a @ManyToOne field is involved:

public List<Orders> findAll(Long customerId) {

    return Orders.list("customer.id", Sort.by("item"), customerId);

}


By debugging the Panache findAll methods I can see it builds an infinite loop of $$_hibernate_previousManagedEntity, which could be the cause of the StackOverflow Error:

debug.png

If you have time to cast an eye on it, you can just clone the repo and have a test.
Thanks
Francesco

On Tue, Jul 30, 2019 at 8:05 PM Emmanuel Bernard <eber...@redhat.com> wrote:
I think it’s a normal serialisation problem. Does orders points to customer and customer to order ? You need to add one of The JSON @Ignore like annotations. 

--
You received this message because you are subscribed to the Google Groups "Quarkus Development mailing list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to quarkus-dev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/quarkus-dev/e167fb7d-f860-43f2-93e5-4bb28240637c%40googlegroups.com.


--

Francesco Marchioni

Senior QA Engineer

Red Hat

via fausto coppi, 50

ROME - Italy

fmar...@redhat.com   
M: +393209671710    





--

Francesco Marchioni

Senior QA Engineer

Red Hat

via fausto coppi, 50

ROME - Italy

fmar...@redhat.com   
M: +393209671710    



Stephane Epardaud

unread,
Jul 31, 2019, 7:35:58 AM7/31/19
to fmar...@redhat.com, Quarkus Development mailing list
So this is a serialisation issue: you have entities that point to one another and the JSON serialiser doesn't see the circular refs. You need to add "ignore" annotations to get rid of that. It's not related to panache or one-to-many.



--
Stéphane Épardaud

Francesco Marchioni

unread,
Jul 31, 2019, 8:35:20 AM7/31/19
to Stephane Epardaud, Quarkus Development mailing list
Hi Stephane
You need to add "ignore" annotations to get rid of that. It's not related to panache or one-to-many.
If you are referring to @JsonIgnore, as I said, it doesn't help.

Although not in the Github source, I've already tried adding @JsonIgnore annotation on without success:

    @ManyToOne
    @JoinColumn(name = "customer_id")
    @JsonIgnore
    public Customer customer;

Stephane Epardaud

unread,
Jul 31, 2019, 8:40:00 AM7/31/19
to Francesco Marchioni, Quarkus Development mailing list
I am, and I'm sorry I don't see any mention of it. I see you're using public fields, could you try to add @JsonIgnore not on the field but on a getter for the field? So leave the field as-is, but add an annotated getter for it. It's possible that the json serialiser ignores the fields and actually only looks at the auto-generated getters we produce, which do not have the annotation unless you explicitly add one.
--
Stéphane Épardaud

Emmanuel Bernard

unread,
Jul 31, 2019, 8:42:22 AM7/31/19
to Stephane Epardaud, Francesco Marchioni, Quarkus Development mailing list
Also are you sure you use jackson and not json-b which might have a different ignore annotation.
The "infinite loop" you show in your screen capture is not an infinite loop. It's just a self reference, you can see the object id is the same.

Emmanuel Bernard

unread,
Jul 31, 2019, 8:44:31 AM7/31/19
to Stephane Epardaud, Francesco Marchioni, Quarkus Development mailing list

Guillaume Smet

unread,
Jul 31, 2019, 8:45:24 AM7/31/19
to Emmanuel Bernard, Stephane Epardaud, Francesco Marchioni, Quarkus Development mailing list
If using JSON-B, which was until the release coming today, the default choice, you have to use @JsonbTransient.

That being said, if the issue is on methods generated by the enhancer, adding this to your fields won't help.

I wonder if we should have the enhancer add the appropriate annotations (at least the ones for JSON-B and Jackson).

Stephane Epardaud

unread,
Jul 31, 2019, 9:03:53 AM7/31/19
to Guillaume Smet, Emmanuel Bernard, Francesco Marchioni, Quarkus Development mailing list
Well, let's first find out if it works with @JsonbTransient, but frankly I think we should automatically augment transient (the field modifier) and @Transient with both @JsonbTransient and @JsonIgnore just to avoid WTFs like that.
--
Stéphane Épardaud

Francesco Marchioni

unread,
Jul 31, 2019, 9:33:07 AM7/31/19
to Stephane Epardaud, Guillaume Smet, Emmanuel Bernard, Quarkus Development mailing list
Thanks a lot for the feedback. Yes with @JsonbTransient it works :)
I wasn't honestly aware of this annotation......

Luciano Degni

unread,
Sep 29, 2020, 8:21:15 AM9/29/20
to Quarkus Development mailing list
HI guys i have same issue but  i use @JsonbTransient   

javax.ws.rs.ProcessingException: RESTEASY008200: JSON Binding deserialization error: javax.json.bind.JsonbException:
Internal error: Unexpected char 47 at (line no=1, column no=1, offset=0)


exceptions is on @POST request on AutoEndpoint on create 

Reply all
Reply to author
Forward
0 new messages