Skip to content

feat: upgrade to Spring Boot 4.1.1 and Spring AI 2.0.1 - #23

Merged
epugh merged 32 commits into
apache:mainfrom
adityamparikh:sb4
Oct 7, 2026
Merged

epugh merged 32 commits into
apache:mainfrom
adityamparikh:sb4

Conversation

@adityamparikh

@adityamparikh adityamparikh commented Dec 13, 2025 •

Copy link
Copy Markdown
Contributor

Upgrades the server to Spring Boot 4.1.1 and Spring AI 2.0.1, with Jackson 3, the MCP Java SDK 2.0.1, mcp-server-security 0.1.14 and Spring Boot's own OpenTelemetry starter. All are GA on Maven Central; no milestone repositories are needed.

Breaking changes (HTTP profile only)

  • OTLP export moves from gRPC on port 4317 to OTLP/HTTP on 4318, with one complete URL per signal. OTEL_TRACES_URL changes meaning: it was a base endpoint shared by all three signals (http://collector:4317) and is now the full traces URL (http://collector:4318/v1/traces). A value carried over unchanged does not error; traces simply stop arriving. OTEL_METRICS_URL and OTEL_LOGS_URL are new.
  • /actuator/prometheus is removed. Metrics leave over OTLP only, and now include the full Micrometer set (JVM, Tomcat, Spring Security, per-tool timers). Timers are exported in milliseconds (http_server_requests_milliseconds_*, method_observed_milliseconds_*).
  • @Observed span names change from search-service#search to SearchService#search.

See docs/observability.md.

Versions

Component main This PR
Spring Boot 3.5.14 4.1.1
Spring AI 1.1.7 2.0.1
MCP Java SDK 0.18.x (transitive) 2.0.1, via mcp-bom imported ahead of spring-ai-bom (Spring AI 2.0.1 resolves 2.0.0; 2.0.1 fixes stateless-server error handling, which is our HTTP profile, and bounds reads on the HTTP and STDIO transports)
mcp-server-security 0.0.6 0.1.14 (Spring Security 7) — catalog change only, McpServerOAuth2Configurer API unchanged
OpenTelemetry instrumentation BOM 2.11.0 + opentelemetry-spring-boot-starter spring-boot-starter-opentelemetry (SDK managed by Boot) + opentelemetry-logback-appender-1.0 2.28.1-alpha
JSpecify explicit 1.0.0 dependency transitive from Spring Framework 7 (spring-core)
Testcontainers 1.21.3 2.0.5 (modules renamed testcontainers-junit-jupiter, -solr, -grafana)
CycloneDX Gradle plugin 2.4.1 3.4.1; buildSrc's cyclonedx-core-java 10.2.1 → 13.1.0 to match it
GraalVM native plugin 0.10.6 1.1.14
Spotless 7.0.2 8.9.0 (Eclipse JDT pinned to 4.34, ktlint to 1.5.0, so formatting output is unchanged)
Gradle 9.7.1 9.8.0 (wrapper retries = 3 now set on the wrapper task in build.gradle.kts, so regenerating the wrapper keeps it)
Others Error Prone 2.50.0, NullAway 0.14.2, Error Prone plugin 5.1.1, Jib 3.5.4, commonmark 0.30.0, Apache RAT plugin 0.11.0, buildSrc JUnit 6.1.3

Code changes

Jackson 3. tools.jackson.databind replaces com.fasterxml.jackson.databind in SolrConfig, JsonResponseParser, JsonDocumentCreator, JsonUtils, CollectionService and SchemaService. JacksonException replaces IOException / JsonProcessingException in catch clauses; JsonNode.properties() / asString() replace fields() / asText(). Annotations stay in com.fasterxml.jackson.annotation. Test MCP clients build their transports with io.modelcontextprotocol.json.jackson3.JacksonMcpJsonMapper.

MCP annotations. org.springaicommunity.mcp.annotation → org.springframework.ai.mcp.annotation (now part of Spring AI) in all five service classes, including AliasService. MCP SDK 2.0's CompleteArgument rejects a null value at construction, so CollectionServiceTest's null-completion case now asserts that instead of calling the service.

Modular starters. spring-boot-starter-web → -webmvc + -json; -aop → -aspectj (what @Observed needs on Boot 4); modular test starters (-webmvc-test, -actuator-test, -opentelemetry-test). The test classpath no longer carries spring-ai-starter-mcp-client: the tests build their clients from the MCP Java SDK directly.

Observability. spring-boot-starter-opentelemetry provides traces, metrics and OTLP log export; micrometer-registry-otlp replaces the Prometheus registry. The OTel logback appender is installed by a new InstallOpenTelemetryAppender bean (@Profile("http")), since Boot 4 does not bundle it. application-http.properties uses management.opentelemetry.* / management.otlp.* endpoints. opentelemetry-proto resolves to 1.10.0-alpha, the version micrometer-registry-otlp 1.17.1 is built against, alongside Boot's protobuf-java 4.35.1, with no version override. DistributedTracingTest is updated for the new span names and the management.tracing.export.otlp.enabled property.

Profiles and logging. application-stdio.properties excludes the Boot 4.1 security auto-configuration classes (org.springframework.boot.security.autoconfigure.SecurityAutoConfiguration and ...actuate.web.servlet.ManagementWebSecurityAutoConfiguration); the Boot 3 names would be silently ignored. It also stops setting logging.pattern.console=: Boot copies that value into the JVM-wide CONSOLE_LOG_PATTERN system property and logback rejects an empty pattern, and since Framework 7 pauses a test's context on context switch, a stdio-profile test running first broke every later http-profile context in the same JVM. STDIO stays silent because logback-spring.xml declares no appenders for it. LoggingConfigurationTest guards against the empty pattern returning.

GraalVM native. MemberCategory.DECLARED_FIELDS (marked for removal) → ACCESS_DECLARED_FIELDS. New hints for the SolrJ 10 API model types (SolrJerseyResponse, ErrorInfo, CoreStatusResponse and nested types), the relocated org.springframework.ai.mcp.annotation.context.DefaultMetaProvider, and Solr's EnvToSyspropMappings.properties / DeprecatedSystemPropertyMappings.properties resources. Error Prone / NullAway are disabled for the generated compileAotJava / compileAotTestJava sources. The manual org.junit.platform.* --initialize-at-build-time entries for the test binary are dropped; GraalVM native plugin 0.11+ handles that itself, and keeping them fails nativeTestCompile.

SBOM. cyclonedx 3.x splits the work into cyclonedxDirectBom (resolves dependencies, owns includeConfigs) and cyclonedxBom (aggregates). Boot 4.1's CyclonedxPluginAction configures the output for 3.x and embeds it in the bootJar, so the manual output wiring is gone; the direct task is scoped to productionRuntimeClasspath, because at defaults it adds ~100 test-only components that scanners would read as shipped. The license-notice plugin reads the SBOM from build/reports/cyclonedx/application.cdx.json. Resolves #186.

compose.yaml. grafana/otel-lgtm pinned to 0.33.0 instead of latest, the same version the Testcontainers tests use; Grafana and the OTLP receivers bind to loopback by default (GRAFANA_BIND / OTLP_BIND to override), and anonymous access is Viewer rather than Admin (GF_ANON_ROLE=Admin to opt in).

Docs. AGENTS.md, README.md, docs/observability.md (per-signal endpoints, Micrometer metric names in milliseconds, upgrade callout), new dev-docs/Observability.md, dev-docs/DEVELOPMENT.md, dev-docs/graalvm-native-image.md (OTel version alignment), docs/security/stdio.md, docs/security/keycloak.md.

Verification

Command Result
./gradlew build (Java 25) 465 tests, 0 failed, 0 skipped
./gradlew nativeTest -Pnative (GraalVM CE 25.0.2) 462 found, 304 passed, 0 failed, 158 skipped (all Mockito-based unit tests, @DisabledInNativeImage)
buildSrc tests (LicenseNoticeTasksTest) 12 passed
./gradlew rat spotlessCheck pass
OTLP metrics export (jar in HTTP mode against grafana/otel-lgtm) the app's Micrometer series reach Prometheus, /mcp request count matches the calls made
./gradlew dockerIntegrationTest not run

The bootJar contains META-INF/sbom/application.cdx.json, META-INF/LICENSE and META-INF/NOTICE. No automated test configures an OAuth2 issuer, so McpServerOAuth2Configurer from the upgraded mcp-server-security is not exercised by the suite.

References

🤖 Generated with Claude Code

@adityamparikh
adityamparikh marked this pull request as draft December 16, 2025 22:10
@epugh

epugh commented Jan 6, 2026

Copy link
Copy Markdown
Contributor

Thanks for the update on this one... We will merge when we get an official Spring AI 2.0 release!

@epugh epugh changed the title feat: Spring Boot 4 upgrade feat: Spring Boot 4 + Spring AI 2.0 upgrade Jan 6, 2026
epugh pushed a commit that referenced this pull request Mar 9, 2026
* feat: implement observability with OpenTelemetry and Micrometer, add logging configuration, and enable tracing with annotation support

* test(observability): implement distributed tracing tests for Spring Boot 3.5

Add comprehensive distributed tracing test suite using SimpleTracer from
micrometer-tracing-test library. This is the Spring Boot 3-native approach
for testing observability without requiring external infrastructure.

Key changes:
- Add DistributedTracingTest with 6 passing tests for @observed methods
- Add OpenTelemetryTestConfiguration providing SimpleTracer as @primary bean
- Add OtlpExportIntegrationTest (disabled due to Jetty dependency issue)
- Add LgtmAssertions and TraceAssertions utility classes
- Add micrometer-tracing-bridge-otel to bridge Observation API to OpenTelemetry
- Add spring-boot-starter-aop for @observed annotation support
- Add test dependencies: micrometer-tracing-test, awaitility, Jetty modules

Test results:
- DistributedTracingTest: 6/6 tests passing
- Spans successfully captured from @observed annotations
- Build: SUCCESS (219 tests passing, 0 failures)

Spring Boot 3.5 uses Micrometer Observation → Micrometer Tracing → OpenTelemetry
bridge, which differs from Spring Boot 4's direct OpenTelemetry integration.

Adapted from PR #23 (Spring Boot 4 implementation) with modifications for
Spring Boot 3.5 architecture and APIs.

---------

Signed-off-by: adityamparikh <aditya.m.parikh@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
@adityamparikh adityamparikh reopened this May 2, 2026
@epugh

epugh commented May 2, 2026

Copy link
Copy Markdown
Contributor

Looks like you have some conflicts.. I think you need to update from main to pick up the new ci stuff?

adityamparikh and others added 5 commits August 19, 2026 07:35
Migrate the Solr MCP server from Spring Boot 3.5.x / Spring AI 1.1.x to
Spring Boot 4.1.0 and Spring AI 2.0.0 GA.

Highlights:
- Jackson 3: tools.jackson.databind replaces com.fasterxml.jackson.databind
  (annotations stay in com.fasterxml.jackson.annotation); the MCP SDK uses the
  mcp-json-jackson3 module. JacksonException replaces IOException/
  JsonProcessingException; JsonNode.properties()/asString() replace
  fields()/asText().
- MCP annotations: package moved from org.springaicommunity.mcp.annotation to
  org.springframework.ai.mcp.annotation (now part of Spring AI core).
- Modular starters: spring-boot-starter-web -> -webmvc + -json; explicit
  spring-ai-autoconfigure-mcp-server-common (no longer pulled transitively
  after Spring AI 2.0.0-M7); modular test starters (actuator / opentelemetry /
  webmvc).
- Observability: spring-boot-starter-opentelemetry (SB4 idiomatic) for traces,
  metrics, and OTLP log export, replacing the manual OTel BOM +
  micrometer-tracing-bridge-otel approach; spring-boot-starter-aspectj for
  @observed; OpenTelemetry logback appender installed programmatically via
  InstallOpenTelemetryAppender; management.opentelemetry.* OTLP properties.
- Testcontainers 2.x module/package renames.
- JSpecify is built into Spring Boot 4, so the explicit dependency is dropped.
- GraalVM native: AOT NullAway exclusions for generated sources, JUnit-platform
  build-time init, DefaultMetaProvider + Solr API model reflection hints, and
  per-profile AOT documentation; dependency-resolution alignment for
  opentelemetry-proto and opentelemetry-api-incubator against the Spring Boot
  4.1.0 BOM.

Both Spring Boot 4.1.0 and Spring AI 2.0.0 are GA on Maven Central, so no
milestone repositories are required.

Scope is limited to the Spring Boot 4 / Spring AI 2.0 upgrade and its required
changes; unrelated CI, Solr-version-matrix, and Solr 10 metrics changes are
intentionally excluded.

Signed-off-by: adityamparikh <aditya.m.parikh@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… JSON test to Jackson 3

Resolving PR #23 (sb4 -> main) onto current main surfaced two build breaks
that the conflict resolution had to fix:

1. SBOM completeness gate failed. `generateBinaryLicense` compares the
   CycloneDX SBOM against the shipped `productionRuntimeClasspath`, but
   `cyclonedxBom` was never configured for it. Spring Boot's
   `CycloneDxPluginAction` only auto-configures the cyclonedx plugin version it
   recognizes (3.x for Spring Boot 4.1.0); we stay pinned to 2.4.1 because
   cyclonedx 3.x fails at configuration time on Gradle 9.4.1 (variant-mutation
   conflict on `:cyclonedxDirectBom`). With 2.4.1 unrecognized, the task fell
   back to plugin defaults: it wrote `build/reports/bom.json` (not
   `application.cdx.json`) and scanned the wrong configuration set (stale
   Jackson 2, none of the Spring Boot 4 modular jars), so the gate reported
   ~30 bundled deps "absent from the SBOM". Configure the task explicitly:
   `outputName = "application.cdx"` and
   `includeConfigs = [productionRuntimeClasspath]`.

2. `JsonResponseParserContentTypesTest` (added on main via #90) imported the
   Jackson 2 `com.fasterxml.jackson.databind.ObjectMapper`, but SB4 migrated
   `JsonResponseParser` to Jackson 3. Use `tools.jackson.databind.json.JsonMapper`
   (the project's Jackson 3 mapper-construction pattern) instead.

Update the AGENTS.md SBOM Architecture note to match the explicit wiring.
`./gradlew build` is green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: adityamparikh <aditya.m.parikh@gmail.com>
The lgtm service published Grafana on "3000:3000" (all interfaces) while
setting GF_AUTH_ANONYMOUS_ORG_ROLE=Admin, so any host that could reach the
developer's machine had unauthenticated admin access to the observability
stack - no credentials, no prompt.

Verified against the running container:
- Old config: anonymous POST /api/folders -> HTTP 200, folder created.
- New config: same request      -> HTTP 403 "folders:create" denied.
- Grafana answers on 127.0.0.1:3000 but the LAN address refuses the
  connection.

Defaults are now loopback-only and read-only. Both are overridable for the
cases that genuinely need them, so the previous behaviour stays available
but has to be asked for:

  GF_ANON_ROLE=Admin  docker compose up -d lgtm   # editable dashboards
  GRAFANA_BIND=0.0.0.0 docker compose up -d lgtm  # expose on a trusted LAN

The OTLP receivers (4317/4318) are bound the same way via OTLP_BIND. The
application posts telemetry to http://localhost:4318 by default, so the
documented workflow is unaffected.

Reported by a CodeRabbit review of #23.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
The lgtm service tracked grafana/otel-lgtm:latest, so a rebuild could pull a
different observability stack without any change to this repo. Pin 0.30.0
(current release as of 2026-07-31).

Verified against the pinned image rather than assumed:
- Provisioned Grafana datasources are Loki, Prometheus (default), Pyroscope
  and Tempo. There is no Mimir datasource, and the image ships a prometheus
  binary and prometheus.yaml with no mimir equivalent.
- OTLP ingestion works end to end on this tag: POST /v1/metrics returned 200
  and Prometheus then answered probe_counter_total{service_name=
  "solr-mcp-probe"} = 7.

So the docs were sending readers to a datasource that does not exist -
"Select Mimir as the datasource" could not be followed. Corrected across
compose.yaml and dev-docs/Observability.md, and added Pyroscope, which the
stack provides but the docs never mentioned. The architecture diagram was
redrawn (Prometheus is wider than Mimir) and all rows re-aligned to 81
columns.

The LGTM table keeps its "M is for Mimir" row - that is what the acronym
stands for - but now says the image actually ships Prometheus.

Reported by a CodeRabbit review of #23.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
Rebasing the Spring Boot 4 / Spring AI 2.0 branch onto current main
applied cleanly at the textual level but left three test-side breaks
that only compiling and running the suite surfaces.

1. `SearchServiceIntegrationTest` and `IndexingServiceIntegrationTest`
   failed to compile. Main still uses the wildcard
   `import static org.junit.jupiter.api.Assertions.*`, which this branch
   had expanded to explicit imports. Git merged the explicit list, so the
   assertions main added since the fork point (apache#166 `assertThrows`, apache#165
   `assertFalse`) had no import. Add the two missing static imports rather
   than reintroducing the wildcard.

2. `SolrNativeHintsTest.registersDefaultMetaProviderConstructorHint`
   (added on main via apache#172) asserts a hint for
   `org.springaicommunity.mcp.context.DefaultMetaProvider`. Spring AI 2.x
   relocated that class to
   `org.springframework.ai.mcp.annotation.context.DefaultMetaProvider`,
   which the Registrar already registers. Because `registerTypeIfPresent`
   silently no-ops for a class that is absent from the classpath, the
   legacy coordinate registers nothing here and the assertion failed. Point
   the test at the coordinate that Spring AI 2.x actually ships; the
   legacy registration stays in the Registrar defensively.

`./gradlew build` is green on JDK 25: 372 tests, 0 failures, 0 errors,
7 skipped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
…line

0.0.6 is built against the Spring Boot 3 line: its POM declares
spring-core 6.2.9 and spring-security-{web,config,core,oauth2-*} 6.5.2,
and it predates mcp-core 2.x entirely. This branch ships Spring Framework
7.0.8 and Spring Security 7.1.0 via the Spring Boot 4.1.0 BOM, so the
0.0.6 bytecode was running against a Security major it never saw.

0.1.14 is the current release of the same library on the Boot 4 line:
spring-core 7.0.8, spring-security-* 7.1.0, mcp-core 2.0.0 — matching
exactly what Spring Boot 4.1.0 and Spring AI 2.0.0 put on the classpath.
The upgrade is a version-catalog change only; McpServerOAuth2Configurer's
API in HttpSecurityConfiguration is unchanged.

Note on verification: no automated test in this repo exercises
McpServerOAuth2Configurer on any version. It is wired only when
OAUTH2_ISSUER_URI is set (HttpSecurityConfiguration#secured), and
DockerImageHttpIntegrationTest deliberately runs without an issuer since
it has no IdP. That coverage gap is pre-existing and worth closing
separately.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
…y main merges

The upstream/main merges brought main's DEVELOPMENT.md wording into sb4
unchanged, so the sb4 guide described Spring Boot 3.5's observability stack,
kebab-case span names, and an OtlpExportIntegrationTest that main re-enabled
in apache#198 as still disabled. It now describes what sb4 runs: Micrometer
Observation bridged by spring-boot-starter-opentelemetry, ClassName#methodName
span names, and the enabled LGTM export test. The OTel BOM bullet referred to
a BOM sb4 no longer imports; it now points at the dependency-alignment notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014AYFY1qefKnAxMshu5pYjg
Ghorbel37 pushed a commit to Ghorbel37/solr-mcp that referenced this pull request Oct 5, 2026
feat: add support for STDIO and SSE transport modes in Solr MCP server
Ghorbel37 pushed a commit to Ghorbel37/solr-mcp that referenced this pull request Oct 5, 2026
…e#41)

* feat: implement observability with OpenTelemetry and Micrometer, add logging configuration, and enable tracing with annotation support

* test(observability): implement distributed tracing tests for Spring Boot 3.5

Add comprehensive distributed tracing test suite using SimpleTracer from
micrometer-tracing-test library. This is the Spring Boot 3-native approach
for testing observability without requiring external infrastructure.

Key changes:
- Add DistributedTracingTest with 6 passing tests for @observed methods
- Add OpenTelemetryTestConfiguration providing SimpleTracer as @primary bean
- Add OtlpExportIntegrationTest (disabled due to Jetty dependency issue)
- Add LgtmAssertions and TraceAssertions utility classes
- Add micrometer-tracing-bridge-otel to bridge Observation API to OpenTelemetry
- Add spring-boot-starter-aop for @observed annotation support
- Add test dependencies: micrometer-tracing-test, awaitility, Jetty modules

Test results:
- DistributedTracingTest: 6/6 tests passing
- Spans successfully captured from @observed annotations
- Build: SUCCESS (219 tests passing, 0 failures)

Spring Boot 3.5 uses Micrometer Observation → Micrometer Tracing → OpenTelemetry
bridge, which differs from Spring Boot 4's direct OpenTelemetry integration.

Adapted from PR apache#23 (Spring Boot 4 implementation) with modifications for
Spring Boot 3.5 architecture and APIs.

---------

Signed-off-by: adityamparikh <aditya.m.parikh@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Spring Boot 4.1.1, Spring AI 2.0.1, mcp-server-security 0.1.14 and the
MCP Java SDK 2.0.1 are already the latest GA releases; this moves the
rest of the catalog up.

- OTel logback appender 2.21.0-alpha -> 2.28.1-alpha, the newest release
  built against the opentelemetry-api 1.62.0 that Boot 4.1.1 manages. It
  pulls opentelemetry-api-incubator 1.62.0-alpha itself, so the
  resolutionStrategy rule forcing that version is removed.
- Testcontainers 2.0.2 -> 2.0.5, commonmark 0.28.0 -> 0.30.0,
  Error Prone 2.48.0 -> 2.50.0, NullAway 0.13.1 -> 0.14.2.
- GraalVM native plugin 0.10.6 -> 1.1.14. Since 0.11 its JUnit feature
  handles build-time initialization of the test plan; the manual
  org.junit.platform.* --initialize-at-build-time entries now put a JUnit
  logger in the image heap and fail nativeTestCompile, so they are dropped.
- Spotless 7.0.2 -> 8.9.0 with Eclipse JDT pinned to 4.34 and ktlint to
  1.5.0 (the 7.0.2 defaults): JDT 4.39 collapses Javadoc <pre>{@code}
  blocks and folds @param/@see tags into the preceding paragraph.
- Jib 3.5.3 -> 3.5.4, Error Prone plugin 5.1.0 -> 5.1.1, Apache RAT
  plugin 0.8.2 -> 0.11.0, buildSrc JUnit 5.12.2 -> 6.1.3, Gradle 9.7.1 -> 9.8.0.

Verified: ./gradlew build (422 tests, 0 failed, 0 skipped) and
./gradlew nativeTest -Pnative (281 passed, 0 failed, 138 skipped).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
@epugh

epugh commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

This is the big one before we go to 1.0... we don't want to release on onld spring stuff...

adityamparikh and others added 10 commits October 6, 2026 15:03
Brings in apache#195 apache#200 apache#207 apache#212 apache#214 apache#215 apache#221 apache#230 apache#231 apache#233 apache#234 apache#235
apache#238 apache#239 apache#242 apache#243 apache#244 apache#247 and apache#191 apache#192, keeping the Spring Boot 4.1 /
Spring AI 2.0 / Jackson 3 / Boot OTel starter line.

Resolutions beyond the textual conflicts:

- libs.versions.toml: keep sb4's plugin versions, add main's
  changelog-plugin.
- build.gradle.kts (nativeTest args): keep sb4's removal of the manual
  org.junit.platform.* build-time init (GraalVM plugin >= 0.11 does it),
  take main's -H:IncludeResources=shows-markdown\.md.
- buildSrc: cyclonedx-core-java 10.2.1 -> 13.1.0, the version the
  cyclonedx 3.4.1 plugin uses. apache#247 pinned it to match plugin 2.4.1; the
  older model on buildSrc's classpath shadowed the plugin's and failed
  cyclonedxDirectBom (no Version.VERSION_17).
- AliasService (apache#214): MCP annotations from org.springframework.ai.mcp.
- ShowsSampleDataTest (apache#207): Jackson 3 JsonMapper.
- Tests from apache#195/apache#207/apache#212: add the explicit Assertions static imports
  sb4 uses in place of main's wildcard.
- docs/observability.md: rewrite apache#230's Boot 3 text (gRPC 4317, one
  shared endpoint, OTel-semconv metric names, /actuator/prometheus,
  kebab-case span names) for OTLP/HTTP per-signal URLs, Micrometer
  metrics in milliseconds and ClassName#method spans.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
…enerated file

gradle-wrapper.properties is generated, and apache#188 set retries=3 by hand
in it. Regenerating the wrapper for 9.8.0 wrote the generator's
default back (retries=0), silently dropping that setting.

Gradle 9.8's Wrapper task exposes `retries`, so set it there, with
distributionType BIN, and regenerate with
`./gradlew wrapper --gradle-version latest`. 9.8.0 is the current
release; future upgrades keep retries=3 without a hand edit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
spring-ai-autoconfigure-mcp-server-common was declared because Spring AI
2.0.0-M7 made it optional in the webmvc starter. In 2.0.1,
spring-ai-autoconfigure-mcp-server-webmvc depends on it at compile
scope again, so it arrives transitively.

spring-ai-starter-mcp-client and spring-ai-autoconfigure-mcp-client-common
were on the test classpath, but the tests build their clients from the
MCP Java SDK directly (io.modelcontextprotocol.client.McpClient with the
stdio and streamable-HTTP transports in mcp-core). Nothing uses a Spring
AI client class or a spring.ai.mcp.client.* property.

The SBOM is unchanged (same 140 components).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
…tion value

The comment said io.modelcontextprotocol >= 0.16. The check arrived in
SDK 2.0.0: CompleteArgument in 0.18.x and 1.0-1.1.x accepts a null
value, and main (on 0.18) still exercises that path.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
- AGENTS.md: version is 1.0.0-SNAPSHOT; the native OTel build-time init
  is for the logback appender (there is no instrumentation BOM any more);
  list the native hints SolrNativeHints actually registers; JSpecify
  arrives through spring-core; SBOM path build/reports/cyclonedx/;
  drop the stale component count; document the wrapper upgrade command.
- dev-docs/Observability.md: lgtm is boot-ignored, so bootRun never
  starts it; service name is solr-mcp; LogQL filters on the level and
  trace_id attributes (|= "ERROR" and | json match nothing); PromQL uses
  the OTLP registry's _milliseconds_ timers and job label; pin the lgtm
  image tag in the example.
- docs/site observability page: regenerated from docs/observability.md;
  it still described the Boot 3 gRPC/4317 export and /actuator/prometheus.
- docs/observability.md, DEVELOPMENT.md: the lgtm image runs Prometheus,
  not Mimir; SBOM path; OTel native note.
- observability test README: service, metric and span names, and the
  Boot 4 export properties.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
The resolution rule forced opentelemetry-proto to 1.3.2-alpha, built
against protobuf 3.x, citing a NoSuchMethodError seen with 1.8.0-alpha
on the Boot 3 line. On Boot 4.1.1 the only consumer,
micrometer-registry-otlp 1.17.1, is built against 1.10.0-alpha, and Boot
manages protobuf-java 4.35.1, so the rule downgraded the proto classes
below the protobuf runtime they run on.

Without the rule the graph resolves opentelemetry-proto 1.10.0-alpha
with protobuf-java 4.35.1, the pair Micrometer is built with.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
spring-ai-spring-boot-docker-compose 2.0.1 declares its vector-store
starters, spring-boot-starter-mongodb included, as optional, so none of
them reach developmentOnly and the exclusion matched nothing. Without it
the two docker-compose modules go back to the spring-boot-dev bundle, as
on main; developmentOnly still resolves no Mongo artifact.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
compose.yaml pinned grafana/otel-lgtm 0.30.0 while the version catalog
pins the Testcontainers image to 0.33.0 (test-image-lgtm), so local
bootRun and OtlpExportIntegrationTest ran different collector and
backend versions. Use 0.33.0 in both.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
adityamparikh and others added 3 commits October 7, 2026 11:18
…tibility runs

The solr-compatibility matrix only runs on pushes to main, and has failed
there on every push: Solr 10 removed /admin/mbeans, so cache and handler
stats degrade to null as documented, but three CollectionService
integration tests required them non-null; Solr 8.11 predates
DenseVectorField, so the dense-vector schema round trip is rejected.

TestcontainersConfiguration now exposes the image under test and its
major version, and those tests assert what each version actually does
(null stats on 10+, a RemoteSolrException below 9) instead of skipping.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
The solr-compatibility job was gated on a "solr-compatibility" label that
does not exist in the repository, and ci.yml does not trigger on labeled
events, so the job was skipped on every PR. Version-specific failures
(Solr 8.11, 9.4, 9.10, 10) therefore surfaced only on the next push to
main via build-and-publish.yml. Drop the gate so PRs run the matrix.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
With needs: integration-tests, any unit or integration failure made GitHub
skip the whole matrix, so the PR showed a skipped compatibility check and no
signal about other Solr versions. Depend on build like the unit-tests and
integration-tests jobs, so the matrix always runs and reports its own result.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
@adityamparikh

Copy link
Copy Markdown
Contributor Author

@epugh could you approve the workflow runs for 36f5c56? CI and Native Image are both waiting as action_required:

This push brings the Solr compatibility fix from #237 onto this branch. The matrix was gated on a solr-compatibility label that doesn't exist, so it was skipped on every PR. The gate is gone, and the integration tests now assert each version's behaviour (null cache/handler stats on Solr 10, no DenseVectorField on 8.11). Run locally against 8.11, 9.4, 9.10 and 10: 184 tests each, all passing, none skipped.

@epugh
epugh merged commit 3b91ab9 into apache:main Oct 7, 2026
16 of 17 checks passed
adityamparikh added a commit to adityamparikh/solr-mcp that referenced this pull request Oct 12, 2026
… build

The coc2026 image, native images and JAR are now built from the Spring
Boot 4.1 / Spring AI 2.0 line (apache#23), which carries
everything on main, so the card describes what that build does:

- Fifteen tools, with the three alias tools in the toolbox table.
- Step 3: CSV, XML and Markdown samples come from main's
  src/test/resources. CSV and XML go to Solr's own handlers, which
  report the payload accepted instead of a count. XML is Solr update
  XML, so its field names match JSON and the show_ prefix notes go;
  the Option B XML paste is converted to <add><doc> form. Markdown is
  one multi-record file and one tool call; its description is in
  content, which the step 6 note now says.
- Step 4: one outcome, an empty facet (apache#175 is in the image).
- Native Docker images are prebuilt for amd64 and arm64.
- Observability: OTLP/HTTP on 4318 with a URL per signal,
  ClassName#method span names, timers in milliseconds, JVM metrics over
  OTLP rather than /actuator/prometheus.
- Security: protected resource metadata for /mcp is served at the
  RFC 9728 path-suffixed URL.
- Sizes (52 MB JAR, ~170 MB image) and the verified-against footer.
- Table cards: fifteen tools, and ChatGPT in the client list.

Every step was replayed against the published image for all four
formats, including the Option B pastes, the observability panel against
grafana/otel-lgtm 0.33.0, and the security panel against Keycloak.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

build: revisit the CycloneDX 2.4.1 pin once the Gradle 9.4.1 variant conflict is fixed

3 participants