Skip to content

Spring Modulith Support

Martin Lippert edited this page Sep 2, 2026 · 1 revision

Describes the current support for Spring Modulith in the Spring Tools. Spring Modulith lets you structure a Spring Boot application into logical application modules, with each module exposing a well-defined API to the rest of the system and keeping the rest of its code internal.

The Spring Tools pick up that module structure and make it visible while you are coding:

All of this is enabled automatically, there is nothing to install in addition to the Spring Tools.

When a project is treated as a Spring Modulith project

The tooling considers a project to be a Spring Modulith project as soon as it has a spring-modulith-core dependency on its compile or runtime classpath. A dependency that exists only for tests is not enough - the Modulith features stay switched off for such a project.

Application module metadata

All Modulith-specific features are built on top of the application module metadata: the list of application modules of the project, their base packages, and the named interfaces that each module exposes.

The Spring Tools do not re-implement the rules that Spring Modulith uses to derive that information. Instead they run Spring Modulith's own ApplicationModulesExporter in a separate process, using the classpath of your project, starting at the package of each @SpringBootApplication class of the project. This way the tooling always sees exactly the same module structure that Spring Modulith itself sees at runtime, including everything that you configured via @ApplicationModule, @NamedInterface, or package-info.java files.

Two consequences of this approach are worth knowing about:

  • The project needs to be built. The exporter works on compiled classes, so a project without any .class files in its output folders has no module metadata yet. If the module structure in the tooling looks empty or outdated, a (re-)build of the project is usually the fix.
  • The metadata is cached and refreshed in the background. The tools watch the output folders of the project and re-compute the metadata when class files of module packages change - package-info.class files in particular, since those carry the module and named interface declarations.

Automatic project tracking

The background tracking of Modulith projects is switched on by default. You can turn it off if you prefer to update the metadata manually only:

  • Eclipse: Preferences -> Spring -> Spring Boot Modulith automatic project tracking and metadata update
  • VSCode: the boot-java.modulith-project-tracking setting

Refreshing the metadata manually

You can always ask the tooling to re-compute the module metadata of a project and re-validate its sources:

  • Eclipse: right-click the project (or its pom.xml / build.gradle file) and choose Spring -> Refresh Modulith Metadata. The action shows up for Maven and Gradle projects that depend on spring-modulith-core.
  • VSCode: run Spring Boot: Refresh Modulith Metadata from the command palette. If more than one Modulith project is open, you are asked which project to refresh.

The tooling reports back whether the metadata actually changed, and tells you when it could not be computed - for example because the project does not depend on Spring Modulith at all, or because its output folder does not contain any compiled classes yet.

Application modules in the Logical Structure view

The Logical Structure view shows the components of a Spring Boot project grouped by their logical role instead of by files and folders. For Spring Modulith projects, the application modules become the top level of that tree:

  • Each application module appears as a node labelled with its display name followed by its (abbreviated) base package.
  • Inside a module, its components are grouped by their stereotypes, in the same way as for non-Modulith projects.
  • Each type is marked as either (API) or (internal), depending on whether the module exposes it through one of its named interfaces. This makes it easy to see at a glance which parts of a module other modules are allowed to use.

You can open the view via Window -> Show View -> Spring -> Logical Structure in Eclipse, and as the Logical Structure section of the Explorer in VSCode. The refresh action of the view re-requests the Modulith metadata before rebuilding the tree, so it doubles as a quick way to pick up module changes. The grouping action lets you choose which stereotype groups the tree should be structured by.

Validation: invalid references to module internals

Spring Modulith projects usually verify their module boundaries with an ApplicationModules.verify() test. The Spring Tools bring the most important part of that check directly into the editor: a type from another application module that is not exposed via one of that module's named interfaces is flagged right where it is referenced.

The problem is reported as Invalid reference to non-exposed type of module '<module>'! and has ERROR severity by default.

Consider a project with an order module that exposes its spi sub-package as a named interface:

// src/main/java/com/example/order/spi/package-info.java
@org.springframework.modulith.NamedInterface
package com.example.order.spi;

Then, from within a different module:

package com.example.inventory;

import com.example.order.spi.SomeSpi;        // fine, exposed via a named interface
import com.example.order.internal.OrderInternal;  // flagged: not exposed by module 'order'

class InventoryManagement {
    // ...
}

References within the same application module are never flagged, and neither are references to types that any named interface of the target module exposes.

Note that this validation can only run once the module metadata is available, so it needs a built project just like the structure view does. Whenever the metadata changes, the tooling automatically re-validates the Java sources of the project.

Validation and quick fix for @ApplicationModuleListener

(new in 5.4.0 / 2.4.0)

Spring Modulith provides @ApplicationModuleListener as a single meta-annotation for the common combination of @Async, @Transactional, and @TransactionalEventListener. In Spring Modulith projects, the tooling points out methods that still use the three separate annotations and offers a quick fix to combine them. The problem is reported with INFO severity by default.

Before:

@Async
@Transactional
@TransactionalEventListener
void on(OrderCompleted event) {
    // ...
}

After applying the quick fix:

@ApplicationModuleListener
void on(OrderCompleted event) {
    // ...
}

Two quick fixes are offered: Combine into @ApplicationModuleListener for the method at hand, and Combine all into @ApplicationModuleListener in file to convert every affected method of the file at once. Unused imports of the replaced annotations are cleaned up, and the attributes that @ApplicationModuleListener supports are carried over - @Transactional's readOnly becomes readOnlyTransaction, propagation stays propagation, and @TransactionalEventListener's id and condition are kept as they are.

Methods that use an attribute which @ApplicationModuleListener cannot express - for example @Async("executorName"), @Transactional(timeout = ...), or @TransactionalEventListener(phase = ...) - are deliberately left alone, since combining the annotations would silently change the behavior of the method.

Configuring the validations

Both Modulith validations are part of the Spring-specific validations of the tooling, so everything described in Validations and Quick Fixes applies to them as well. You can change their severity individually, or set them to IGNORE if you don't want to see them at all:

  • Eclipse: Preferences -> Spring -> Validation, in the Boot 3.x Best Practices & Optimizations category
  • VSCode: the spring-boot.ls.problem.boot3.MODULITH_TYPE_REF_VIOLATION and spring-boot.ls.problem.boot3.MODULITH_APPLICATION_MODULE_LISTENER settings

Since both validations analyze Java sources, they require Reconciling of Java Sources to be enabled (which is the default).

Application module structure for AI assistants

The language server ships an embedded MCP server, and the logical structure of a project - including the application modules of Spring Modulith projects - is available to AI assistants through it. An assistant can therefore reason about your application in terms of its application modules and exposed APIs instead of just its files, and it sees exactly the same tree that the Logical Structure view renders.

Known limitations

  • Module metadata is derived from compiled classes, so changes to module or named interface declarations only become visible to the tooling after the project has been rebuilt.
  • Computing the metadata starts from the @SpringBootApplication classes of a project. A Modulith project without such a class in the tooling's index does not get any module metadata.

Clone this wiki locally