Переход на Spring Boot 2 и использование Spring Batch 4

Я переношу Spring Boot с 1.4.2 на 2.0.0, что также включает перенос пакета Spring с 3.0.7 на 4.0.0, и похоже, что пакетный процесс больше не работает, когда я пытаюсь запустить его с новой версией Spring Batch.

Когда я попытался отладить, я обнаружил проблему, когда пакет пытается получить данные из batch_job_execution_context.

Я вижу, что получение данных из базы данных работает нормально, но новая версия пакета не может анализировать данные базы данных.

{"map":[{"entry":[{"string":["name",""]},{"string":["sender",""]},{"string":["id",""]},{"string":["nav",""]},{"string":["created",140418]}]}]}

с этой ошибкой:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (START_OBJECT), expected VALUE_STRING: need JSON String that contains type id (for subtype of java.lang.Object) at [Source: (ByteArrayInputStream); line: 1, column: 9] (through reference chain: java.util.HashMap["map"])

Я обнаружил, что когда я удаляю все таблицы метаданных пакета и воссоздаю их с нуля, пакет снова работает. Похоже, формат метаданных JSON изменился на этот

{"name":"","sender":"145844","id":"","nav":"","created":"160909"}

Я не хочу удалять старые данные, чтобы снова заставить эту работу работать, есть ли способ исправить это?

Кто-нибудь еще пробовал сделать это обновление? Было бы неплохо узнать, есть ли какие-нибудь критические изменения, которые я, возможно, не заметил.

Спасибо

Вероятно, это связано с jira.spring.io/browse/BATCH-2680. Вы пробовали использовать Spring Batch версии 4.0.1?

Mahmoud Ben Hassine 03.04.2018 10:35

@MahmoudBenHassine Я уже пробовал это, но все равно получаю то же исключение Jackson MismatchedInputException.

Viestuts 03.04.2018 11:06
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
3
2
4 159
3

Ответы 3

До Spring Batch 4 механизм сериализации по умолчанию для ExecutionContext был через XStream. Теперь он по умолчанию использует Jackson, который нет совместим со старым форматом сериализации. У нас все еще доступна старая версия (XStreamExecutionContextStringSerializer), но вам нужно будет настроить ее самостоятельно, реализовав BatchConfigurer и переопределив конфигурацию в JobRepositoryFactoryBean.

Для записи, это связано с этой проблемой: https://jira.spring.io/browse/BATCH-2575.

Не могли бы вы и здесь ответить stackoverflow.com/questions/51688838/…?

Jeff Cook 04.08.2018 21:27

Я не совсем понимаю ответ. Не могли бы вы вставить код, подтверждающий ваш ответ? Будучи новичком в Spring Batch, трудно понять, что вы говорите

Jeff Cook 24.08.2018 20:47

Основываясь на ответе Майкла выше, этот блок кода помог мне расширить конфигурацию по умолчанию - мне пришлось подключить сериализатор как к JobRepository.class, так и к JobExplorer.class:

@Configuration
@EnableBatchProcessing
MyBatchConfigurer extends DefaultBatchConfigurer {
    private final DataSource dataSource;

    @Autowired
    public BatchConfiguration(final DataSource dataSource) throws Exception {
        this.dataSource = dataSource;
    }

    @Bean
    ExecutionContextSerializer getSerializer() {
        return new XStreamExecutionContextStringSerializer();
    }


    @Override
    protected JobRepository createJobRepository() throws Exception {
        final JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
        factory.setDataSource(dataSource);
        factory.setSerializer(getSerializer());
        factory.setTransactionManager(getTransactionManager());
        factory.afterPropertiesSet();
        return factory.getObject();
    }

    @Override
    protected JobExplorer createJobExplorer() throws Exception {
        final JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean();
        jobExplorerFactoryBean.setDataSource(dataSource);
        jobExplorerFactoryBean.setSerializer(getSerializer());
        jobExplorerFactoryBean.afterPropertiesSet();
        return jobExplorerFactoryBean.getObject();
    }
}

очень полезно tnx. Но моя текущая конфигурация также включает публичный метод \ @Bean JobExecutionDao jobExecutionDao (). Я не могу изменить это с помощью DefaultBatchConfigurer. Любые идеи? не уверен, что могу оставить его как "фасоль" и не отменять

Spring 02.04.2019 15:46

В решении @anotherdave и @ michael-minella вы также можете заменить простой XStreamExecutionContextStringSerializer экземпляром следующего класса. Он принимает оба формата при десериализации и сериализуется в новый формат.

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.batch.core.repository.ExecutionContextSerializer;
import org.springframework.batch.core.repository.dao.Jackson2ExecutionContextStringSerializer;
import org.springframework.batch.core.repository.dao.XStreamExecutionContextStringSerializer;


/**
 * Enables Spring Batch 4 to read both ExecutionContext entries written by ealier versions and the Spring 5 format. Entries are
 * written in Spring 5 format.
 */
@SuppressWarnings("deprecation")
class XStreamOrJackson2ExecutionContextSerializer implements ExecutionContextSerializer {
    private final XStreamExecutionContextStringSerializer xStream = new XStreamExecutionContextStringSerializer();
    private final Jackson2ExecutionContextStringSerializer jackson = new Jackson2ExecutionContextStringSerializer();

    public XStreamOrJackson2ExecutionContextSerializer() throws Exception {
        xStream.afterPropertiesSet();
    }

    // The caller closes the stream; and the decoration by ensureMarkSupported does not need any cleanup.
    @SuppressWarnings("resource")
    @Override
    public Map<String, Object> deserialize(InputStream inputStream) throws IOException {
        InputStream repeatableInputStream = ensureMarkSupported(inputStream);
        repeatableInputStream.mark(Integer.MAX_VALUE);

        try {
            return jackson.deserialize(repeatableInputStream);
        } catch (JsonProcessingException e) {
            repeatableInputStream.reset();
            return xStream.deserialize(repeatableInputStream);
        }
    }

    private static InputStream ensureMarkSupported(InputStream in) {
        return in.markSupported() ? in : new BufferedInputStream(in);
    }

    @Override
    public void serialize(Map<String, Object> object, OutputStream outputStream) throws IOException {
        jackson.serialize(object, outputStream);
    }
}

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