весенние данные отдых котлин ассоциации POST - PullRequest
0 голосов
/ 27 апреля 2018

Я следовал за учебником http://www.baeldung.com/spring-data-rest-relationships. Я также заметил, что могу создать ассоциацию напрямую, предоставив ссылку на связь.

curl -i -X POST -H "Content-Type:application/json" -d '{"name":"My Library"}' http://localhost:8080/libraries
curl -i -X POST -d '{"title":"Books", "library":"http://localhost:8080/libraries/1"}' -H "Content-Type:application/json" http://localhost:8080/books

Это прекрасно работает в Java, а также в Kotlin при использовании обычного класса.

Однако, если я использую класс данных в Kotlin, я получаю следующую ошибку

2018-04-26 14: 13: 43.730 ОШИБКА 79256 --- [nio-8080-exec-2] behRestResponseEntityExceptionHandler: org.springframework.http.converter.HttpMessageNotReadableException: ошибка синтаксического анализа JSON: не удается создать экземпляр com. baeldung.models.Library (хотя существует хотя бы один создатель): нет конструктора аргумента строки / фабричного метода для десериализации из значения строки ('http://localhost:8080/libraries/1'); вложенное исключение - com.fasterxml.jackson.databind.exc.MismatchedInputException: Невозможно создать экземпляр com.baeldung.models.Library (хотя существует хотя бы один создатель): нет конструктора аргумента String / метода фабрики для десериализации из значения String ('http://localhost:8080/libraries/1') в [Source: (org.apache. catalina.connector.CoyoteInputStream); строка: 1, столбец: 29] (через цепочку ссылок: com.baeldung.models.Book ["library"])

У меня есть соответствующие плагины kotlin-spring, kotlin-jpa и kotlin-noarg в моем проекте.

Код здесь https://github.com/vijaysl/spring-data-rest

Ответы [ 3 ]

0 голосов
/ 03 июля 2018

С котлином все ок.

Просто замените «класс данных» на «класс».

Джексон не находит пустой конструктор в "классе данных". И используй другой десериализатор ... не Ури ....

0 голосов
/ 28 августа 2018

Попробуйте добавить @JsonCreator(mode = JsonCreator.Mode.DISABLED) аннотацию к первичному конструктору. Нет необходимости отключать com.fasterxml.jackson.module:jackson-module-kotlin.

Пояснение:

  • Модуль Kotlin Jackson подразумевает, что ваш конструктор по умолчанию является создателем JSON (см. KotlinValueInstantiator класс).
  • Поэтому Spring Data REST не применяет свой модификатор десериализатора бина (который должен загружать бин по URI), потому что сопоставления свойств бина не используются для свойств создателя (параметров конструктора).
  • KotlinValueInstantiator пытается десериализовать параметры конструктора, используя стандартные десериализаторы и инстанциаторы, и это приводит к указанной вами ошибке.

Возможное решение:

Поскольку модуль koltin-jpa добавляет пустой конструктор по умолчанию для JPA, вы можете указать Джексону не использовать создатель JSON, а пустой конструктор по умолчанию, явно отключив его.

Пример:

@Entity
class Book @JsonCreator(mode = JsonCreator.Mode.DISABLED) constructor(

  @ManyToMany
  val libraries: ModifiableList<Library> = ArrayList(),

): AbstractPersistable<Long>(), Identifiable<Long>
0 голосов
/ 28 апреля 2018

Классы данных Kotlin довольно строгие. Он говорит вам, по сути, он не может создать ваше POKO, и он перечисляет некоторые способы, которые он пытается. Один из них с конструктором String. Другие - через частные манипуляции с полями (как это обычно делается).

Классы данных в kotlin, если у них есть поля, объявленные как private val name:String, преобразуются в (в java) private final String name; Он не может присваиваться полю final (что грязно, если пытаться назначить частному полю, но невозможно, когда это окончательно; JVM не допустит этого), и нет функций getName() или setName(), которые можно использовать в качестве другого метода гидратации.

Некоторые опции:

  1. Объявите ваши переменные var вместо val. private var name:String - это эквивалент Java, равный private String name, который будет использовать полевую (грязную) гидратацию.
  2. включает определенную зависимость kotlin для kotlin, которая устраняет эту проблему: compile("com.fasterxml.jackson.module:jackson-module-kotlin") посмотрите на этот проект

пример класса kotlin, который должен работать для вас:

import org.springframework.hateoas.Identifiable
import java.time.LocalDate
import javax.persistence.*
import javax.validation.constraints.*

@Entity
data class Employee(@Pattern(regexp = "[A-Za-z0-9]+")
                    @Size(min = 6, max = 32)
                    val name: String,
                    @Email
                    @NotNull
                    val email: String?,
                    @PastOrPresent
                    val hireDate: LocalDate = LocalDate.now(),

                    @OneToMany(mappedBy = "employee", cascade = [CascadeType.ALL])
                    val forms:List<Form> = listOf(),
                    @OneToMany(mappedBy = "employee", cascade = [CascadeType.ALL])
                    val reports:List<Report> = listOf(),
                    @Id @GeneratedValue( strategy =  GenerationType.IDENTITY) private val id: Long? = null): Identifiable<Long> {

    override fun getId() = id

    constructor(name:String): this(name,"$name@foo.com")
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...