Ничего не имею - нормальный город, был там пару раз, когда по Алтаю ходил. А что касается вашего опыта, то он, как и возраст, не всегда является залогом мудрости.
Вы всё правильно пишите. Если брать в расчёт только Россию. И да, рост благосостояния сербов, никак не влияет на Барнаул в ваших координатах. А всё что глобальнее для вас утопия.
В общем, я с вами согласен - в рамках вашего восприятия мира вы действуете максимально эффективно.
Это же ваша фраза - “Налогов плачу больше, и пользы от меня тоже больше стало ;-Р”? А как распределяются налоги в Германии я не знаю. А в России… Ну вы там живете. Вам виднее. Глобально, они всё равно реинвестируются, в детскую плашадку или в ракету (космическую) - так что я спокоен :)
Ну вы же понимаете, что это просто масштаб. Вы оба глобально поднимаете Землю. Если идти до деталей, то если бы вы платили налог в Барнауле а не в СПб, то для Барнаула толку было бы больше. А если глобально, то для Земли налоги Neusserа имеют большый вес.
А у вас не пойми что. Если с точки зрения налогов смотреть.
это не прямо 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.
Ничего не имею - нормальный город, был там пару раз, когда по Алтаю ходил. А что касается вашего опыта, то он, как и возраст, не всегда является залогом мудрости.
Вы всё правильно пишите. Если брать в расчёт только Россию. И да, рост благосостояния сербов, никак не влияет на Барнаул в ваших координатах. А всё что глобальнее для вас утопия.
В общем, я с вами согласен - в рамках вашего восприятия мира вы действуете максимально эффективно.
Ну человек же из Барнаула - не надо от него много требовать.
Это же ваша фраза - “Налогов плачу больше, и пользы от меня тоже больше стало ;-Р”? А как распределяются налоги в Германии я не знаю. А в России… Ну вы там живете. Вам виднее. Глобально, они всё равно реинвестируются, в детскую плашадку или в ракету (космическую) - так что я спокоен :)
Просто всё зависит от широты мышления. Для жителя деревушки в Карелии США тоже могут казаться чем-то из области фантастики.
Мы, вообще-то, о налогах говорим. А в Германии они заметно выше, чем в Москве.
Ну вы же понимаете, что это просто масштаб. Вы оба глобально поднимаете Землю. Если идти до деталей, то если бы вы платили налог в Барнауле а не в СПб, то для Барнаула толку было бы больше. А если глобально, то для Земли налоги Neusserа имеют большый вес.
А у вас не пойми что. Если с точки зрения налогов смотреть.
@Kaluchi я там пару багов добавил - https://github.com/kaluchi/jdtbridge/issues
Мой опыт:
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.