Обнуляемость проверки bean-компонентов Kotlin Spring

В моем приложении Spring, созданном с помощью Kotlin, я хотел бы использовать проверку bean-компонентов для класса данных, который выглядит следующим образом.

data class CustomerDto(
    @field: NotBlank
    val firstName: String,

    @field: NotBlank
    val lastName: String)

При отправке сообщения с пустым firstName в конечную точку клиента я хотел бы получить проверки ограничений, но из-за того, что поля не допускают нулевые значения, я не получаю проверки, а скорее получаю следующую ошибку.

"status": 400,
"error": "Bad Request",
"message": "JSON parse error: Instantiation of [simple type, class pkg.CustomerDto] value failed for JSON property firstName due to missing (therefore NULL) value for creator parameter firstName which is a non-nullable type; nested exception is com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException: Instantiation of [simple type, class pkg.CustomerDto] value failed for JSON property firstName due to missing (therefore NULL) value for creator parameter firstName which is a non-nullable type\n at [Source: (PushbackInputStream); line: 19, column: 1] (through reference chain: pkg.CustomerDto[\"firstName\"])",
"path": "/shop/5/customer"

Есть ли другой вариант, чтобы пометить поле dto как необязательное и по-прежнему получать нарушения ограничений? Когда я помечаю их как необязательные, я должен использовать !! в полях кода, не допускающих значения NULL, при сопоставлении их с моими сущностями.

Спасибо.

Хороший вопрос, возможно, тишина здесь подтверждает мое впечатление. Imo нет никакого способа, поскольку успешное построение объекта является предпосылкой для проверки поля. Тем не менее, я хотел бы прочитать мнение чемпиона Котлина. У меня есть для этого решение, связанное с Spring, но я думаю, вы хотите решить его по-Kotlin?

Jan B. 21.09.2018 19:15

Нет, у меня нет хорошего решения, кроме как сделать все необязательным или использовать !! при сопоставлении с моими объектами полагаться на нулевую безопасность в моей модели. Я был бы заинтересован в решении Spring, которое вы имели в виду.

jgeerts 24.09.2018 14:28

После небольшого поиска, я думаю, это может быть немного сложнее, чем я думал в первую очередь, однако, возможно. Вопрос в том, оправдывают ли подходы те усилия, которые вам необходимо приложить. Во-первых, следует использовать Spring AOP, второй HandlerInterceptors, который позволяет вам получать доступ и изменять запрос до того, как Джексон десериализует полезную нагрузку запроса в ваш CustomerDTO. Это определенно непростое решение, взгляните на этот вопрос: stackoverflow.com/questions/50932518/…

Jan B. 24.09.2018 23:44
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
14
3
2 689
2

Ответы 2

Я считаю, что вы идете неверным путем.

Точная цель нулевых операторов безопасности Kotlin - заставить вас явно выражать поведение нулевого значения в вашем коде, чтобы резко минимизировать NPE или, по крайней мере, убедиться, что вы сознательно вызвали их сами :). В вашем (или любом другом MVC-подобном шаблоне доступа) случае вы сталкиваетесь со следующим сценарием

  • Поле может быть нулевым как часть полезной нагрузки DTO
  • Проверка фреймворка должна дисквалифицировать DTO, если поле равно нулю.
  • Если проверка фреймворка прошла успешно, поле DTO будет неявно предполагается, что он не равен нулю.

Хотя это имеет смысл с точки зрения логического потока, на самом деле это нарушение, которое может привести к NPE, потому что ничто в модели / контракте не гарантирует, что эти поля не будут нулевыми.

Тем не менее, в java вы бы просто сделали это последнее предположение, используя геттер (вы бы все равно использовали геттер, это java, верно?).

Что ж - в котлине ничего не изменилось, если это то, что вам нужно:

data class CustomerDto(@field:NotNull 
                       @JsonProperty("firstName") private val _firstName: String? = null,
                       @field:NotNull
                       @JsonProperty("lastName") private val _lastName: String? = null) {
        val firstName get() = _firstName!!
        val lastName get() = _lastName!!
    }

(В этом примере предполагается, что вы используете jackson для де / сериализации JSON)

Хотя вы все еще вручную форсируете недопустимость обнуления с помощью оператора !! (чего вы хотели избежать), теперь вы абстрагируете этот аспект от остальной части своей кодовой базы, получая поведение, подобное java-getter.

Вы описываете проблему, но мне было интересно, есть ли способ сделать аннотацию @NotNull в Kotlin ненулевым полем. Я все еще думаю, что этого можно достичь, если Spring сначала выполнит проверку, а затем отобразит целевой класс, как то, что описывает @Matt, но с поддержкой фреймворка.

jgeerts 10.05.2019 09:10

Я понимаю вашу проблему, но я также считаю, что макет класса данных, который я предложил, решает эту проблему способом "kotlin", потому что он позволяет вам пользоваться как нулевой безопасностью kotlin, так и проверкой Spring (вы все равно можете аннотировать поля DTO) при абстрагировании первый из остальной части вашего приложения и сохраняя его как соображение при проектировании внутреннего класса данных. Я не понимаю, как этого недостаточно.

Sheinbergon 12.05.2019 13:39

field: JsonProperty необходимо использовать, чтобы распознать аннотацию для поля. Получатель должен иметь аннотацию get: JsonIgnore, чтобы Джексон не использовал получатель для идентификации. Если он идентифицирует и вызывает метод получения, когда скрытое значение равно нулю, это приведет к исключению JsonProcessingException из-за NPE. Далее, даже при этом, в случае ошибки проверки, в ответе spring будет отображаться имя поля вместо свойства json. Это описано в этом вопросе: stackoverflow.com/questions/41717866/…

somedev 07.01.2021 09:22

Я думаю, что лучшим решением будет использовать значение Kotlin по умолчанию внутри свойств:

data class CustomerDto(
@field: NotBlank
val firstName: String = "",

@field: NotBlank
val lastName: String = "")

Атрибуты имени и фамилии всегда будут иметь значение (из json или значение по умолчанию = ""). Решение не идеальное, но работает так, как ожидалось.

Имейте в виду, что это значение по умолчанию помогает только в том случае, если свойство отсутствует в json, например, в { "firstName": "Name" }. Но он все равно выдает исключение, если json явно определяет свойство как null, например, { "firstName": "Name", "lastName": null }

Roman_D 02.09.2020 12:02

Другие вопросы по теме