Skip to content

[#95] Mark build-bom mojo as thread safe - #94

Open
rhusar wants to merge 1 commit into
wildfly:mainfrom
rhusar:thread-safe
Open

rhusar wants to merge 1 commit into
wildfly:mainfrom
rhusar:thread-safe

Conversation

@rhusar

@rhusar rhusar commented Sep 10, 2026

Copy link
Copy Markdown
Member

Allows the plugin to run in parallel builds (-T) without Maven emitting the "not marked @threadsafe" warning and degrading to serial execution.

Audited the mojo for the usual parallel-build hazards:

  • No static mutable state. The only static members are the WILDCARD constant and the ModelWriter nested class.
  • Mojo instances are created per execution, so all @parameter and @component fields are thread confined. This covers the in-place mutation of configuration objects in initializeModel() (parent version) and resolveDependency() (includeDependencies entries).
  • addDependencyManagement() operates on mavenProject.clone(), and MavenProject.deepCopy() clones the underlying Model, so the reactor's MavenProject is never mutated when the resolver project's dependencies and dependency management are rewritten.
  • addBuilderManagedDependency() clones each source dependency before changing its version, scope or exclusions, so the source project's dependency management list is not modified in place.
  • The injected components (ProjectDependenciesResolver, RepositorySystem, ProjectBuilder, ArtifactHandlerManager) are Maven singletons intended for concurrent use; repositorySystemSession and repositories are only read.
  • MavenProject and MavenSession are injected through the mojo execution scope, which is backed by a ThreadLocal, so each thread gets its own instances.
  • The BOM is written to the project's own build directory, so concurrent reactor modules cannot write the same file.
  • OrderedProperties is documented as not thread safe, but a fresh instance is created per execution and never escapes the thread.
  • The one remaining write to state shared between threads is MavenSession.getProjectBuildingRequest(), which lazily creates and then mutates the single ProjectBuildingRequest owned by the MavenExecutionRequest. That happens inside Maven core, every thread writes the same repository session, and the result is immediately copied into a new DefaultProjectBuildingRequest before use.

@rhusar
rhusar requested a review from emmartins as a code owner September 10, 2026 16:03

@emmartins emmartins left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks good, may I just ask you to create an issue for this change at https://github.com/wildfly/wildfly-bom-builder-plugin/issues ?

@rhusar

rhusar commented Sep 11, 2026

Copy link
Copy Markdown
Member Author

Ok will do.

@rhusar rhusar changed the title Mark build-bom mojo as thread safe [#95] Mark build-bom mojo as thread safe Sep 13, 2026
Allows the plugin to run in parallel builds (-T) without Maven emitting
the "not marked @threadsafe" warning and degrading to serial execution.

Audited the mojo for the usual parallel-build hazards:

* No static mutable state. The only static members are the WILDCARD
  constant and the ModelWriter nested class.

* Mojo instances are created per execution, so all @parameter and
  @component fields are thread confined. This covers the in-place
  mutation of configuration objects in initializeModel() (parent
  version) and resolveDependency() (includeDependencies entries).

* addDependencyManagement() operates on mavenProject.clone(), and
  MavenProject.deepCopy() clones the underlying Model, so the reactor's
  MavenProject is never mutated when the resolver project's dependencies
  and dependency management are rewritten.

* addBuilderManagedDependency() clones each source dependency before
  changing its version, scope or exclusions, so the source project's
  dependency management list is not modified in place.

* The injected components (ProjectDependenciesResolver, RepositorySystem,
  ProjectBuilder, ArtifactHandlerManager) are Maven singletons intended
  for concurrent use; repositorySystemSession and repositories are only
  read.

* MavenProject and MavenSession are injected through the mojo execution
  scope, which is backed by a ThreadLocal, so each thread gets its own
  instances.

* The BOM is written to the project's own build directory, so concurrent
  reactor modules cannot write the same file.

* OrderedProperties is documented as not thread safe, but a fresh
  instance is created per execution and never escapes the thread.

The one remaining write to state shared between threads is
MavenSession.getProjectBuildingRequest(), which lazily creates and then
mutates the single ProjectBuildingRequest owned by the
MavenExecutionRequest. That happens inside Maven core, every thread
writes the same repository session, and the result is immediately copied
into a new DefaultProjectBuildingRequest before use.

Also add the missing @OverRide on execute().

Signed-off-by: Radoslav Husar <rhusar@ibm.com>
@rhusar

rhusar commented Sep 13, 2026

Copy link
Copy Markdown
Member Author

Looks good, may I just ask you to create an issue for this change at https://github.com/wildfly/wildfly-bom-builder-plugin/issues ?

Done #95 and linked. 👍🏼

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.

2 participants