Oliver Drotbohm Archive About Tags

jMolecules 2.0 – Stereotypical

November 14th, 2025

On behalf of the community and all contributors to the release, I am excited to announce the availability of jMolecules 2.0. Five years after its first major version, we now ship the second generation, marking an important step in our vision to empower developers to write architecturally evident code and ultimately produce more understandable and thus better software. I would like to spend a few lines on jMolecules 2.0’s primary new feature: its stereotype metamodel.

As described in previous articles, jMolecules mission is to provide Java developers with the means to assign elements of their code bases to design and architecture concepts. Up until now, jMolecules has provided well-defined concepts originating in Domain-Driven Design and various architecture definitions, such as Layered-, Hexagonal- and Onion-Architecture.

Moreover, its companion project jMolecules Integrations connects the logical concept assigned to various technologies in the broader Java ecosystem, ranging from conceptual verification via ArchUnit and integration into Spring and Jackson to sophisticated byte-code generation to avoid boilerplate persistence mappings and generating developer documentation.

Stereotypes

Interacting with various stakeholders over the last five years made us realize that the defined set of stereotypes jMolecules ships itself significantly helps developers to produce easier-to-understand code. That said, we also learned about a few aspects that users thought we should improve on:

Combining all these ideas, we realized that the design and architecture concepts we deal with essentially form stereotypes. They assign a role to an element of the code base, whether that’s a method (in the case of an event listener), a type (an entity or service), or even a package (Hexagonal Architecture adapters).

With jMolecules 2.0, we explicitly introduce that concept in the form of configuration metadata located in a file META-INF/jmolecules-stereotypes.json within our artifacts. The general schema definition can be found here. A Domain-Driven Design Aggregate Root, for example, is defined like this (source here):

{
  "stereotypes" : {
    "ddd.AggregateRoot" : {
      "assignments": [
        "@org.jmolecules.ddd.annotation.AggregateRoot",
        "org.jmolecules.ddd.types.AggregateRoot"
      ],
      "groups": [
        "ddd"
      ],
      
    },
    
  },
  "groups": {
    "ddd" : {
      "displayName": "Domain-Driven Design",
      "type" : "design"
    }
  }
}

The stereotype object takes keyed stereotype definitions. In this case, we express that we assign the stereotype ddd.AggregateRoot to all types that are either annotated (the assignment starting with @) or implementing the fully qualified type. Furthermore, the concept is assigned to stereotype group ddd. We are going to further discuss the groups below.

These definitions now allow a new jMolecules Integrations artifact jmolecules-stereotype to provide an API to inspect a project for all the stereotypes available and detect which stereotypes are assigned to elements of the codebase.

var source = CatalogSource.ofClassLoader();
var catalog = new JsonPathStereotypeCatalog(source);
var factory = new ReflectionStereotypeFactory(catalog);

var metadata = factory.fromType(MyClass.class);

First we set up a CatalogSource that can inspect the classpath for the jMolecules stereotype configuration files described above. That source is then handed into a StereotypeCatalog implementation that parses these files using JSONPath and ultimately enables a StereotypeFactory working reflection to find the registered stereotypes.

The latter abstraction is the most important one, as it allows tooling providers operating on top of different APIs abstracting Java code to implement the assignment detection. We ship one based on Java reflection and another one on top of ArchUnit. In Bringing Stereotypes to Life in IDEs, we will see how development environments will use that API to portray a Java project on the level of design and architecture stereotypes.

jMolecules Out-of-The-Box Stereotypes

As of version 2.0, all of our jMolecules artifacts ship the stereotype metadata in their artifacts. To make use of that, all you need to do is bump the version number, ideally, the BOM:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.jmolecules</groupId>
      <artifactId>jmolecules-bom</artifactId>
      <version>2025.0.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

Aside from the design and architecture stereotypes, the jMolecules Integration artifacts additionally ship with technical stereotype descriptions for third-party libraries such as Spring or Jackson. Note how the Spring stereotype definitions allow us to generalize the concept of a message listener and summarize the marker annotations of the Kafka, Rabbit and simple messaging libraries. The list of stereotypes is, of course, not exhaustive yet, and we are going to add new ones in upcoming releases. If you find a concept particularly interesting to you missing, please open a ticket.

Custom Stereotypes

To define a custom stereotype, all we need to do is create a description file following the jMolecules stereotypes schema in META-INF/jmolecules-stereotypes.json. We further simplify this process by providing an @Stereotype annotation located in the org.jmolecules:jstereotype artifact. The org.jmolecules.integrations:jmolecules-apt annotation processor picks up that annotation on arbitrary annotations and types, creating a stereotype definition file according to the configuration of the annotation. In Spring RESTBucks, you find the definition of a data transfer object in the form of the DTO interface:

package de.odrotbohm.restbucks;

import org.jmolecules.stereotype.Stereotype;

@Stereotype(groups = "restbucks")
public interface DTO {}

The interface is then used to mark the PaymentForm as a DTO:

record PaymentForm(CreditCardNumber number) implements DTO {}

Compiling the code will cause the following jmolecules-stereotypes.json to be created:

{
  "stereotypes": {
    "restbucks.DTO": {
      "assignments": ["de.odrotbohm.restbucks.DTO"],
      "groups": ["restbucks"],
      "priority": 0
    }
  }
}

This would now reveal the restbucks.DTO stereotype for the PaymentForm when using the StereotypeFactory described above.

Bringing Stereotypes to Life in IDEs

Now that we have seen the fundamentals of stereotype assignment and how to inspect that information in reverse, it’s time to explore actual use cases for the assignment. Traditionally, IDEs have presented Java projects to developers as a very thin layer of abstraction over the file system. They know about the general concepts of a Java project, source folders, packages, etc., and carry that abstraction into their UI.

But now that our mental model about our codebase operates on a higher level of abstractions and we think about entities, aggregates, ports, and adapters, wouldn’t it be nice if our project was presented to us on the same level of abstraction? To support that, the jmolecules-stereotype artifact contains an API to process a project tree. It takes the inverted approach to “What stereotype does a type adhere to?” by operating on all stereotypes available to the project and assigning the source elements to those in a hierarchical way.

The Spring Tools team around Martin Lippert and Alex Boyko have taken the time to integrate a custom StereotypeFactory operating within the language server backing the Spring Tools in VSCode and Eclipse.

The Logical Structure View in Spring Tools

The Logical Structure View in Spring Tools

Note how the Logical Structure view completely abstracts from the physical arrangement of source code elements in the file system. On the very first level, Spring Tools detects that the project is a Spring Modulith one, evaluates the application’s module structure, and partitions the source code elements based on that.

All nested groupings are driven by jMolecules stereotypes. The hacking/hexagonal branch of RESTBucks assigns types in the code base to the concepts of Hexagonal Architecture, subdividing them into Application, Ports, and Adapters. The final nesting level applies stereotype groups of type “design” and “technology”, as visible from the presence of both Domain-Driven Design concepts, such as aggregate roots, and technical stereotypes, such as Spring configuration classes or Spring MVC controllers. Our custom DTO stereotype appears as a first-class citizen in that tree.

Developers can select which stereotype groups they would like to see applied in the tree by clicking on an icon that is revealed when hovering over the project root. It will display a selection window looking as follows.

Selecting Stereotype Groups

Selecting Stereotype Groups

Note how that would allow you to disable, for example, the Hexagonal Architecture grouping layer entirely.

The logical project navigation will be part of the upcoming Spring Tools release and can already be used in VSCode by flipping the Spring Boot plugin to use the preview version. In Eclipse you’d need to register the Spring Tools snapshot update site. I’m also already in touch with the IDEA team at JetBrains to make use of our APIs as well, to provide a similar project browsing experience.

blog comments powered by Disqus