为什么使用quarkus-panache、hibernate和jsonb进行反序列化会失败?

huangapple go评论74阅读模式
英文:

Why is deserialization with quarkus-panache, hibernate and jsonb failing?

问题

我想在使用 Hibernate、Panache 和 Quarkus 方面做一些尝试。我想要构建一个“追踪(tracing)”API,其中一个人可以拥有多个追踪,但一个追踪只能由一个人拥有。但是我遇到了反序列化错误。

假设我想要发送以下内容:

curl --location --request POST 'localhost:8080/trace' \
--header 'Content-Type: application/json' \
--data-raw '{
    "traceOwner": "AtestOwner",
    "participants": ["Karl", "John"],
    "place": "10101, TestCity, TestStreet 25",
    "startTime": "2016-07-20T23:07:41.907+02:00[Europe/Berlin]",
    "stopTime": "2016-07-27T23:07:45.807+02:00",
    "comment": "TestComment"
}'

我收到以下错误:

javax.ws.rs.ProcessingException: RESTEASY008200: JSON Binding deserialization error: javax.json.bind.JsonbException:
Unable to deserialize property 'traceOwner' because of: Error deserialize JSON value into type: class de.test.Person.

并且在日志中看到:

2020-07-27 10:48:12,597 SEVERE [org.ecl.yas.int.Unmarshaller] (executor-thread-1) Unable to deserialize property 'traceOwner' because of: Error deserialize JSON value into type: class de.test.Person.

我的实体类看起来像这样:

import java.time.ZonedDateTime;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;

import io.quarkus.hibernate.orm.panache.PanacheEntity;

@Entity
public class Trace extends PanacheEntity {
  @ManyToOne
  public Person traceOwner;
  @ElementCollection
  public List<String> participants;
  public String place;
  @Column(columnDefinition = "TIMESTAMP WITH TIME ZONE")
  public ZonedDateTime startTime;
  @Column(columnDefinition = "TIMESTAMP WITH TIME ZONE")
  public ZonedDateTime stopTime;
  public String comment;

  public String toString() {
    return String.format("%s, [%s, %s], %s, %s, %s", this.traceOwner, this.participants.get(0),
        this.participants.get(1), this.place, this.startTime, this.stopTime, this.comment);
  }
}

import javax.persistence.Entity;

import io.quarkus.hibernate.orm.panache.PanacheEntity;

@Entity
public class Person extends PanacheEntity {
  public String name;
}

POST 端点看起来是这样的:

  @POST
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public Response createTrace(@Valid Trace trace) {
    try {
      LOG.info(trace);
      transaction.begin();
      trace.persist();
      transaction.commit();
    } catch (NotSupportedException | SystemException | SecurityException | IllegalStateException | RollbackException
        | HeuristicMixedException | HeuristicRollbackException e1) {
      LOG.error("Could not finish transaction to save entity", e1);
      return Response.status(HttpStatus.SC_BAD_REQUEST).build();

    }
    return Response.ok(Trace.find("startTime =?1 AND traceOwner = ?2", trace.startTime, trace.traceOwner).firstResult())
        .build();
  }

为了避免缓存问题,我打开了一个新的事务,但我猜这不是问题的原因?

我真的不明白为什么 JSONB 抱怨反序列化问题,以及我如何解决它。另外,在某个时候,我想让 public List<String> participants 成为 public List<Person> participants,但在关系和反序列化正常工作后再进行修改。

英文:

I wanted to play around with hibernate, panache and quarkus a bit. I wanted to build a "tracing" api where a person can have several traces but a trace can only be owned by one person. but I am facing a deserialization error.

Let's say I want to post this:

curl --location --request POST &#39;localhost:8080/trace&#39; \
--header &#39;Content-Type: application/json&#39; \
--data-raw &#39;{
    &quot;traceOwner&quot;: &quot;AtestOwner&quot;,
    &quot;participants&quot;: [&quot;Karl&quot;, &quot;John&quot;],
    &quot;place&quot;: &quot;10101, TestCity, TestStreet 25&quot;,
    &quot;startTime&quot;: &quot;2016-07-20T23:07:41.907+02:00[Europe/Berlin]&quot;,
    &quot;stopTime&quot;: &quot;2016-07-27T23:07:45.807+02:00&quot;,
    &quot;comment&quot;: &quot;TestComment&quot;
}&#39;

I get the following errors:

javax.ws.rs.ProcessingException: RESTEASY008200: JSON Binding deserialization error: javax.json.bind.JsonbException:
Unable to deserialize property &amp;#x27;traceOwner&amp;#x27; because of: Error deserialize JSON value into type: class
de.test.Person.

and in the logs:

2020-07-27 10:48:12,597 SEVERE [org.ecl.yas.int.Unmarshaller] (executor-thread-1) Unable to deserialize property &#39;traceOwner&#39; because of: Error deserialize JSON value into type: class de.test.Person.

My Entities look like this:

import java.time.ZonedDateTime;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;

import io.quarkus.hibernate.orm.panache.PanacheEntity;

@Entity
public class Trace extends PanacheEntity {
  @ManyToOne
  public Person traceOwner;
  @ElementCollection
  public List&lt;String&gt; participants;
  public String place;
  @Column(columnDefinition = &quot;TIMESTAMP WITH TIME ZONE&quot;)
  public ZonedDateTime startTime;
  @Column(columnDefinition = &quot;TIMESTAMP WITH TIME ZONE&quot;)
  public ZonedDateTime stopTime;
  public String comment;

  public String toString() {
    return String.format(&quot;%s, [%s, %s], %s, %s, %s&quot;, this.traceOwner, this.participants.get(0),
        this.participants.get(1), this.place, this.startTime, this.stopTime, this.comment);
  }
}

and

import javax.persistence.Entity;

import io.quarkus.hibernate.orm.panache.PanacheEntity;

@Entity
public class Person extends PanacheEntity {
  public String name;
}

The POST endpoint looks like this:

  @POST
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public Response createTrace(@Valid Trace trace) {
    try {
      LOG.info(trace);
      transaction.begin();
      trace.persist();
      transaction.commit();
    } catch (NotSupportedException | SystemException | SecurityException | IllegalStateException | RollbackException
        | HeuristicMixedException | HeuristicRollbackException e1) {
      LOG.error(&quot;Could not finish transaction to save entity&quot;, e1);
      return Response.status(HttpStatus.SC_BAD_REQUEST).build();

    }
    return Response.ok(Trace.find(&quot;startTime =?1 AND traceOwner = ?2&quot;, trace.startTime, trace.traceOwner).firstResult())
        .build();
  }

To avoid a caching problem I open a new transaction, but I guess that is not the problem?

I don't really get why jsonB complains about the deserialization and how I can fix it. Also, at some point I wanted public List&lt;String&gt; participants to be public List&lt;Person&gt; participants but that can wait till the relation and deserialization works.

答案1

得分: 2

所以,我发现我做错了两件事:

  1. 使用有效的 JSON:
curl --location --request POST 'localhost:8080/trace' \
--header 'Content-Type: application/json' \
--data-raw '{
    "traceOwner": {"name": "AtestOwner"},
    "participants": ["Karl", "John"],
    "place": "10101, TestCity, TestStreet 25",
    "startTime": "2016-07-20T23:07:41.907+02:00[Europe/Berlin]",
    "stopTime": "2016-07-27T23:07:45.807+02:00",
    "comment": "TestComment"
}'

请注意不同的 "traceOwner" 部分。

  1. 使用 @ManyToOne(cascade = CascadeType.ALL) 在持久化时也更新瞬态属性。
英文:

So, I found out what I did do wrong. Two things:

  1. Use a valid json:
curl --location --request POST &#39;localhost:8080/trace&#39; \
--header &#39;Content-Type: application/json&#39; \
--data-raw &#39;{
    &quot;traceOwner&quot;: {&quot;name&quot;: &quot;AtestOwner&quot;},
    &quot;participants&quot;: [&quot;Karl&quot;, &quot;John&quot;],
    &quot;place&quot;: &quot;10101, TestCity, TestStreet 25&quot;,
    &quot;startTime&quot;: &quot;2016-07-20T23:07:41.907+02:00[Europe/Berlin]&quot;,
    &quot;stopTime&quot;: &quot;2016-07-27T23:07:45.807+02:00&quot;,
    &quot;comment&quot;: &quot;TestComment&quot;
}&#39;

Please notice the different "traceOwner" part.

  1. Use @ManyToOne(cascade = CascadeType.ALL) to also update the transient property when persisting.

huangapple
  • 本文由 发表于 2020年7月27日 16:38:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/63111595.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定