Skip to content

Add design documentation for extension mechanism - #9

Open
wborn wants to merge 16 commits into
mainfrom
docs/extension-mechanism-design
Open

Add design documentation for extension mechanism#9
wborn wants to merge 16 commits into
mainfrom
docs/extension-mechanism-design

Conversation

@wborn

@wborn wborn commented Feb 19, 2026

Copy link
Copy Markdown
Member

Introduces the Technical Design Specification for decoupling domain-specific logic (Energy, Protocols, UI) from the platform Core.

Closes openremote/openremote#2327

Introduces the Technical Design Specification for decoupling domain-specific logic (Energy, Protocols, UI) from the platform Core.

Closes openremote/openremote#2327
@wborn wborn added the Documentation Improvements or additions to documentation label Feb 19, 2026
Comment thread DESIGN.md

@ebariaux ebariaux left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a great start, I think you covered quite a bit of ground and it's good to have things explicitly described and written down.

I made quite a few comments that I think will be subjective. My proposal would be that once there's been feedback from a few reviewers, we organise a session to go over all the remarks and align on a direction to proceed with.

Comment thread DESIGN.md Outdated
Comment thread DESIGN.md
Comment thread DESIGN.md
Comment thread DESIGN.md
Comment thread DESIGN.md Outdated
Comment thread DESIGN.md
Comment thread DESIGN.md
Comment thread DESIGN.md Outdated
Comment thread DESIGN.md Outdated
Comment thread DESIGN.md Outdated
@pierrekil

Copy link
Copy Markdown
Member

For agents, also ENTSOE, openWeather, battery simulator might become extensions

@pierrekil

Copy link
Copy Markdown
Member

@remyberden and @pierrekil: Good to think about naming conventions and way we explain from a marketing communication perspective to less/non technical users.

@MartinaeyNL MartinaeyNL left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a really well written document! Thanks! 👏

Only two small comments from my own pair of eyes. (and field of expertise I guess)
Feel free to respond or explain details.

Comment thread DESIGN.md
Comment on lines +151 to +172
energy/
├── src/main/java/org/openremote/extension/energy/
│ ├── model/ # Java Asset implementations
│ │ ├── ElectricityAsset.java
│ │ └── EnergyModelProvider.java # Implements AssetModelProvider SPI
│ ├── manager/ # Core logic & Container services
│ │ └── EnergyOptimisationService.java # Implements ContainerService SPI
├── src/main/resources/
│   ├── org/openremote/extension/energy/setup/database/ # Flyway scripts
│   │   └── V20260131_01__RenameEnumValues.sql
│ └── META-INF/services/ # SPI Registration
│ ├── org.openremote.model.AssetModelProvider
│ ├── org.openremote.model.ContainerService
│ ├── org.openremote.model.ExtensionMetadata
│ └── org.openremote.model.setup.SetupTasks
├── src/test/groovy/org/openremote/extension/energy/
│ ├── EnergyOptimisationTest.groovy # Spock Integration Tests
│ ├── ForecastSolarServiceTest.groovy
│ └── ManagerTestSetup.groovy # Test-specific environment logic
└── src/test/resources/
└── META-INF/services/
└── org.openremote.model.setup.SetupTasks # Test-only setup tasks

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, don't extensions have their own build.gradle file?
As in, I assume extensions can have their own third party dependencies outside of OpenRemote.
And the list of "other extensions it depends on" would be in one central place,
so either in build.gradle or inside the org.openremote.model.ExtensionMetadata file, not both.
Or do I misunderstand something?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gradle dependencies and extension dependencies serve different purposes.

Gradle defines the dependencies required to build and run the extension code, while ExtensionMetadata defines logical dependencies used by Manager for extension activation and validation. These may overlap, but don't necessarily have to. For example, a composite extension could depend on several other extensions without having compile-time dependencies on them.

For the initial implementation the extension dependencies are explicitly declared in ExtensionMetadata to keep things simple. We could later consider deriving or validating this information from the Gradle configuration if that proves useful.

Also added build.gradle to the extension artifact layout diagram for completeness.

Comment thread DESIGN.md Outdated
The `OR_ENABLED_EXTENSIONS` environment variable is introduced.

* **Behavior**: The Manager filters the discovered `ExtensionMetadata` list. The Manager automatically activates all transitive dependencies declared in the metadata.
* **Persistence**: The list of active extension IDs is persisted in `manager_config.json`.

@MartinaeyNL MartinaeyNL Mar 5, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm totally against persisting this info inside the manager_config.json 😂
It's better to, as a first step, introduce a simple HTTP GET endpoint to retrieve the list of installed extensions.
That would prevent multiple sources of truth, and prevents breaking changes when extending this API.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just got context from @wborn on what the persistence is meant for.

Apparently it's the other way around, where we would persist OR_ENABLED_EXTENSIONS inside the manager_config.json file. However, this is not the intended use of this config file, as it's the "configuration of the Manager User Interface". So we'd probably store this in a separate extensions.json file instead.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it's probably better to persist it in another file. I've removed this implementation detail in 599c232.

Comment thread DESIGN.md
Comment thread DESIGN.md Outdated
@wborn
wborn requested review from a team, Ekhorn, MartinaeyNL and ebariaux September 2, 2026 14:14
Comment thread DESIGN.md
### Dependency Management (Build-time)

Extensions are developed as independent Gradle projects.
To include an extension in an OpenRemote deployment, it is added as a standard dependency in the project's `build.gradle`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To include an extension in an OpenRemote deployment, it is added as a standard dependency in the project's `build.gradle`.
To include an extension in an OpenRemote deployment, it is added as a standard dependency in the project's `build.gradle` file.

Comment thread DESIGN.md
To include an extension in an OpenRemote deployment, it is added as a standard dependency in the project's `build.gradle`.

- **Transitive Dependencies**: Gradle handles the resolution of shared libraries between the Core and multiple extensions, ensuring a consistent and conflict-free classpath.
- **Composition**: Composite Extensions define a collection of dependencies in their `build.gradle`, allowing a developer to include a single "Composite" artifact to pull in a complete suite of functional and data modules.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- **Composition**: Composite Extensions define a collection of dependencies in their `build.gradle`, allowing a developer to include a single "Composite" artifact to pull in a complete suite of functional and data modules.
- **Composition**: Composite Extensions define a collection of dependencies in their `build.gradle` file, allowing a developer to include a single "Composite" artifact to pull in a complete suite of functional and data modules.

Comment thread DESIGN.md
### Repository Structure

The monorepo uses Gradle subprojects to isolate each extension.
A shared `build.gradle` in the root provides common build logic, ensuring all extensions use the same compiler settings and dependency versions.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A shared `build.gradle` in the root provides common build logic, ensuring all extensions use the same compiler settings and dependency versions.
A shared `build.gradle` file in the root provides common build logic, ensuring all extensions use the same compiler settings and dependency versions.

Comment thread DESIGN.md
- **Discovery**: The Manager discovers the available extensions through the `ExtensionMetadata` SPI.
- **Activation**: The Manager determines the active extension set from `OR_ENABLED_EXTENSIONS` and automatically includes transitive extension dependencies declared in the metadata.
- **Component Filtering**: `AssetModelProvider`, `SetupTasks`, `ContainerService`, and other extension components belonging to inactive extensions are not initialized or registered. The existing SPI discovery mechanisms therefore need to become extension-aware.
- **Validation**: The Manager validates that required extension dependencies are present and detects invalid or circular dependency configurations before initialization.

@Ekhorn Ekhorn Sep 11, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume "invalid" includes conflicting asset types, or other model definition names? And so thinking about the future. If we ever have e.g. "unofficial" extensions conflicting with "official" asset types people using "UI-Driven Configuration" would need be informed about this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create design for extension mechanism

5 participants