Configuring Spring Boot Starter

How to wire the Axelix Spring Boot Starter into a Spring Boot application so Axelix Master can discover it, read its state, and act on it.

This page shows how to wire the Axelix Spring Boot Starter into a Spring Boot application so Axelix Master can discover it, read its state, and act on it — both from the UI and through Master's bundled MCP (Model Context Protocol) server, which exposes the same data to AI agents. Pick the starter module matching your Boot major version, expose the Axelix actuator endpoints (automatic as of Axelix 1.2.0), share the JWT signing key with Master, and tell Master where to find the instance.

Before you start

A few facts worth pinning down before you copy any of the snippets below.

  • Three starter modules, one per Spring Boot major version. Pick the one that matches the Boot version your application already uses:
    • com.axelixlabs:axelix-spring-boot-2-starter — Spring Boot 2.7+ (a hard floor, not just what we tested; built and tested against 2.7.18, Spring Cloud 2021.0.9, minimum JDK 11).
    • com.axelixlabs:axelix-spring-boot-3-starter — Spring Boot 3.x (built and tested against 3.0.13, Spring Cloud 2022.0.4, minimum JDK 17).
    • com.axelixlabs:axelix-spring-boot-4-starter — Spring Boot 4.x (built and tested against 4.0.6, Spring Cloud 2025.1.0, minimum JDK 17).
  • What the starter contributes: a set of Axelix-specific actuator endpoints (axelix-metadata, axelix-beans, axelix-loggers, …), a JWT-based authorization filter that gates them, and an optional self-registration component that announces this instance to Master.
  • The Axelix build plugin is required too: alongside the starter dependency, apply the Axelix Gradle or Maven build plugin. It stamps your build coordinates (groupId/artifactId/version) into the artifact, and Master identifies every application by those coordinates — an instance built without the plugin cannot register. See What is the Axelix build plugin? and Configuring the build plugin.
  • Two consumers of the same data: Master serves the Axelix UI at / and an MCP server at /api/mcp (controlled by axelix.master.mcp-server.enabled, on by default). Both read from the actuator endpoints the starter exposes, so wiring the starter up makes the instance visible to UI users and to MCP clients with no extra configuration on the starter side.
  • What Master needs to talk to the instance: HTTP reachability to the application's actuator base path (default /actuator), the Axelix endpoints exposed through management.endpoints.web.exposure.include, and a JWT signing key identical to the one configured on Master — see Authentication — JWT for the master side.
  • Two ways Master finds the instance:
    • Master-side autodiscovery — Master scans its environment (currently Kubernetes Services) and probes the actuator endpoint itself. The starter only needs to expose the endpoints; nothing additional to configure.
    • Self-registration — the starter posts a heartbeat to Master on a fixed interval. Use this when Master cannot scan the instance's environment (different network, no platform integration, plain VMs).

Reactive (WebFlux) applications

UpcomingAvailable in an upcoming minor release

Starting with Axelix 1.3.0, all three starters work in reactive applications built on Spring WebFlux, not only in servlet (Spring MVC) applications. The starter detects which web stack your application runs on, so there is nothing extra to add or configure: the dependency, the build plugin, and the properties on this page are the same for both. The Axelix endpoints and the JWT authorization in front of them work the same way, including when Actuator runs on a separate management.server.port.

One feature stays servlet-only. Transaction monitoring, and with it the Transaction Control and Entities Map pages, is not available in WebFlux applications.

Add the dependency

Declare the starter coordinate matching your Boot major version.

The snippets below use the latest release, 1.2.2.

build.gradle.kts
dependencies {
    implementation("com.axelixlabs:axelix-spring-boot-4-starter:1.2.2")
}

The starter also depends on Spring Boot Actuator if your application doesn't already include spring-boot-starter-actuator, add it alongside.

The build plugin is a separate step

Applying the Axelix build plugin is required for every managed service, but it lives in its own section — see What is the Axelix build plugin? and Configuring the build plugin.

Transitive dependencies

The starter is built to add as little as possible to your classpath. Everything it integrates with — Spring Boot, Actuator, Spring Kafka, Micrometer, Caffeine, Jackson — is compiled against but not brought in: the starter uses whatever your application already has. The only libraries it brings in transitively are:

DependencyWhy it is there
org.slf4j:slf4j-apiLogging. Already present in every Spring Boot application.
io.jsonwebtoken:jjwt-api, jjwt-impl, jjwt-jacksonVerifying the JWT that Master sends with every request.

This list is meant to shrink. The starter is the one Axelix component that runs inside your services, and every library it brings in is one more thing on your classpath to scan, patch, and keep compatible with the rest of your application. The Axelix core team's position is that the starter should have no external dependencies at all, and we are removing the remaining ones step by step — follow axelixlabs/axelix#1748 for the progress.

JsonPath is no longer included

ReleasedAvailable since release: 1.2.0

Up to and including Axelix 1.1.x, the starter also brought in com.jayway.jsonpath:json-path, although it never used it. Starting with Axelix 1.2.0, that dependency is removed — the first step towards the dependency-free starter described in axelixlabs/axelix#1748.

If your application uses JsonPath in its own code and has been getting it only through the Axelix starter, declare it explicitly when you upgrade. The version is managed by Spring Boot, so you do not need to specify one:

build.gradle.kts
dependencies {
    implementation("com.jayway.jsonpath:json-path")
}

Tests are not affected: spring-boot-starter-test brings in JsonPath on its own.

JSpecify is no longer included

UpcomingAvailable in an upcoming minor release

Up to and including Axelix 1.2.x, the starter also brought in org.jspecify:jspecify. The starter uses JSpecify only for its nullness annotations, and it needs them only at compile time. Starting with Axelix 1.3.0, the dependency is removed, as the next step towards the dependency-free starter described in axelixlabs/axelix#1748.

The starter keeps working without JSpecify on the classpath, because the JVM ignores annotations whose classes are missing at runtime. On Spring Boot 4 nothing changes at all, since Spring Framework 7 depends on JSpecify itself.

If your own code uses the JSpecify annotations and has been getting them only through the Axelix starter, declare the dependency explicitly when you upgrade. Spring Boot 2 and 3 do not manage its version, so specify it:

build.gradle.kts
dependencies {
    implementation("org.jspecify:jspecify:1.0.0")
}

Actuator endpoints

Starting with Axelix 1.2.0 there is nothing to configure by hand: on application startup the starter adds its own actuator endpoints to management.endpoints.web.exposure.include, so Master can reach them out of the box. On older versions the starter does not do this, and the endpoints must be listed manually — see Exposing the endpoints on Axelix below 1.2.0.

What the starter exposes

The starter exposes the following endpoints:

EndpointPurposeSince
axelix-metadata requiredService metadata; the one Master probes first1.0.0
axelix-pingHealth, memory, and transaction data Master polls for instances it already knows1.3.0 upcoming
axelix-detailsSummary information about the instance1.0.0
axelix-beansContext beans1.0.0
axelix-cachesCaches (when a CacheManager is present)1.0.0
axelix-conditionsAuto-configuration conditions report1.0.0
axelix-configprops@ConfigurationProperties1.0.0
axelix-envEnvironment and property sources1.0.0
axelix-feign legacyFeign clients (when Feign is on the classpath). Removed in 1.3.0, see below1.0.0
axelix-gcGarbage collection1.0.0
axelix-heap-dumpHeap dump1.0.0
axelix-loggersLogging levels1.0.0
axelix-logsRecent log entries1.3.0 upcoming
axelix-metricsMetrics1.0.0
axelix-scheduled-tasksScheduled tasks1.0.0
axelix-thread-dumpThread dump1.0.0
axelix-dependenciesDependency SBOM1.2.0

The Since column names the Axelix starter release an endpoint first shipped in. 1.0.0 is the first Axelix release, so an endpoint marked 1.0.0 has been there from the very beginning. A version marked upcoming is not released yet: the endpoint will become available in the next Axelix release, whether that is a minor or a major one.

Endpoints that don't apply to your application stay inert — the starter activates each one only when its prerequisites are met (for example, axelix-caches without a CacheManager never comes up).

As of Axelix 1.2.0 the native health and info endpoints are no longer required, so the starter never exposes them on its own (before 1.2.0 Axelix depended on them, and the starter force-exposed both). Only the endpoints you list in management.endpoints.web.exposure.include plus the Axelix ones are exposed — add health and info to the list yourself when you need them, including the health endpoint that Spring Boot would otherwise expose by default.

The axelix-feign endpoint is removed

UpcomingAvailable in an upcoming minor release

Up to and including Axelix 1.2.x, the Spring Boot 3 and Spring Boot 4 starters also contributed an axelix-feign endpoint that listed the Spring Cloud OpenFeign clients of the application. Axelix Master has never used it to render anything, and it stayed around only as a leftover from the early days of the project. Starting with Axelix 1.3.0 the endpoint is removed from the starters, together with everything in Master that was able to call it.

There is nothing to do when you upgrade. The only visible difference is that /actuator/axelix-feign no longer exists on a service running starter 1.3.0 or newer, so if your own tooling calls that URL directly, it will get a 404. If you list the Axelix endpoints in management.endpoints.web.exposure.include by hand and axelix-feign is among them, you can drop it from the list — leaving it there is harmless.

Adding your own endpoints

If you need your own actuator endpoints, just list only them — the starter merges your list with its own instead of replacing it.

management:
  endpoints:
    web:
      exposure:
        include:
          - prometheus

The result is that prometheus and all the Axelix endpoints are exposed.

The * value is supported too — everything gets exposed and the starter leaves the list alone.

Exposing the endpoints on Axelix below 1.2.0

LegacyOnly needed before release: 1.2.0. On later versions, skip this section.

Starters older than 1.2.0 do not add their endpoints to the exposure list themselves, so every Axelix endpoint you want Master to read has to be listed in management.endpoints.web.exposure.include by hand. At minimum expose axelix-metadata — without it the instance never appears in Master — and in practice the whole set, so every UI section has data to show. The health and info endpoints are force-exposed by those starter versions on their own, so you do not need to list them:

management:
  endpoints:
    web:
      exposure:
        include:
          - axelix-metadata
          - axelix-beans
          - axelix-caches
          - axelix-conditions
          - axelix-configprops
          - axelix-details
          - axelix-env
          - axelix-gc
          - axelix-heap-dump
          - axelix-loggers
          - axelix-metrics
          - axelix-scheduled-tasks
          - axelix-thread-dump

These starter versions also contribute the legacy axelix-feign endpoint. It is left out of the list on purpose: Master never reads it, and the endpoint is removed in Axelix 1.3.0 — see above.

Export Axelix metrics through Micrometer

The axelix-metrics actuator endpoint powers the Axelix UI. In addition, the Spring Boot starters can publish a small set of Axelix-specific meters into your application's own Micrometer MeterRegistry.

This export path switches on automatically when a MeterRegistry bean is present. There is no extra Axelix property for it. The starter registers these meters:

MeterTypeTagsMeaning
axelix_transaction_durationTimerclass, methodDuration of each monitored @Transactional execution. The timer also publishes 0.5, 0.95, and 0.99 percentiles.
axelix_transaction_queriesCounterclass, methodTotal number of SQL queries executed inside monitored transactions.
axelix_transaction_external_callsCounterclass, methodTotal number of external calls (e.g. RestTemplate) made inside monitored transactions.
axelix_cache_requestsCountercache, resultTotal number of cache lookups recorded by Axelix-enhanced caches.
axelix_cache_enabledGaugecacheCurrent runtime state of each enhanced cache: 1 when enabled, 0 when disabled.

These meters complement the UI-facing actuator endpoints rather than replace them. The UI still reads axelix-metrics and axelix-caches. Transaction monitoring data is not served by a dedicated actuator endpoint — it travels to Master as part of the instance's registration metadata exposed through axelix-metadata (see Transaction monitoring).

Share the JWT signing key with Master

Every Axelix actuator endpoint is gated by JwtAuthorizationFilter. The filter expects an HS256, HS384, or HS512 token signed with the same key Master uses, so the two sides must agree on the algorithm and the secret. Use the same value you set for axelix.master.auth.jwt.signing-key on Master.

axelix:
  sbs:
    auth:
      jwt:
        algorithm: HMAC512
        signing-key: ${AXELIX_JWT_SIGNING_KEY}
        duration: 5m

duration controls how long the starter-issued token used for self-registration heartbeats is valid, the default is five minutes, after which the starter rotates it automatically.

A signing key shared between Master and every monitored service is a sensitive secret. Inject it through an environment variable, mounted file, or secret manager — not a checked-in YAML.

Running without a signing key

ReleasedAvailable since release: 1.2.0

Starting with Axelix 1.2.0, algorithm and signing-key are optional. When they are not set, the starter uses HMAC512 and the same built-in key that Master uses by default, so the service connects to a Master with default settings without any key setup. While the built-in key is in use, the starter logs a warning at startup.

The built-in key is publicly known. Anyone who can reach the service's actuator endpoints can sign a token with it and call the Axelix endpoints, for example to read the environment or take a heap dump. Set your own axelix.sbs.auth.jwt.signing-key, the same as on Master, before using Axelix beyond a local trial.

Let Master find the instance

Pick one of the two paths below. They are mutually exclusive in practice — self-registration only adds latency if Master can already scan the environment.

Option A — Master-side autodiscovery

When Master runs inside a Kubernetes cluster alongside your services, the simplest setup is to let Master scan the namespace for Services and probe each one's /actuator/axelix-metadata. No further configuration is needed on the starter side beyond exposing the actuator endpoints and sharing the JWT signing key. Configure the master-side scan with axelix.master.discovery.auto.* — see Discovery — auto-discovery on the Master page. For what Master does on each scan, see How discovery works.

Option B — Self-registration

When Master cannot scan the instance's environment — a different cluster, a plain VM, an isolated network — switch on self-registration in the starter. The instance then posts a heartbeat carrying its actuator URL to Master on a fixed interval. Master accepts the post at POST /api/internal/service/register, which is also where you point axelix.sbs.discovery.master-url. Starting with Axelix 1.3.0, the starter sends this full registration only once and then switches to lightweight heartbeats, which go to an endpoint next to master-url. For the whole cycle, see How discovery works.

axelix:
  sbs:
    discovery:
      self-registration: true
      master-url: http://master.internal:2935/api/internal/service/register
      instance-actuator-url: http://my-app.internal:8080/actuator
      instance-name: orders-service
      heartbeat-interval: 15s

A few details that catch people out:

  • instance-actuator-url is the base URL of the service as Master will reach it from its own network — host and port only.
  • master-url is the full URL including /api/internal/service/register. The starter posts to it verbatim. Master listens on 2935 by default since Axelix 1.2.0; before that release the default port was 8080 — see General.
  • instance-name is the label Master shows for this instance in the UI and in MCP responses. Pick a name that survives restarts and replicas — typically the service name, not the pod name.
  • Self-registration is accepted by Master out of the box (axelix.master.discovery.self-registration.enabled is true by default), set it to false if you want to refuse heartbeats. Master evicts an instance after axelix.master.discovery.self-registration.eviction.heartbeat-timeout of silence (45s by default), so keep heartbeat-interval comfortably under that.

Sanitize sensitive property values

The Axelix axelix-env and axelix-configprops endpoints return property values to Master. To keep secrets out of casual reads, the starter masks values it returns to callers that lack the right authority. The mechanism is the same for both endpoints, controlled by a single starter property:

axelix.sbs.endpoints.config.sanitized-properties

  • Empty list (default) — every value returned by axelix-env and axelix-configprops is replaced with ****** for callers without the relevant authority. The default is intentionally conservative: no opt-in needed to be safe.
  • Non-empty list — only the listed keys are masked; everything else is returned raw to any caller. Use this when the conservative default is too aggressive and you want to mask only specific keys (passwords, tokens, signing keys).

Authority is checked per-endpoint:

  • axelix-env — the ENV_VALUES_READ authority lets the caller see raw values.
  • axelix-configprops — the CONFIG_PROPS_VALUES_READ authority lets the caller see raw values.

Both authorities are granted by Master's built-in ADMIN and SUPER_ADMIN roles. VIEWER and EDITOR always go through the sanitization function. See Roles and authorities for the full matrix.

axelix:
  sbs:
    endpoints:
      config:
        sanitized-properties:
          - database.password
          - spring.datasource.password
          - jwt.signing-key

The standard Spring Boot Actuator masking switches — management.endpoint.env.show-values, management.endpoint.env.keys-to-sanitize, and their configprops equivalents — are not consulted.

Configuration reference

Every starter property lives under the axelix.sbs.* namespace.

Disabling the starter

ReleasedAvailable since release: 1.2.0

axelix.sbs.enabled is the global switch for the whole starter. It is true by default, so adding the dependency is enough to activate everything described on this page. Set it to false and every Axelix auto-configuration backs off: no Axelix actuator endpoints, no JWT authorization filter, no self-registration heartbeats, no Micrometer meters, and no transaction monitoring. The application then starts as if the starter were not on the classpath, while the dependency itself stays in the build.

Reach for this switch when you want Axelix off in a specific environment — for example locally or in a test profile — without maintaining a separate dependency set. It is also a quick way to rule the starter out while troubleshooting startup issues.

axelix:
  sbs:
    enabled: false

The property is read once, during startup. As a result, changing it requires a restart of the application.

With the starter disabled, Master loses sight of the instance: autodiscovery probes to /actuator/axelix-metadata fail, and self-registration heartbeats stop, so the instance disappears from the UI and from MCP responses.

PropertyDefaultDescription
axelix.sbs.enabledtrueGlobal switch for the whole starter. Set to false to make every Axelix auto-configuration back off. Behaves identically on the Spring Boot 2, 3, and 4 starters.

Authentication — JWT

PropertyDefaultDescription
axelix.sbs.auth.jwt.algorithmHMAC512 (1.2.0+; required before)Signing algorithm. One of HMAC256, HMAC384, or HMAC512. Must match Master's axelix.master.auth.jwt.algorithm.
axelix.sbs.auth.jwt.signing-keybuilt-in key (1.2.0+; required before)Shared secret used to verify Master-issued tokens and to sign self-registration heartbeats. Must match Master's signing key.
axelix.sbs.auth.jwt.duration5mValidity of the self-registration token the starter issues itself. Tokens are rotated automatically before expiry.

Self-registration

Self-registration is off by default (axelix.sbs.discovery.self-registration=false) — leave it that way when Master can find the instance through Master-side autodiscovery instead.

When axelix.sbs.discovery.self-registration=true, the following properties become required:

  • axelix.sbs.discovery.master-url
  • axelix.sbs.discovery.instance-actuator-url
  • axelix.sbs.discovery.instance-name

The Master-side receiver of these heartbeats — endpoint, eviction timeout, eviction sweep schedule — is documented on the Master page in Discovery — self-registration. The JWT signing key configured under axelix.sbs.auth.jwt.signing-key must match axelix.master.auth.jwt.signing-key on Master, otherwise heartbeats are rejected with 401.

PropertyDefaultDescription
axelix.sbs.discovery.self-registrationfalseMaster switch. Set to true to enable self-registration; leave false to rely on Master-side autodiscovery.
axelix.sbs.discovery.master-url(unset) requiredFull URL of Master's self-registration endpoint, e.g. http://master:2935/api/internal/service/register. Required when self-registration=true.
axelix.sbs.discovery.instance-actuator-url(unset) requiredBase URL of this service as reachable from Master (It is necessary to specify the postfix /actuator). Required when self-registration=true.
axelix.sbs.discovery.instance-name(unset) requiredDisplay name shown in Axelix UI and MCP responses. Required when self-registration=true.
axelix.sbs.discovery.heartbeat-interval15sInterval between heartbeats. Should be smaller than Master's eviction heartbeat-timeout.

Endpoint value sanitization

PropertyDefaultDescription
axelix.sbs.endpoints.config.sanitized-properties(empty list)Property keys whose values are masked as ****** for callers without ENV_VALUES_READ (for axelix-env) or CONFIG_PROPS_VALUES_READ (for axelix-configprops). Empty list means all values are masked. See Sanitize sensitive property values for the matching rules.

Cache management

ReleasedAvailable since release: 1.2.0

Cache management is what powers the Caches page and the axelix_cache_* meters: the starter wraps every CacheManager bean of your application in a proxy that records cache lookups and lets you enable, disable, and clear caches at runtime, and it exposes that data through the axelix-caches actuator endpoint. It is on by default once the starter is on the classpath.

Set axelix.sbs.cache.management.enabled to false to turn it off entirely — no CacheManager proxying, no axelix-caches endpoint, and no cache meters. Your CacheManager beans are then left exactly as your application defined them.

axelix:
  sbs:
    cache:
      management:
        enabled: false
PropertyDefaultDescription
axelix.sbs.cache.management.enabledtrueMaster switch for cache management. Set to false to make the whole cache management auto-configuration back off. Behaves identically on the Spring Boot 2, 3, and 4 starters.

With cache management disabled, the Caches page in Master has no data to show for this instance, and the cache MCP tools fail for it.

Log entries

UpcomingAvailable in an upcoming minor release

The axelix-logs endpoint serves the most recent log entries of your application, so you can read them without access to the host. The starter keeps these entries in memory, starting from application startup. When the buffer is full, each new entry pushes out the oldest one. Because the buffer lives in memory, it is empty again after a restart.

By default, the starter keeps the last 1000 entries. Raise axelix.sbs.logs.max-entries when a busy service logs so much that 1000 entries cover only a few seconds. Lower it when memory is tight, because every kept entry stays on the heap.

axelix:
  sbs:
    logs:
      max-entries: 5000
PropertyDefaultDescription
axelix.sbs.logs.max-entries1000Maximum number of the most recent log entries the starter keeps in memory. Must be greater than 0.

The starter checks the value once the application has started. If it is 0 or negative, startup fails with an IllegalArgumentException saying axelix.sbs.logs.max-entries must be positive.

Transaction monitoring

Transaction monitoring is what powers the Transaction Control page and the related meters: it wraps your @Transactional methods, proxies the data source to count queries, cleans up the per-request transaction stack, and registers the Hibernate N+1 integrator. The collected insights travel to Master inside the instance's registration metadata (exposed through axelix-metadata), so there is no separate actuator endpoint to expose. It is on by default once the starter is on the classpath.

Transaction monitoring works only in servlet (Spring MVC) applications. In a reactive (WebFlux) application the starter doesn't turn it on, whatever the property says. See Reactive (WebFlux) applications.

Set axelix.sbs.transaction.monitoring.enabled to false to turn it off entirely — no bean post-processors, no data source proxying, no cleanup filter, and no Hibernate integrator. Use this to shave the associated overhead, to rule out interference while troubleshooting your data source / Hibernate setup, or simply when you don't use the feature.

axelix:
  sbs:
    transaction:
      monitoring:
        enabled: false
PropertyDefaultDescription
axelix.sbs.transaction.monitoring.enabledtrueMaster switch for transaction monitoring. Set to false to make the whole transaction monitoring auto-configuration back off. Behaves identically on the Spring Boot 2, 3, and 4 starters.

Disabling transaction monitoring also disables in-memory pagination detection described below, since that detection is part of the same auto-configuration.

In-memory pagination detection

Detects Hibernate`s in-memory pagination caused by using setFirstResult/setMaxResults together with a collection fetch.

By default, transaction monitoring registers an appender that intercepts Hibernate warnings (HHH000104 in Hibernate 5.x and HHH90003004 in Hibernate 6.x–7.3.x). The starter picks the appender that matches your application's active logging system, so detection works whether you run on Logback or Log4j2:

  • Logback — the starter registers com.axelixlabs.axelix.sbs.spring.core.persistence.hibernate.pagination.LogbackInMemoryPaginationAppender. This is the case for a default Spring Boot setup, where Logback is the logging system.
  • Log4j2 — when your application uses Log4j2 instead (typically after adding spring-boot-starter-log4j2 and excluding the default Logback starter), the starter registers com.axelixlabs.axelix.sbs.spring.core.persistence.hibernate.pagination.Log4j2InMemoryPaginationAppender.

You don't choose between them — the starter detects the active logging system and registers the right appender for you.

Set axelix.sbs.transaction.monitoring.in-memory-pagination-detection.enabled to false if you want to prevent either appender from being registered.

axelix:
  sbs:
    transaction:
      monitoring:
        in-memory-pagination-detection:
          enabled: false

On this page

Edit on GitHubReport an issue