Integrate into an existing Java project
This guide shows how to add JoinedWorkz step by step to an existing Java project, without rewriting everything from scratch.
Typical goals are:
- generate OpenAPI for existing or planned REST APIs
- generate DTOs / API interfaces and use them from hand-written code
- gradually move parts of the API and domain model into CMN models
We’ll focus on Maven-based projects. The examples assume you use Java 21 and, for REST, a Spring Boot stack – but the patterns apply to other Java technologies as well.
For background reading see:
Release and evidence boundary
This guide targets JoinedWorkz 1.3.80, Java 21 and Maven 3.9+. Its model snippets and release behavior were source- and syntax-checked by 2026-07-26. It is an adoption pattern, not a separately built canonical project. Use the linked Quickstart, Spring Boot release example and multi-module guide for their exact build and output evidence.
1. Integration strategies
There is no single “right” way to introduce JoinedWorkz into an existing project. In practice, three patterns work well:
Model inside an existing module
Put CMN models directly into an existing Maven module (for example the REST API module) and generate OpenAPI and DTOs alongside your current code.Dedicated model module (recommended for larger systems)
Create a new Maven module that only contains CMN models and the JoinedWorkz plugin, and route generated artefacts into existing modules viajoinedworkz.properties.Hybrid approach
Start with (1) inside an existing module, and later extract the models into a dedicated module when the model grows.
This guide will show the first two approaches, so you can choose what fits your project best.
2. Prerequisites
Your existing project should:
- be built with Maven
- use Java 21 (aligned with JoinedWorkz 1.3.80 examples)
- use Maven 3.9 or newer
- have a module where it makes sense to introduce API/domain modelling (e.g. a “web”, “api”, “service” or “backend” module)
You also need:
- JoinedWorkz Studio installed (optional but highly recommended)
- access to Maven Central (for the JoinedWorkz facilities and plugin)
The basic dependencies are:
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<joinedworkz.version>1.3.80</joinedworkz.version>
</properties>
<dependencies>
<!-- Spring Boot platform (includes Java and Base via transitive dependencies) -->
<dependency>
<groupId>org.joinedworkz.facilities</groupId>
<artifactId>spring-boot</artifactId>
<version>${joinedworkz.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>You can also depend only on common-base or common-java if you do not use Spring Boot, see Facilities & platforms.
3. Option A – Integrate into an existing module
This is the simplest way to start. You:
- add the JoinedWorkz plugin to an existing Maven module
- add a
model/folder with CMN models - register generated resources/sources if needed
3.1 Add the plugin and facilities
In the existing module where you want to introduce modelling (for example your REST API module), update the POM:
<build>
<resources>
<!-- existing resources -->
<resource>
<directory>src/main/resources</directory>
</resource>
<!-- CMN models -->
<resource>
<directory>model</directory>
</resource>
<!-- generated resources (e.g. OpenAPI) -->
<resource>
<directory>src/generated/resources</directory>
</resource>
</resources>
<plugins>
<!-- JoinedWorkz generator -->
<plugin>
<groupId>org.joinedworkz.cmn</groupId>
<artifactId>cmn-maven-plugin</artifactId>
<version>${joinedworkz.version}</version>
<executions>
<execution>
<?m2e ignore?><!-- ignore this execution in Eclipse -->
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- register generated Java sources (optional, if you generate Java) -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<id>add-generated-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${basedir}/src/generated/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>Add the Spring Boot facility (or the facility you need) as a dependency:
<dependencies>
<!-- JoinedWorkz facilities (SpringBoot, brings in Java + Base) -->
<dependency>
<groupId>org.joinedworkz.facilities</groupId>
<artifactId>spring-boot</artifactId>
<version>${joinedworkz.version}</version>
<scope>provided</scope>
</dependency>
<!-- your existing dependencies -->
...
</dependencies>3.2 Add a first CMN model
Create a model/ directory next to src/main/java and src/main/resources and add a CMN file, for example:
model/customer-api.cmn
api package com.example.existing.api
import org.joinedworkz.facilities.common.base
import org.joinedworkz.facilities.common.base.api
import org.joinedworkz.facilities.profiles.springboot
import org.joinedworkz.facilities.springboot.api
platform SpringBoot
type<entity> Customer {
id**: Id
firstName*: Name
lastName*: Name
email: String(255)
}
resource /customers as Customer[] by id {
queryEntities()
createEntity()
readEntity()
updateEntity()
deleteEntity()
}You can now:
- run
mvn clean package - or open the project in JoinedWorkz Studio and generate from there
With the default outlets from Base and SpringBoot, inspect these configured output directories:
src/generated/resources/openapifor model-scoped OpenAPI;diagram/apifor matching OpenAPI viewers;src/generated/javafor Java output selected by the platform.
The exact file names derive from the effective model and component namespaces. This illustrative integration fragment is not assigned invented expected file names. See the Spring Boot example for release-built, exact paths.
The resource-only model above produces the model-scoped OpenAPI document. In SpringBoot 1.3.80, add a component with provide /customers before expecting a generated API interface or controller. That component also produces the additional component-scoped OpenAPI aggregate.
3.3 Use generated artefacts from existing code
How you integrate the generated artefacts depends on what you generate:
OpenAPI
Use the generated YAML/HTML as the source of truth for your API docs, or feed the OpenAPI into your existing tooling (e.g. client generation).DTOs Let JoinedWorkz generate DTOs and reference them from your hand-written controllers or services instead of writing DTOs by hand.
API interfaces and controllers Define a component that provides the resource. SpringBoot generates the API interface and controller from that
provideboundary, not from a resource model alone. Treat the generated files as replaceable output. Keep business logic in project-owned services outsidesrc/generated/**; do not adopt generated controller files as manually maintained sources. The canonical release example calls its generatedCustomerDataAccessServicedirectly and does not demonstrate a manual handler layer.See also Spring Boot facility
A common pattern is:
- generate DTOs from CMN,
- add a component
provideboundary when you want a generated API interface/controller and component OpenAPI aggregate, - keep manual business logic behind the generated boundary,
- let the CMN model and facilities handle OpenAPI and documentation.
4. Option B – Add a dedicated model module
For larger projects or when you want to keep modelling concerns separate, create a dedicated model module and route outputs into existing modules.
4.1 Create a model module
Add a new Maven module (for example model) to your multi-module project:
<modules>
<module>model</module>
<module>backend</module>
<module>webapp</module>
...
</modules>In model/pom.xml:
<project>
...
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<joinedworkz.version>1.3.80</joinedworkz.version>
</properties>
<dependencies>
<dependency>
<groupId>org.joinedworkz.facilities</groupId>
<artifactId>spring-boot</artifactId>
<version>${joinedworkz.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>model</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.joinedworkz.cmn</groupId>
<artifactId>cmn-maven-plugin</artifactId>
<version>${joinedworkz.version}</version>
<executions>
<execution>
<?m2e ignore?><!-- ignore this execution in Eclipse -->
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>In this module you only keep:
- CMN models (e.g. domain, API, backend components)
- no hand-written Java code
4.2 Route outputs with layers and facility-specific outlets
Use joinedworkz.properties in the root of the model module (or project) to route generated outputs into existing modules. A layer such as core can select a source-tag-specific directory when the responsible generator passes that layer. Other outputs must use their actual facility outlet.
Example for a project with:
backendmodule (services, domain, persistence)webappmodule (Spring Boot application, controllers, HTTP boundary)
model/joinedworkz.properties:
# default for generated Java sources
outlet.generatedJavaSource.directory=src/generated/java
# domain-related Java code (core layer) to backend module
outlet.generatedJavaSource.core.directory=../backend/src/generated/java
# SpringBoot controller/API output to web module
outlet.generatedApiSource.directory=../webapp/src/generated/java
# OpenAPI and HTML viewers globally to the web module
outlet.generatedOpenApi.directory=../webapp/src/generated/resources/openapi
outlet.generatedOpenApiHtml.directory=../webapp/diagram/apiThe exact outlet names depend on the platform (see the Base and SpringBoot profiles):
outlet.<outletName>.directory– default directoryoutlet.<outletName>.<sourceTag>.directory– source-tag mapping, but only when the generator passes that tag
In release 1.3.80, Java generators writing to generatedJavaSource can use the CMN layer as their source tag. SpringBoot controller/API output uses the distinct generatedApiSource outlet; the global override above also catches output derived from an untagged component model. The Base OpenAPI and OpenAPI HTML generators do not pass a source tag, so their mappings above are also deliberately global. Make sure the target modules (backend, webapp, …) register these directories as resources or sources as described in the Maven plugin reference.
4.3 Build order in the parent POM
In a multi-module setup, ensure that the model module is built first so that generated artefacts are available when compiling dependent modules.
In the parent pom.xml:
<modules>
<module>model</module>
<module>backend</module>
<module>webapp</module>
</modules>Maven respects the module order (as long as there are no conflicting dependency cycles), so the generators in model run before backend and webapp are compiled.
5. Gradual adoption patterns
You do not need to model the whole existing system at once. Common gradual steps are:
OpenAPI only
Start by modelling just the REST resources in CMN and generate OpenAPI and diagrams. Keep all implementation code unchanged.Introduce DTOs
Add CMN types (entities, projections) and let JoinedWorkz generate DTOs. Use the generated DTOs in your existing controllers/services instead of hand-written ones.Introduce component / application models
Use a component to combine all endpoints in itsprovidedeclarations into an additional component-scoped OpenAPI document, even when the resources come from several imported CMN models. Applications add the higher-level diagrams; release 1.3.80 does not create another OpenAPI aggregate per application.Optional: Generated API interface and controller
When you are comfortable with the model, let the SpringBoot platform generate an API interface and controller from the component's
provideboundary. Keep additional manual business services outside the replaceable generated tree.
Throughout this process, your existing Java code remains in control of the runtime behaviour. JoinedWorkz augments the project with generated artefacts that you can adopt step by step.
6. Summary
To integrate JoinedWorkz into an existing Java project:
Decide on a strategy
- integrate into an existing module, or
- create a dedicated model module and route outputs via outlets.
Add the facilities and Maven plugin
Include the appropriate facility (Base, Java, SpringBoot, …) and configure thecmn-maven-pluginas described above.Create CMN models
Start small – for example with one API and its key types – and grow the model over time.Configure resources and generated sources
Register generated resource/source directories in the modules that use them.Use the generated artefacts
Wire OpenAPI, DTOs and (optionally) generated API/controller boundaries into your existing project, gradually replacing hand-written boilerplate where it makes sense.
For concrete CMN examples, see:
- Model a REST API step by step
- the self-contained Quickstart
- the Examples status page, which identifies the verified release source for each example role
