Skip to content

Conversation

@holly-cummins
Copy link
Contributor

It's only five releases overdue :)

@github-actions
Copy link

github-actions bot commented Nov 13, 2025

🎊 PR Preview 7ca167d has been successfully built and deployed to https://quarkus-site-pr-2460-preview.surge.sh

  • Images of blog posts older than 3 months are not available.
  • Newsletters older than 3 months are not available.

Copy link
Contributor

@ozangunalp ozangunalp left a comment

Choose a reason for hiding this comment

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

That is very good, Thanks @holly-cummins !

I've added some minor recommendations


----

Deciding whether to re-use or replace a service is now handled centrally, based on a diff of the configuration.
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we need to give some more context on this. How this was done before in dev service implementations.

Edit:

The article speaks about it later, maybe a word with a link to eligibility ro re-use would suffice


==== The `Startable`

In order to support lazy starting, pass an implementation of `Startable` to the builder.
Copy link
Contributor

Choose a reason for hiding this comment

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

It is obvious to us, but we can add here a note NOT to call start before passing the startable


=== How can I have a build step do something after a dev service is started?

This isn’t possible, because a dev service would never be started in the build phase. However, the `postStartHook` on the builder allows you to take actions once the dev service is started.
Copy link
Contributor

Choose a reason for hiding this comment

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

The postStartHook covers one of the use cases for the current build steps after the dev service starts.
There is another one for injecting configuration into the application through recorders, etc.

We can include a recommendation for how to resolve this second issue using Config in recorders.


If you have test suites which use multiple profiles or test resources, you should find that you no longer see duplicate containers active at the same time. The containers should launch one after the other.

However, this depends on the extension, because every extension needs to be converted to the new model. The Redis, Lambda, Nayarana, and Kafka extensions have been converted so far. You can track progress with the conversions by following the sub-issues of https://github.com/quarkusio/quarkus/issues/45785[#45785].
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
However, this depends on the extension, because every extension needs to be converted to the new model. The Redis, Lambda, Nayarana, and Kafka extensions have been converted so far. You can track progress with the conversions by following the sub-issues of https://github.com/quarkusio/quarkus/issues/45785[#45785].
However, this depends on the extension, as each needs to be converted to the new model. The Redis, Lambda, Narayana, and Kafka extensions have been converted so far. You can track progress on conversions by following the sub-issues in https://github.com/quarkusio/quarkus/issues/45785[#45785].


[source,java]
----
DevServicesResultBuildItem = DevServicesResultBuildItem.owned().name(MY_FEATURE_NAME)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
DevServicesResultBuildItem = DevServicesResultBuildItem.owned().name(MY_FEATURE_NAME)
var item = DevServicesResultBuildItem.owned().name(MY_FEATURE_NAME)

useSharedNetwork)
.withEnv(myConfig.containerEnv())
.configProvider(
Map.of(someProp, s -> s.getConnectionInfo()))
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Map.of(someProp, s -> s.getConnectionInfo()))
Map.of(someProp, s -> s.getConnectionInfo())
)


Because service lifecycle is handled centrally, any shutdown listeners or other logic for stopping services should also be removed.

=== Remove any references to `RunningDevService`
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
=== Remove any references to `RunningDevService`
==== Remove any references to `RunningDevService`


All dev services using the old API start in the JUnit discovery phase (as of Quarkus 3.22). This is because they are started during https://quarkus.io/guides/reaugmentation#what-is-augmentation[the augmentation phase], along with bytecode manipulation and other application initialization steps. When the testing design changed, all augmentation happened at the beginning of the test run, during the JUnit discovery phase. This means all Dev Services also start at the beginning of the test run. If several test classes with different Dev Service configuration are augmented before any tests are run, multiple differently-configured Dev Services may be running at the same time.

In the new model, Dev Services are started post-augment, and pre-launch.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
In the new model, Dev Services are started post-augment, and pre-launch.
In the new model, Dev Services are started between the augmentation and the application's actual launch.


As always, if you spot issues or oddities, please let us know on https://quarkusio.zulipchat.com/[zulip] or https://github.com/quarkusio/quarkus/issues[raise an issue].

=== Technical details
Copy link
Member

Choose a reason for hiding this comment

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

Maybe "Why this change was needed" or "Background".

The rationale is that this subsection is under "What changes for users" (and you said nothing), but then why should they care about the technical details?


==== Dependency changes and setting a minimum Quarkus version

This bit is a bit awkward, unfortunately! In Quarkus 3.28, a new `devservices` runtime module was introduced. Most extensions have both a deployment and a runtime model, but historically, Dev Services only had a deployment module. The associated runtime classes lived in other modules. A runtime module was added in 3.28. Because it was a potentially disruptive change, it was done post-LTS. That seemed like a good idea, but had some unexpected consequences.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
This bit is a bit awkward, unfortunately! In Quarkus 3.28, a new `devservices` runtime module was introduced. Most extensions have both a deployment and a runtime model, but historically, Dev Services only had a deployment module. The associated runtime classes lived in other modules. A runtime module was added in 3.28. Because it was a potentially disruptive change, it was done post-LTS. That seemed like a good idea, but had some unexpected consequences.
This bit is a bit awkward, unfortunately! In Quarkus 3.28, a new `devservices` runtime module was introduced. Most extensions have both a deployment and a runtime module, but historically, Dev Services only had a deployment module. The associated runtime classes lived in other modules. A runtime module was added in 3.28. Because it was a potentially disruptive change, it was done post-LTS. That seemed like a good idea, but it had some unexpected consequences.

- Do not use static variables in the extension processor
- Use the `discovered()` and `owned()` builders in `DevServicesResultBuildItem`
- Config which is only known after the service is started can be passed in using a `configProvider()`

Copy link
Member

Choose a reason for hiding this comment

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

Can we have a checklist? The section is rather long (and the dependency part slightly overwhelming (I had to read it twice)), if we could introduce a checklist with all actions, the owner could just see the action plan.

layout: post
title: 'A Better Way of Creating Dev Services'
tags: announcement testing
synopsis: ''
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
synopsis: ''
synopsis: 'A new Dev Services API in Quarkus 3.25 fixes port conflicts and excessive resource usage in test suites, while providing a simpler programming model for extension authors.'

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants