luchob / softuni-spring-may-2024

Our common projects
15 stars 1 forks source link

Как да получа през REST API PagedModel<> #73

Closed ChrisHartarski closed 3 months ago

ChrisHartarski commented 3 months ago

основен проект: https://github.com/ChrisHartarski/MagnaTechnica-WebShop-SoftUniProject REST service: https://github.com/ChrisHartarski/MagnaTechnica-WebShop-Machines-SoftUniProject

Кратко описание:

Възможно най-накратко опишете:

  1. Какво очаквате да се случи Искам да получа през rest client-а PagedModel.
  2. Какво всъщност се случва Явно получения резултат не може да се десериализира. Полуачвам следната грешка: "com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of org.springframework.data.web.PagedModel (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)"

Стъпки за репродуциране: За да се генерират машини в базата: Login -> User: admin@example.com Pass:asdasd -> Admin Panel -> Initialize Mock DB Получавам грешка, когато се опирам да достъпя Machines таб-а, защото не може да десериализира PagedModel<>.

luchob commented 3 months ago

🎉Благодаря, че сте тук и се интересувате от Spring Framework!🎉

🌴 За съжаление обаче, аз не съм тук (това е автоматичен отговор) и ще бъда много ограничено достъпен чак до 10-ти август.
🥲Така че, не обещавам да ви отговоря или да ви пиша.
🥹Извинете ме!

:rocket: Успешно и приятно програмиране! :rocket:

luchob commented 3 months ago

Здравей! Още съм си тук, утре заминавам. Вчера правихме github action с auto reply :-)

За нещастие не можеш. И аз бях леко озадачен :-) Лесен workaround е да си направиш един прост клас който да десериализираш вместо това:

public class PageData<T> {

  private List<T> content;
  private PageMetadata page;

  public List<T> getContent() {
    return content;
  }

  public PageData<T> setContent(List<T> content) {
    this.content = content;
    return this;
  }

  public PageMetadata getPage() {
    return page;
  }

  public PageData<T> setPage(PageMetadata page) {
    this.page = page;
    return this;
  }
}

PageMetadata е вътрешен публичен клас от PagedModel. Можеш да си нащракаш и разни методчета вътре, ако е необходимо:


  public boolean isFirst() {
    return page.number() == 0;
  }

  public boolean isLast() {
    return page.number() >= page.totalPages() - 1;
  }

  public boolean hasPrevious() {
    return !isFirst() && page.totalPages() > 1;
  }

  public boolean hasNext() {
    return !isLast() && page.totalPages() > 1;
  }

Изненадата с PagedModel e прясна прясна, в 3.3.0 хвърлиха бомбата.

Поздрави, Л.

ChrisHartarski commented 3 months ago

Здравей,

Благодаря за отговора и приятна почивка.

Поровичках се един ден в нета и пробвах и ChatGPT. Решението, до което стигнах е: 1) В контролера на body му давам да получава String.class 2) след това се прави клас PagedModelDeserializer, който казва как да се десериализира String-а. 3) след това с ObjectMapper се мап-ва String към PagedModel.

Не знам дали е най-чистия начин, но за сега работи.

luchob commented 3 months ago

Май с къстъм клас ми изглежда по простичко, знам ли :-)

Поздрави, Л.