Почему происходит сбой десериализации с помощью quarkus-panache, hibernate и jsonb?

Я хотел немного поиграть с hibernate, panache и quarkus. Я хотел создать 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, но это может подождать, пока связь и десериализация не сработают.


person maiksensi    schedule 27.07.2020    source источник
comment
Можете ли вы вставить сообщение об ошибке и трассировку стека, чтобы мы могли лучше понять проблему?   -  person loicmathieu    schedule 27.07.2020
comment
Я приложил сообщение об ошибке и то, что смог почерпнуть из журналов. Журнал выглядит одинаково, даже если я использую ./gradlew quarkusDev --stacktrace или ... --debug   -  person maiksensi    schedule 27.07.2020
comment
честно говоря, я думаю, что причина, по которой это не работает, не имеет ничего общего с quarkus (хотя я хотел бы знать, как лучше отладить ошибку), а скорее то, что я делаю некоторую ошибку, связанную с гибернацией   -  person maiksensi    schedule 27.07.2020


Ответы (1)


Итак, я выяснил, что сделал не так. Две вещи:

  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), чтобы также обновить временное свойство при сохранении.
person maiksensi    schedule 27.07.2020