это не прямо SB4 миграция, но в 7 Спринге появились удобные @ImportHttpServices анотации, так что мы мигровали одновременно с SB4. Проблема - @AutoConfigureMockRestServiceServer не работает если в контексте несколько груп. Моё решение
import org.springframework.boot.restclient.test.MockServerRestClientCustomizer;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.RestClient;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class MockServerRegistry {
private final Map<String, MockServerRestClientCustomizer> customizers = new ConcurrentHashMap<>();
private final Map<String, RestClient.Builder> builderByGroup = new ConcurrentHashMap<>();
public void put(String group, RestClient.Builder builder) {
builderByGroup.put(group, builder);
customizers.computeIfAbsent(group, _ -> new MockServerRestClientCustomizer()).customize(builder);
}
public MockRestServiceServer get(String group) {
RestClient.Builder builder = builderByGroup.get(group);
if (builder == null) {
throw new IllegalStateException("No builder for group: " + group);
}
return customizers.get(group).getServer(builder);
}
}
@Configuration
@SuppressWarnings("static-method")
public class TestConfiguration {
@Bean
MockServerRegistry groupRestClientBuildersRegistry() {
return new MockServerRegistry();
}
@Bean
RestClientHttpServiceGroupConfigurer groupConfigurer(MockServerRegistry registry) {
return groups -> groups.forEachGroup((group, builder, _) -> {
registry.put(group.name(), builder);
});
}
}
BTW property для base URL: spring.http.serviceclient.my_group.base-url
Jackson migration
Поменялись названия пропертей SP3:
#Rest configuration (modules JavaTimeModule and Jdk8Module loads automaticaly)
#AfterburnerModule defined as a bean in the configuration
# Keep numeric timestamps (instead of ISO-8601 strings)
spring.jackson.serialization.write-dates-as-timestamps=true
# Milliseconds precision (not nanoseconds)
spring.jackson.serialization.write-date-timestamps-as-nanoseconds=false
spring.jackson.deserialization.read-date-timestamps-as-nanoseconds=false
# avoid locale/host drift
spring.jackson.time-zone=UTC
# Ignore unknown JSON properties on deserialization
spring.jackson.deserialization.fail-on-unknown-properties=false
# Exclude null/empty properties from serialization
spring.jackson.default-property-inclusion=non_empty
SB4:
#Jackson configuration
#BlackbirdModule defined as a bean in the configuration
# Keep numeric timestamps (instead of ISO-8601 strings)
spring.jackson.datatype.datetime.write-dates-as-timestamps=true
# Milliseconds precision (not nanoseconds)
spring.jackson.datatype.datetime.write-date-timestamps-as-nanoseconds=false
spring.jackson.datatype.datetime.read-date-timestamps-as-nanoseconds=false
# avoid locale/host drift
spring.jackson.time-zone=UTC
# Ignore unknown JSON properties on deserialization
spring.jackson.deserialization.fail-on-unknown-properties=false
# Exclude null/empty properties from serialization
spring.jackson.default-property-inclusion=non_empty
Все остальное по мелочам: например стартеры нормально решает АйЯй. Кстати ему можно отдать и финальную проверку. По-крайней мере у меня он нашел несколько вешей которыя я пропустил - типа устаревших пропертей, которые еще поддерживаются, но скоро будут удалены, и которые логично поменять в рамках миграции.
Как раз сегодня пришло письмо от Hetzner - бла, бла, бла, память диски... мы вам цену увеличим - previous price New price as of 1 April 2026 € 27.00 € 27.81 В общем на 3% цена выросла.
Field injection удобнее, когда есть наследование. Не могу сказать, что это очень часто, но иногда встркчается. И field injection позволяет добавить зависимость в базовый класс не переписывая конструкторы у всех потомков.
Можно ограничить фронт на named query, которые рассматриваются беком. Таким образом, сохраняется гибкость, а при возникновении проблем можно или попробовать оптимизировать запрос, или заточить бекенд.
Честно говоря всегда использовал вариант с квалификатором. Вариант с expression плох еще тем, что я всегда выставляю unmappedSourcePolicy = ERROR, unmappedTargetPolicy = ERROR а по expression MapStruct не поймет, что Source поле trueName используется.
А с помощью assertj можно проверить у вызова, который возвращает Map<String, List>, где MyBean содержит List у которых есть атрибут size, что есть Event c size = 10?
Смысл, что вам может вернуться довольно вложенное дерево структур, а вы с помощью hamcrest можете описать выборочную проверку только нужных вам атрибутов на любом уровне вложенности.
Возможно, это можно и с assertj, я просто не знаю...
Да, он LTS. Это важно, если есть политика в компании использовать только LTS в продукции. Так что для некоторых это не просто, что нового в 25, а что нового в сравнении с 21. Для меня, например, важны улучшенные LocalThread - в 21 успели наступить на грабли с synchronize.
Потому что разработка на PHP требует офигенной самодисциплины, чтобы не скатиться в говнокод. В Jave говнокод разумеется тоже возможен, но в ней больше естественных барьеров. Например, тот же деплой в Java это осознанное действие, не всегда даже доступное разработчику.
Я пишу на беке, но иногда нужен фронт. Для меня выбор был сделан уже давно и похоже навсегда - для фронта я использую GWT и только его :) Так что подобные статьи у меня вызывают искренний вопрос - "о чём говорят все эти люди?" :)
И в любой стране ЕС, например, подобные идеи сдохнут не родившись.
В Чехии уже давно существует Identity občana (идентификация гражданина), с её помощью можно зайти на любой государственный сайт, некоторые магазины тоже её поддерживают. В целом это не один способ, а набор разных, можно пользоваться любым. https://www.identita.gov.cz/
Не вижу я тут аналогии. IMHO в описанном мной примере самым простым решением было просто игнорировать все что пользователь нажал между первым esc и показом диалога и всё.
Мой опыт:
RestTemplate -> RestClient
это не прямо SB4 миграция, но в 7 Спринге появились удобные @ImportHttpServices анотации, так что мы мигровали одновременно с SB4.
Проблема - @AutoConfigureMockRestServiceServer не работает если в контексте несколько груп. Моё решение
и в тесте
BTW property для base URL:
spring.http.serviceclient.my_group.base-urlJackson migration
Поменялись названия пропертей
SP3:
SB4:
Все остальное по мелочам: например стартеры нормально решает АйЯй. Кстати ему можно отдать и финальную проверку. По-крайней мере у меня он нашел несколько вешей которыя я пропустил - типа устаревших пропертей, которые еще поддерживаются, но скоро будут удалены, и которые логично поменять в рамках миграции.
Как раз сегодня пришло письмо от Hetzner - бла, бла, бла, память диски... мы вам цену увеличим -
previous price New price as of 1 April 2026
€ 27.00 € 27.81
В общем на 3% цена выросла.
Field injection удобнее, когда есть наследование. Не могу сказать, что это очень часто, но иногда встркчается. И field injection позволяет добавить зависимость в базовый класс не переписывая конструкторы у всех потомков.
Можно ограничить фронт на named query, которые рассматриваются беком. Таким образом, сохраняется гибкость, а при возникновении проблем можно или попробовать оптимизировать запрос, или заточить бекенд.
Честно говоря всегда использовал вариант с квалификатором. Вариант с expression плох еще тем, что я всегда выставляю unmappedSourcePolicy = ERROR, unmappedTargetPolicy = ERROR а по expression MapStruct не поймет, что Source поле trueName используется.
А с помощью assertj можно проверить у вызова, который возвращает Map<String, List>, где MyBean содержит List у которых есть атрибут size, что есть Event c size = 10?
Смысл, что вам может вернуться довольно вложенное дерево структур, а вы с помощью hamcrest можете описать выборочную проверку только нужных вам атрибутов на любом уровне вложенности.
Возможно, это можно и с assertj, я просто не знаю...
Есть еще мой проект https://github.com/hortonolite/hamcrestBeanMatcherApt. Автоматически генерирует и синхронизирует мачеры для бинов (JavaBean, Records)
Вот странно - статья про GIT, а ветки из Mercurial нарисовали...
Легко - поиск по ключу. Сначала вычисляется партиция, потом ищем только в ней.
Пример первый - использовать final для зависимостей/настроек?
Да, да - https://openjdk.org/projects/jdk/25/jeps-since-jdk-21
Да, он LTS. Это важно, если есть политика в компании использовать только LTS в продукции. Так что для некоторых это не просто, что нового в 25, а что нового в сравнении с 21. Для меня, например, важны улучшенные LocalThread - в 21 успели наступить на грабли с synchronize.
Посмотрите на https://github.com/Randgalt/record-builder. Я до этого тоже плевался на Java record.
Вы так пишите, будто это что-то плохое. Я, вот, уже 30 лет разработчик, и всё меня устраивает.
Потому что разработка на PHP требует офигенной самодисциплины, чтобы не скатиться в говнокод. В Jave говнокод разумеется тоже возможен, но в ней больше естественных барьеров. Например, тот же деплой в Java это осознанное действие, не всегда даже доступное разработчику.
Да, сейчас нет. Но GWT довольно мощная штука, а я в нём неплохо разбираюсь. В общем мне хватает :)
Я пишу на беке, но иногда нужен фронт. Для меня выбор был сделан уже давно и похоже навсегда - для фронта я использую GWT и только его :) Так что подобные статьи у меня вызывают искренний вопрос - "о чём говорят все эти люди?" :)
В Чехии уже давно существует Identity občana (идентификация гражданина), с её помощью можно зайти на любой государственный сайт, некоторые магазины тоже её поддерживают.
В целом это не один способ, а набор разных, можно пользоваться любым.
https://www.identita.gov.cz/
Код ниже сломается при смене
genVal()соStringnaIntegerкод с
varбудет дальше работать, но неправильно.Не вижу я тут аналогии. IMHO в описанном мной примере самым простым решением было просто игнорировать все что пользователь нажал между первым esc и показом диалога и всё.