Skip to content

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 17 and, for REST, a Spring Boot stack – but the patterns apply to other Java technologies as well.

For background reading see:


1. Integration strategies

There is no single “right” way to introduce JoinedWorkz into an existing project. In practice, three patterns work well:

  1. 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.

  2. 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 via joinedworkz.properties.

  3. 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 17 or higher (aligned with the JoinedWorkz examples)
  • 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:

xml
<properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <joinedworkz.version>1.3.74</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:

xml
<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:

xml
<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
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.spring.boot

platform SpringBoot

type<entity> Customer {
    id**:       Id
    firstName*: Name
    lastName*:  Name
    email:      String(255)
}

resource /customers as Customer[] by id {

    query(^page: Integer, pageSize: Integer)
    create()
    read readCustomer()
    update()
    delete()
}

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, you will get:

  • OpenAPI in src/generated/resources/openapi/...yaml
  • optional HTML viewer in diagram/api/...
  • optional Java artefacts in src/generated/java/... (depending on the platform)

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 / API interfaces
    Let JoinedWorkz generate DTOs and/or API interfaces and reference them from your hand-written controllers or services instead of writing DTOs by hand.

  • Controllers
    If you let the SpringBoot platform generate controllers, you can:

    • either implement only the business logic in separate service classes and call them from the generated controllers, or
    • use the generated controllers as a starting point and keep them under version control (accepting that regeneration may require manual merges).

    See also Spring Boot facility

A common pattern is:

  1. generate interfaces (or DTOs) from CMN,
  2. implement those interfaces in your existing code,
  3. 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:

xml
<modules>
    <module>model</module>
    <module>backend</module>
    <module>webapp</module>
    ...
</modules>

In model/pom.xml:

xml
<project>
    ...
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <joinedworkz.version>1.3.74</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 into existing modules with layers

Use joinedworkz.properties in the root of the model module (or project) to route generated outputs into existing modules. Layers like core and api help distinguish between domain and API boundary artefacts.

Example for a project with:

  • backend module (services, domain, persistence)
  • webapp module (Spring Boot application, controllers, HTTP boundary)

model/joinedworkz.properties:

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

# API controllers and DTOs (api layer) to web module
outlet.generatedJavaSource.api.directory=../webapp/src/generated/java

# OpenAPI only for the API layer
outlet.generatedOpenApi.api.directory=../webapp/src/generated/resources/openapi
outlet.generatedOpenApiHtml.api.directory=../webapp/diagram/api

The exact outlet names depend on the platform (see the Base and SpringBoot profiles), but the pattern is always the same:

  • outlet.<outletName>.directory – default directory
  • outlet.<outletName>.<layer>.directory – per-layer override

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:

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:

  1. OpenAPI only
    Start by modelling just the REST resources in CMN and generate OpenAPI and diagrams. Keep all implementation code unchanged.

  2. 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.

  3. Introduce component / application models
    Model components and applications to get better diagrams and aggregated OpenAPI documents, without touching the runtime architecture.

  4. Optional: Generated controllers + handlers
    When you are comfortable with the model, let the SpringBoot platform generate controllers and handler interfaces. Implement the handlers in your own code and keep business logic in terms of domain types.

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:

  1. Decide on a strategy

    • integrate into an existing module, or
    • create a dedicated model module and route outputs via outlets.
  2. Add the facilities and Maven plugin
    Include the appropriate facility (Base, Java, SpringBoot, …) and configure the cmn-maven-plugin as described above.

  3. Create CMN models
    Start small – for example with one API and its key types – and grow the model over time.

  4. Configure resources and generated sources
    Register generated resource/source directories in the modules that use them.

  5. Use the generated artefacts
    Wire OpenAPI, DTOs and (optionally) controllers/handlers into your existing project, gradually replacing hand-written boilerplate where it makes sense.

For concrete CMN examples, see: