Джексон и Ломбок: исключение MismatchedInputException, когда атрибуты являются объектами - PullRequest
0 голосов
/ 16 июня 2020

У меня есть класс Job, который выглядит так:

@Entity
@Table
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Data
@NoArgsConstructor
public class Job implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Column(nullable = false)
    private String job;

    @ManyToOne
    @JsonIgnoreProperties("jobs")
    private Job next;

и метод для создания рабочих мест:

    @PostMapping("/jobs")
    public ResponseEntity<Job> createJob(@Valid @RequestBody Job job) throws URISyntaxException {
        Job result = jobRepository.save(job);
        return ...
    }

Все работает нормально, пока здесь. Добавление @AllArgsConstructor к классу Job теперь приводит к MismatchedInputException.

Bad Request: JSON parse error: Cannot construct instance of `xxx.domain.Job` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `xxx.domain.Job` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator) 

Я пытался добавить lombok.anyConstructor.addConstructorProperties = true в файл lombok.config, как описано в ответах, которые я нашел. Но это приводит только к следующей ошибке:

[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ project-name ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 27 source files to /path/target/test-classes
Unknown key 'lombok.anyConstructor.addConstructorProperties' (/path/lombok.config:2)

Я пробовал использовать старую версию ломбока, так как обнаружил некоторые проблемы с github, решающие эту проблему при обновлении ломбока. Кроме того, безуспешно (пробовала версия 1.16.18)

Я также попытался удалить атрибут private Job next, который заставил код работать без ошибок. Значит, это какая-то проблема?

Ответы [ 2 ]

0 голосов
/ 18 июня 2020

Я обнаружил эту проблему на github: https://github.com/meltmedia/jackson-crypto/issues/6

, как описано там, я исправил проблему, установив:

jackson:
    mapper:
        INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES: false

Jackson Do c говорит:

Функция в основном используется для обеспечения взаимодействия с такими фреймворками, как Lombok , которые могут автоматически генерировать аннотацию ConstructorProperties, но не обязательно означает, что конструктор должен использоваться как Создатель для десериализации.

0 голосов
/ 16 июня 2020

Сводка

Вероятно, вы не хотите @ConstructorProperties ни в какой форме.

Ключ lombok.anyConstructor.addConstructorProperties = true больше не доступен по досадным причинам. Правый ключ - lombok.anyConstructor.suppressConstructorProperties = false, хотя вы, вероятно, не хотите на самом деле применять этот ключ конфигурации.

Исправление, вероятно, состоит в том, чтобы обновить инструменты сборки, чтобы указать javac для генерации информации об имени параметра в файлах классов.

Вы не хотите @ ConstructorProperties

'Точка' аннотации @ConstructorProperties состоит из двух частей: чтобы разрешить код времени выполнения (java код, используя API отражения), чтобы проверить имена параметров конструктора и позволить инструментам времени компиляции вычислить имена параметров конструктора, если все, что доступно, скомпилированный (классовый) файл, а не исходные (java) файлы.

Однако для этой цели @ConstructorProperties является устаревшим. В наши дни большинство конфигураций компилятора были обновлены по умолчанию для включения имен параметров в файлы классов, а API-интерфейсы отражения были обновлены, чтобы вы могли легко их получить. Например:

public class Example {
    public Example(String a, int b) {}
    public static void main(String[] args) throws Exception {
        System.out.println(Example.class
            .getConstructor(String.class, int.class)
            .getParameters()[1]
            .getName());
    }
}

, затем в командной строке:

javac Example.java
java Example
arg1

javac -parameters Example.java
java Example
b

Вы можете включить указанный выше исходный файл в свою сборку в качестве быстрой проверки, чтобы убедиться, что -parameters Опция устанавливается любой системой сборки, которую вы используете для сборки исходных файлов. Он должен напечатать b, а если нет (если он напечатает arg1), выполните быстрый поиск того, как сделать maven или gradle или любую другую соответствующую информацию об имени параметра emit во время его компиляции.

Теперь Джексон имеет шанс просто использовать эту информацию (вместо того, чтобы полагаться на @ConstructorProperties). На самом деле я не знаю, есть ли, но я предполагаю, что да: это «новый» способ сделать это.

Почему вам это не нужно

... потому что Сообществу java нельзя доверять это, что доказано историей.

Аннотации начинались с простого, ясного дизайна (вы используете ее для передачи имен параметров в форме аннотации) и почти сразу же сообщество в целом запуталось: и android, и GWT отказались бы компилировать ваш код, если бы эта аннотация была даже в ваших java файлах.

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

Но затем вышел java9 с модульной системой, и в * Бесконечная мудрость 1088 *, решили .... засунуть эту аннотацию в ... модуль ... java.desktop ??? По сей день я совершенно не понимаю, что там произошло, поскольку это кажется дико неподходящим модулем для него. Но это означает, что если вы хотите использовать ConstructorProperties в любой форме в модульных сборках (то есть что-нибудь с файлом module-info.java в root), вам нужно добавить к нему requires java.desktop;, за исключением того, что обычно подразумевают вещи, которые не имеют смысла (например: что ваш модуль не может работать на JVM без головы).

Это сводится к двум пунктам: [1] почему конфигурация ломбока и поведение для свойств конструктора так испорчены, и [2] почему я советую вам не использовать @ConstructorProperties.

конфигурацию Lombok

Если, несмотря на приведенный выше совет, вы действительно хотите использовать ConstructorProperties, правильная конфигурация в ломбоке :

lombok.anyConstructor.suppressConstructorProperties = false

Конфигурационные ключи в ломбоке для генерации @ConstructorProperties прошли немного неудачно из-за описанной выше истории. Я прошу прощения за причиненные вам трудности. (Я являюсь основным участником ломбока).

Первоначально существовал addConstructorProperties (по сравнению с гораздо более простым: всегда генерировать эту аннотацию и вообще не иметь ключа конфигурации), потому что android и GWT не могли обрабатывать его присутствие, и, по нашей оценке, больше людей использовали android / GWT + lombok, чем люди, которые полагались на создание @ConstructorProperties, поэтому мы решили, что соответствующее поведение по умолчанию должно заключаться в том, чтобы не включать аннотацию при создании конструктора *. 1067 *

Затем, когда GWT / Android исправил проблему, баланс сил изменился: теперь мы поняли, что «генерировать по умолчанию» скорее поможет, чем повредит. Мы очень, очень хотели, чтобы наши свойства всегда были «по умолчанию false», поэтому вместо этого мы переименовали ключ в lombok.anyConstructor.suppressConstructorProperties.

Затем в более поздней версии lombok, после отказа от 'we wi sh все по умолчанию - false 'максим, мы изменили поведение по умолчанию на то, что было: Do NOT генерировать ConstructorProperties по умолчанию. Это было как раз в тот момент, когда это могло привести к тому, что код вообще не компилировался, если вы используете модульную сборку, из-за того, что аннотация помещается в модуль java.desktop. В то время как сообщество java в целом по-прежнему в значительной степени избегает головоломки, некоторые все же используют ее, более чем достаточно, чтобы сместить баланс сил обратно. Вдобавок теперь нам ясно, что @ConstructorProperties как механизм обречен, с переключателем -parameters правильным решением, с меньшими головными болями.

Мы ожидаем, что поведение ломбока не изменится в третий раз.

...