Operaton 2.0 Scope

Migrating to Spring Boot 4, Spring Framework 7, or Quarkus 4 will require broader refactorings. All now depend on Jakarta EE 11, breaking binary compatibility through the move from javax.* to jakarta.*. Together with Jackson *, updated servlet and JPA specs, and newer runtime requirements, this is a platform-level change, not a simple upgrade.

1 Like

We should discuss whether to include a topic on test directory structure and JUnit 4 support in the 2.0 roadmap. The current multi-root layout (src/main/junit-shared, src/main/junit4, src/main/junit5, …) was introduced during migration but is, in my opinion, difficult to maintain and causes IDE and build issues.

To make the project easier to access for new contributors, align with the standard Maven layout, and reduce build complexity, we could consider the following for 2.0:

  • Consolidate all tests into the standard Maven layout
  • Drop JUnit 4 / Vintage support
  • Move shared test utilities (currently under src/main/junit-shared) out of main into a dedicated test-utils module (used with scope=test)

This would simplify builds, improve developer experience, and align the project with modern tooling.

2 Likes

IMHO we can’t drop JUnit 4 support. There are many user projects that we do not force to migrate their tests. It was a major act to do this ourselves, but we surely can’t put the burden on others.

With the src/main/junit4 & src/main/junit5 sources we have adressed the issue that tests in engine are using these rules/extensions, while the rules/extensions must have access to the engine. I’m not sure if we could solve this by seperation into a different module.

src/main/junit-shared can be separated. Actually the sources are independent from JUnit, so the folder name is not accurate. I think it should also be possible on a 1.x stream.

In general, I also have the feeling that we should better do the platform changes and larger refactorings on a 2.x stream. But we need agreement and development power for it.

Hi @kthoms,

I agree we shouldn’t force users to do anything. Maintaining a 1.x LTS line might be the right approach for users who need stability. It gives projects depending on Operaton a safe and predictable base. However, it’s equally important that this branch does not determine the technical direction of Operaton 2.x.

The upcoming updates to Spring Framework 7, Spring Boot 4, and Jackson 3 are changes that will impact Operaton significantly. They raise the baseline to Java 21 and Servlet 6.1, aligning Operaton with the Jakarta EE 11 ecosystem. Because Boot 4 removed the built-in Jersey starter, we have to find a different solution for REST integration, at least until Jersey becomes fully JAX-RS 4 compatible. The WildFly distribution will also be affected, as WildFly itself needs to migrate to Jakarta EE 11, which will impact Operaton’s WildFly distribution. The core engine is mostly unaffected, as it uses MyBatis and only light Spring abstractions like BeanFactory and transaction management.

The bigger changes happen in engine-rest. Jackson 3 introduces stricter polymorphism rules, so a centralized JsonMapper becomes essential. It will likely be hard or even impractical to support Jackson 2 and 3 at the same time, given the breaking API and behavioral differences.

On the testing side, Boot 4 and Spring 7 no longer support legacy JUnit 4 runners. With JUnit 6 released in September 2025, adopting JSpecify and requiring Java 17+, the gap between JUnit 4 and modern toolchains has become too wide. For Operaton 2.x, the engine itself should be tested exclusively with JUnit 6. This ensures long-term compatibility with newer JDKs. Applications using Operaton can test BPMN, DMN, and CMMN through the JUnit Platform (JUnit 5 and 6). For legacy users, a small optional bridge (for example a vintage-junit module) could provide minimal JUnit 4 compatibility.

To support this, I would suggest all test utilities should be moved into dedicated modules following a standard Maven layout, so they can be better maintained separately. The current multi-root structure mixes production and test code and complicates IDE and build setups. A clearer split such as process-engine-junit5, dmn-engine-junit5, and engine-test-common would improve maintainability and make dependencies more explicit — this is also a common practice in many Java projects. Legacy modules like process-engine-junit4 could stay but are clearly separated, so they can also be maintained separately without any problem.

This is also important from a compliance and lifecycle perspective. Frameworks like JUnit 4 are no longer maintained and create potential issues under EU CRA, ISO 27001, or OWASP. Even if I’m currently unsure what the concrete impact of these regulations will be on open source projects, they already raise expectations for up-to-date and secure dependencies. Continuing to rely on outdated dependencies would raise security and audit concerns. Maintaining LTS branches can also become a significant amount of work, and we should be careful not to over-promise here — especially until there’s a sponsor willing to cover the effort involved. IMHO, projects unwilling to migrate should not implicitly define Operaton’s roadmap. The core project must not be held back by those unwilling to upgrade. The longer we postpone modernization, the greater the eventual risk and migration effort becomes.

The move to Spring 7, Boot 4, and Jackson 3 shows how difficult it will be to maintain the status quo and move forward at the same time. The underlying technologies now introduce breaking changes at the platform level — Jakarta EE 11, Servlet 6.1, and Jackson 3 all require updated contracts. Supporting older stacks in parallel would lead to fragmentation and high maintenance overhead. Modernization is no longer a choice; it’s a technical necessity if Operaton wants to stay aligned with its upstream ecosystem.

That said, we may have to take a step back and define clear project goals that can act as a direction in the roadmap discussion. Are we primarily maintaining a stable base for existing Camunda 7 users? Do we want to offer a fully open-source stack that remains aligned with upstream OSS lifecycles? Or do we aim to grow Operaton as a modern BPM engine that reflects today’s needs in automation, observability, and security?

These directions are not mutually exclusive, but they do require prioritization. If the goal is to preserve compatibility, 1.x can continue as a maintained branch. If the goal is to evolve, 2.x should deliberately move forward — adopting Java 21+, Spring 7, Quarkus 4, and the JUnit 6 platform, while simplifying structure and cleaning up deprecated APIs.

In summary, Operaton 2.x should represent a clear modernization step. The core runs on Java 21+, Spring 7, Quarkus 4, Jackson 3, and Servlet 6.1. Tests are based on JUnit 6, with an optional vintage bridge. The build follows a clean, Maven-compliant structure. This keeps Operaton sustainable, compliant, and attractive for new users — while the 1.x LTS line continues to serve those who value stability. The legacy line provides continuity, but the mainline should define the future.

1 Like

This discussion is very interesting and important. I am thinking to make a podium discussion out of it on Nov 21st. Would 1h be enough as a slot?

This is something I’ve been thinking about a lot recently. Operaton already has users who run it in production and actively engage with our community. From what I’ve seen, most of them are using modern technology stacks and are not heavily dependent on legacy frameworks.

I believe our focus should be on these real users - understanding their use cases, learning from their feedback, and evolving the product based on their needs rather than trying to anticipate what potential users might want.

Over the next few months, the (ex C7) community/customers will naturally decide whether Operaton serves as a sufficient replacement for C7 for them or not. After that, our goal should be to continue building a solid, modern solution that can stand alongside other open-source BPM systems like jBPM, Kogito, Flowable or other systems that may arise in the next years.

So, I’m fully in support of taking a pro-modernization path here.

2 Likes

This is the part where we should talk about the definition what “Operaton” is. To me the core of Operaton is its engine. The engine can be integrated into different environments and a heterogeneous infrastructure with its integrations. Modernizing these integrations does not require a breaking change in the engine itself. I would even argue, that we should take care that the integrations do not affect the engine in any meaningful way.

Currently, the integrations carry the same version number as the engine, which makes sense, because they rely heavy on the engine, and every new engine feature needs to be propagated to those integration libraries. Because of this, all of the artifacts from the whole monorepo carry the same version numbers, all of the time.

If we now consider to raise the Spring and Spring Boot integrations to the next framework versions, this is a breaking change to those integrations. If we continue the versioning schema, this would mean raising the version to the next major version for all the artefacts. This will also need to be done for any future updates. New Spring version? Operaton 3.0. New Jakarta Version, 6 months later? Operaton 4.0. New Quarkus version…?

My suggestion was to extend the names of the integration modules with the target version of the framework. We add a engine-spring-7 module, we add an spring-boot-4-starter module, additionaly to the existing modules. They will be in sync with the Operaton versioning scheme, e.g “Spring Boot 4 Starter, 1.1.3”. If Spring Boot 3 reaches its EOL, we will stop providing the Spring Boot 3 Starter, but keep providing the Spring Boot 4 starter. This keeps our distributions flexible, is not a breaking change to Operaton, but a breaking change to this module.

With this approach we can update and modernize the integrations individually, without tying them together as a whole and muddling the integrations versioning scheme with our own.

3 Likes

Starting with the Spring 7/SpringBoot 4/Jakarta 11/JUnit 6 PoC a lively discussion arose on Slack that is worth persisting here.

The PoC contains already significant platform upgrades and is surely breaking in its current state. Thus, following semantic versioning, it must be a major version change.
@javahippie would like to have a stable, official release with SpringBoot 4 support soon. This does not mean that there can’t be a version 1.1.0 as planned. We can even switch `main` to 2.0 and Spring 7/SB4/Jakarta11, we just need to conserve the current 1.1.0 main branch as `release/1.1.x`.

What does “soon”, “stable”, “official” mean? I could imagine to bring a 2.0 Beta version rather soon, mainly once the PoC is stable and merged. But “official”, “stable” would mean a 2.0 final? If we make a 2.0, I would like to have a bit time for it. Maybe around March? If we make this step, I would like to clean up also API that is marked for removal and consider further platform upgrades, when we are already on it.

So my proposal:

  1. release 1.1 in Feb 26 as announced
  2. branch `main` → `release/1.1.x` before merging S7/SB4 PoC to `main`
  3. change project version to `2.0.0-beta-1` on `main`
  4. merge S7/SB4 PoC to `main`
  5. clean up `main`
  6. stabilize
  7. release a beta-2 in Feb, along with 1.1.0
  8. plan the 2.0 release date

From my point of view: I’m not sure if I’m comfortable with the pace we are striking here. Our initial messaging was stability, and from the release party I was under the impression that this is appreciated.

It is a good thing that we will provide 1.x as a long maintained alternative. However, for most(!) Spring Boot users, our 1.x will be unusable in June because they cannot be on Spring Boot 3 anymore. I assume that this is by now a majority of our potential userbase, Spring Boot is very popular. So for many people, “you can stay on 1.x” is not a possibilty for them.

Releasing a 2.0 because of breaking changes would work for me, this takes semantic versioning seriously. If we now put more breaking changes into the release, like removing deprecated methods, this means, that teams who migrated from Camunda 7 to Operaton will face additional migration effort – maybe even more effort than switching from C7 to Operaton 1. Users who waited a little and will migrate from C7 to Operaton 2 will also have a rougher migration path when they have to work around removed methods (or we need a way more complex open rewrite recipe). Is removing these deprecated methods this important, do we really need to do this that soon? We should avoid thinking “It’s a major release anyway, now we can add more breaking changes”.

I’m also not sure what a 1.1.x would contain, if a 2.0 would be released in March. Would we backport new features into the 1.x branch? That would raise the question how many 1.x. versions we should and can maintain at the same time, this will become more and more complex and time consuming.

I’m not completely decided what my preferred route is, but right now our next release is snowballing from “a new feature + additional Spring Boot 4” via “Jakarta EE11” to “Remove deprecated APIs” and I wanted to raise awareness to that.

I would like someday to come to a cleaner API, and we have marked methods for removal that should not be used anymore. This only can be done with a major version change. So, yes, I propose this with the background “it is a major release anyway” (and I am not sure when there will be another). Such cleanup usually does not have weight enough to qualify for a major increment, thus it needs being piggy-backed. But I could live if that is too early now, since we are still ramping up existing users.

A 1.1 version does not contain much more than 1.0.x. A real “feature” is the distro-specific SBOMs. Besides that, it contains more version lifts than 1.0.x, since on the patch release only patch versions are updated. This includes updates of the Wildfly & Quarkus version. Thus a 1.1 version does make sense to me. The “cost” for that release is not that high.

What is clear to me is that the given PoC requires a major version lift. I really appreciate the work that has been done for that. It is giving a clear path.

As you mention, stability is important. So why do we need to rush finalizing a 2.0 version? We can soon deliver a beta version and test it thoroughly. Then carefully decide what we put else into it. What is already there is worth a major version already.

Would we backport new features into the 1.x branch?

Really depends on the case. Only if it is beneficial enough and easy to integrate.

how many 1.x. versions we should and can maintain at the same time,

If 2.0 is out, there is no reason to ship 1.2. There will be only 1.0 and 1.1 receiving patch updates.

We are looking forward to the early arrival of Version 2.0. Our upcoming new project has been confirmed to be based on Spring 4 and Java 21.

We will discuss the release topic tomorrow in a video call. Anyone is free to join.

When? Friday Dec 5th 2025 13:00-14:00 CET
Where? Google Meet

@kthoms Following the video call on Friday, are there any updates on the release strategy for the Spring Boot 4-compatible version of Operaton? Thank you!

The result of the call was that we’ll proceed with two release branches in parallel:

1.1.x – Long-Term Stability (Spring Boot 3)

We will issue a 1.1.x release that receives security updates throughout 2026.

This branch remains fully compatible with Spring Boot 3 and is intended for users who cannot upgrade to Spring Boot 4 any soon.

2.x – Next-Gen Line (Spring Boot 4 only)

In parallel, we’ll open a 2.x branch, where we plan to publish milestone releases as soon as the Spring Boot 4 integration (SB4) is completed and fully validated.

This branch will drop Spring Boot 3 support and move exclusively to Spring Boot 4.

You can find our Spring Boot 4 branch here → GitHub - operaton/operaton at explore/spring-7-upgrade

SB 4 in general is already working, but there there is still some work to be done. You can follow this PR → Explore Spring 7 Upgrade by cachescrubber · Pull Request #1683 · operaton/operaton · GitHub

We’re also preparing the adjustments for the roadmap and the communication for this, which we will release soon.

For the 2.x line, the intention is to follow a 6-month release cadence, like Camunda used to do it.

Lars did an in-depth analysis on different cadence models, and the conclusion was that a 6-month rhythm provides the best balance between predictability, innovation, and ecosystem stability.

What do you think? Does this strategy make sense to you?

2 Likes

Yes, I completely agree. :+1:

The six-month release cycle proved to work well with Camunda 7 and will also provide the Operaton project and its users with the necessary balance between predictability, innovation, and ecosystem stability (as you mentioned).

I would like to raise the question if raising the minimal Java version to 21 is an option for 2.0.

A concrete trigger for bringing up this question is that Jersey3 4.0.1 was compiled with Java 21, while 4.0.0 was still compatible. (see PR).

I would like to keep Java 17 as lower bound as long as possible. But this update - the raised Java requirement might be accidential - made me concern. What if other dependencies start also to raise the Java requirement? We won’t be able to upgrade them anymore.

As we promise to keep the 2.x stream at least 1 year open, it may be an option to raise the Java level now. Otherwise we have to wait upgrading the libraries until the next major release 3.0. Since this requirement change is fundamental I would consider it a breaking change.

WDYT? Shall we raise the minimal Java version for 2.0?

1 Like

Based on your reasoning, adopting Java 21 as the baseline version for Operation 2.0 is sensible and fully supported from my side - particularly because of the argument to ensure security‑related dependency upgrades within the 2.x stream.

I think this is a valid concern. While I also tend to be on the more conservative side when talking about the baselines, Java 21 is not that old, and even the slower organizations start adapting it.

On the other hand, most libraries we use are pretty common in the Java ecosystem, and Spring 7 / Spring Boot 4 sets the pace there. As Jersey3 is used in those frameworks, I’d be surprised if this behavior (in a patch version) was intentional (and it wasnt Jersey 4.0.1 contains classes w/ classfile version 65 (Java 21) · Issue #6064 · eclipse-ee4j/jersey · GitHub)

If we follow this line of thought and extend it, it could also happen that a dependency we reference sets the baseline to Java 25, suddenly. This is even less likely, though.

According to this survey from December, Java 21 is in the “Early Majority” phase. If you consider, that this phase also contains Spring Boot 3(!), we should be safe with the Java 21 baseline.

1 Like

After thinking about it some more: I still think that it is unlikely that any of the libraries we use raises their baseline to 21, soon. If this happened, we could always trigger a new major release if it was this important to us. Spring will set the pace here for the next months / years, and they stuck to 17. This way our previously communicated baseline still holds up just fine.

What do you think? Is there a risk that we are too reactive with major releases?