From 7c2e75facc96306d7912ba3a9107c1e9ecead173 Mon Sep 17 00:00:00 2001 From: Marcel Date: Fri, 15 May 2026 09:51:53 +0200 Subject: [PATCH] fix(backend): switch to sentry-spring-boot-4:8.41.0 for Spring Boot 4/SF7 compatibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sentry-spring-boot-starter-jakarta 8.5.0 does not support Spring Boot 4.0 — it logs an "Incompatible Spring Boot Version" warning and its SentryAutoConfiguration crashes SF7 bean-name generation. sentry-spring-boot-4 (added in 8.21.0) is the dedicated Spring Boot 4 module with a fixed auto-configuration class. - Replace sentry-spring-boot-starter-jakarta:8.5.0 with sentry-spring-boot-4:8.41.0 - Delete SentryConfig.java — workaround no longer needed, auto-config handles init - Remove spring.autoconfigure.exclude from application.yaml + application-test.yaml - Delete SentryConfigTest.java — tested the deleted workaround class - Update ApplicationContextTest: assert Sentry.isEnabled() is false when no DSN set Co-Authored-By: Claude Sonnet 4.6 --- backend/pom.xml | 8 +-- .../familienarchiv/config/SentryConfig.java | 39 -------------- backend/src/main/resources/application.yaml | 7 --- .../ApplicationContextTest.java | 6 +-- .../config/SentryConfigTest.java | 53 ------------------- .../src/test/resources/application-test.yaml | 6 --- 6 files changed, 8 insertions(+), 111 deletions(-) delete mode 100644 backend/src/main/java/org/raddatz/familienarchiv/config/SentryConfig.java delete mode 100644 backend/src/test/java/org/raddatz/familienarchiv/config/SentryConfigTest.java diff --git a/backend/pom.xml b/backend/pom.xml index accc6293..74d513cd 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -225,11 +225,13 @@ - + io.sentry - sentry-spring-boot-starter-jakarta - 8.5.0 + sentry-spring-boot-4 + 8.41.0 diff --git a/backend/src/main/java/org/raddatz/familienarchiv/config/SentryConfig.java b/backend/src/main/java/org/raddatz/familienarchiv/config/SentryConfig.java deleted file mode 100644 index 6b541385..00000000 --- a/backend/src/main/java/org/raddatz/familienarchiv/config/SentryConfig.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.raddatz.familienarchiv.config; - -import io.sentry.Sentry; -import jakarta.annotation.PostConstruct; -import org.raddatz.familienarchiv.exception.DomainException; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Configuration; - -// SentryAutoConfiguration is excluded (see application.yaml) because Spring Boot 4 / Spring -// Framework 7 cannot generate a bean name for the triply-nested -// SentryAutoConfiguration$HubConfiguration$SentrySpanRestClientConfiguration class. -// This bean replicates the essential init: DSN, environment, sample rate, PII guard, -// and DomainException filter. -@Configuration -public class SentryConfig { - - @Value("${sentry.dsn:}") - private String dsn; - - @Value("${sentry.environment:dev}") - private String environment; - - @Value("${sentry.traces-sample-rate:1.0}") - private double tracesSampleRate; - - @PostConstruct - public void init() { - if (dsn == null || dsn.isBlank()) { - return; - } - Sentry.init(options -> { - options.setDsn(dsn); - options.setEnvironment(environment); - options.setTracesSampleRate(tracesSampleRate); - options.setSendDefaultPii(false); - options.addIgnoredExceptionForType(DomainException.class); - }); - } -} diff --git a/backend/src/main/resources/application.yaml b/backend/src/main/resources/application.yaml index 6bb21378..ead3d9e8 100644 --- a/backend/src/main/resources/application.yaml +++ b/backend/src/main/resources/application.yaml @@ -38,13 +38,6 @@ spring: starttls: enable: true - autoconfigure: - exclude: - # SentryAutoConfiguration fails on Spring Boot 4/Spring Framework 7: Spring cannot generate a - # bean name for the triply-nested SentryAutoConfiguration$HubConfiguration$SentrySpanRestClientConfiguration. - # Sentry is initialized manually via SentryConfig instead. See #580. - - io.sentry.spring.boot.jakarta.SentryAutoConfiguration - server: # Behind Caddy/reverse proxy: trust X-Forwarded-{Proto,For,Host} so that # request.getScheme(), redirect URLs, and Spring Session "Secure" cookies diff --git a/backend/src/test/java/org/raddatz/familienarchiv/ApplicationContextTest.java b/backend/src/test/java/org/raddatz/familienarchiv/ApplicationContextTest.java index cd872f7f..f7eaa7b9 100644 --- a/backend/src/test/java/org/raddatz/familienarchiv/ApplicationContextTest.java +++ b/backend/src/test/java/org/raddatz/familienarchiv/ApplicationContextTest.java @@ -31,8 +31,8 @@ class ApplicationContextTest { } @Test - void sentry_auto_configuration_is_excluded_from_context() { - // SentryAutoConfiguration crashes on Spring Boot 4/SF7 — must stay excluded (see #580) - assertThat(ctx.containsBean("sentryAutoConfiguration")).isFalse(); + void sentry_is_disabled_when_no_dsn_is_configured() { + // application-test.yaml has no sentry.dsn — SDK must stay inactive so tests are clean + assertThat(io.sentry.Sentry.isEnabled()).isFalse(); } } diff --git a/backend/src/test/java/org/raddatz/familienarchiv/config/SentryConfigTest.java b/backend/src/test/java/org/raddatz/familienarchiv/config/SentryConfigTest.java deleted file mode 100644 index 022a1b63..00000000 --- a/backend/src/test/java/org/raddatz/familienarchiv/config/SentryConfigTest.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.raddatz.familienarchiv.config; - -import io.sentry.Sentry; -import org.junit.jupiter.api.Test; -import org.mockito.MockedStatic; -import org.springframework.test.util.ReflectionTestUtils; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mockStatic; -import static org.mockito.Mockito.times; - -class SentryConfigTest { - - @Test - void init_does_not_call_sentry_when_dsn_is_blank() { - SentryConfig config = new SentryConfig(); - ReflectionTestUtils.setField(config, "dsn", ""); - ReflectionTestUtils.setField(config, "environment", "test"); - ReflectionTestUtils.setField(config, "tracesSampleRate", 1.0); - - try (MockedStatic sentryMock = mockStatic(Sentry.class)) { - config.init(); - sentryMock.verifyNoInteractions(); - } - } - - @Test - void init_calls_sentry_init_when_dsn_is_set() { - SentryConfig config = new SentryConfig(); - ReflectionTestUtils.setField(config, "dsn", "https://key@glitchtip.example.com/1"); - ReflectionTestUtils.setField(config, "environment", "test"); - ReflectionTestUtils.setField(config, "tracesSampleRate", 0.5); - - try (MockedStatic sentryMock = mockStatic(Sentry.class)) { - config.init(); - sentryMock.verify(() -> Sentry.init(any(Sentry.OptionsConfiguration.class)), times(1)); - } - } - - @Test - void init_does_not_call_sentry_when_dsn_is_null() { - SentryConfig config = new SentryConfig(); - ReflectionTestUtils.setField(config, "dsn", null); - ReflectionTestUtils.setField(config, "environment", "test"); - ReflectionTestUtils.setField(config, "tracesSampleRate", 1.0); - - try (MockedStatic sentryMock = mockStatic(Sentry.class)) { - config.init(); - sentryMock.verifyNoInteractions(); - } - } -} diff --git a/backend/src/test/resources/application-test.yaml b/backend/src/test/resources/application-test.yaml index de2e9347..e1a2f913 100644 --- a/backend/src/test/resources/application-test.yaml +++ b/backend/src/test/resources/application-test.yaml @@ -13,12 +13,6 @@ spring: password: test mail: host: localhost - autoconfigure: - exclude: - # SentryAutoConfiguration fails on Spring Boot 4/Spring Framework 7: Spring cannot generate a - # bean name for the triply-nested SentryAutoConfiguration$HubConfiguration$SentrySpanRestClientConfiguration. - # Sentry is wired manually via SentryConfig instead. See #580. - - io.sentry.spring.boot.jakarta.SentryAutoConfiguration # Disable OTel SDK entirely in tests — prevents auto-configuration from loading resource providers # (e.g. AzureAppServiceResourceProvider) that fail against the semconv version used here.