Spring FrameworkMiddleExperience

Расскажите о случае, когда вы проектировали или улучшали сервис на Spring Framework с учётом транзакций, безопасности, фоновых задач или мониторинга.

Проектировал платёжный сервис на Spring Framework 5: @Transactional с REQUIRES_NEW для аудит-лога, HMAC-валидация вебхуков через OncePerRequestFilter, Transactional Outbox для надёжной отправки уведомлений, кастомные метрики через Micrometer.

Контекст задачи

На одном из проектов я проектировал платёжный микросервис на Spring Framework 5.3 (без Spring Boot). Задача: принимать вебхуки от платёжного шлюза, записывать события в БД, отправлять уведомления, собирать метрики — надёжно, с retry и без потери данных.

Транзакции

Использовал @Transactional на сервисном слое с propagation = REQUIRED и явным rollbackFor = PaymentException.class. Для аудит-лога (не должен откатываться вместе с основной транзакцией) вынес в отдельный сервис с REQUIRES_NEW. Настроил PlatformTransactionManager вручную через @Configuration:

@Bean
public PlatformTransactionManager transactionManager(DataSource ds) {
    return new DataSourceTransactionManager(ds);
}

Безопасность

Подключил Spring Security 5 с кастомным WebSecurityConfigurerAdapter: HMAC-валидация подписи вебхука в OncePerRequestFilter, IP-allowlist через HasIpAddress. Все эндпоинты, кроме /webhook, требовали JWT.

Фоновые задачи

Уведомления отправлял через @Scheduled(fixedDelay = 5000) с выборкой из outbox-таблицы (паттерн Transactional Outbox). Задача атомарно обновляла статус записи и отправляла email — без риска потери события при перезапуске.

Мониторинг

Зарегистрировал кастомные метрики через Micrometer MeterRegistry: счётчик успешных и неудачных платежей, histogram времени обработки вебхука. Подключил PrometheusRegistry и настроил Grafana-алерт на payment_failures_total > 10 за 5 минут.

Подводные камни

  • Self-invocation: при вызове @Transactional-метода через this транзакция не открывалась — потребовалась инъекция себя через ApplicationContext.
  • @Scheduled без ShedLock запускался на всех подах при горизонтальном масштабировании — двойная отправка уведомлений.
  • При ручной конфигурации без Spring Boot важно явно включить @EnableTransactionManagement и @EnableScheduling.
  • Spring Security 5 WebSecurityConfigurerAdapter deprecated в 6.x — при миграции потребовалась переработка конфигурации.
  • Без @EnableAspectJAutoProxy(proxyTargetClass = true) AOP-прокси не оборачивали классы без интерфейсов.
  • Transactional Outbox требует индекс на поле статуса — без него full scan таблицы на каждом тике scheduler-а.

What hurts your answer

  • Выдумывать опыт или говорить слишком общими фразами
  • Не объяснять свою личную роль в работе с Spring Framework
  • Не показывать результат, метрики или извлечённые уроки

What they're listening for

  • Может подготовить честный пример использования Spring Framework
  • Показывает свою роль, решения и результат
  • Умеет рефлексировать над trade-offs и уроками

Related topics