How we used Maven relocation for Xtend

In Xtext release 2.40.0, we adopted Maven relocation to move Xtend Maven artifacts’ groupIds from org.eclipse.xtend to org.eclipse.xtext without breaking existing consumers.

References:

Rationale

Xtend’s Maven coordinates were relocated to comply with Maven Central’s new publishing requirements after the OSSRH sunset.

The new Maven Central publishing portal enforces namespace consistency: all artifacts in a single deployment must share the same groupId prefix (namespace). We were getting this error when trying to deploy:

Xtend Maven artifacts historically had groupId org.eclipse.xtend, while all other Xtext Maven artifacts use org.eclipse.xtext. This mismatch prevented us from publishing both in a single deployment to Maven Central.

See the detailed rationale in issue #3398 and specifically this comment.

Why relocation instead of just renaming

  • Backwards compatibility: Existing builds continue to resolve, emitting a clear warning rather than failing.
  • Gradual migration: Library and plugin maintainers can update on their own schedule.
  • Single source of truth: Only the new artifact publishes real content; the old coordinate becomes a lightweight stub POM.
  • Clear deprecation signal: A relocation message is more explicit than a silent artifact disappearance.
  • No breaking changes: Consumers don’t need to update immediately; their builds keep working.

Maven relocation basics (summary)

Maven relocation allows you to redirect artifact coordinates without breaking existing consumers.

The process involves:

  1. Real artifacts with the new groupId that contain actual JARs, source, and javadoc
  2. Relocation artifacts with the old groupId that are minimal POMs pointing to the new coordinates

A relocation artifact is a simple POM project with this structure:

At resolution time, Maven automatically replaces the old coordinates with the new ones and displays a warning to the user.

Our goals

  1. Preserve build stability for all existing Xtend consumers
  2. Minimize maintenance by publishing only one real artifact per logical module
  3. Provide a clear migration path with visible warnings
  4. Avoid transitive duplication (both old + new coordinates ending up on classpath)
  5. Comply with Maven Central’s namespace requirements

Implementation outline

Our implementation involved several steps (see PR #3461 for details):

Identify artifacts to relocate: All Xtend artifacts published to Maven Central under org.eclipse.xtend: org.eclipse.xtend.lib, org.eclipse.xtend.lib.gwt,org.eclipse.xtend.lib.macro, etc.

Create relocation parent POM: Created org.eclipse.xtend.relocated.parent to organize all relocation artifacts.

For each artifact, create a relocation POM module with:
– Packaging: pom
– Old groupId: org.eclipse.xtend
– Same artifactId and version as the original
– Relocation block pointing to org.eclipse.xtext

Separate publishing workflow: Since Maven Central requires same-namespace deployments, we had to:
– Build relocation artifacts separately
– Archive deployment bundles for manual upload
– Publish relocation artifacts in a separate step from main artifacts

Update CI/CD scripts: Modified Jenkins deployment scripts to handle both artifact sets.

Example relocation POM

Here’s a real example from our implementation:

When a consumer uses the old coordinates, Maven shows:

Ensuring no duplicate classes

Because the relocation artifact is only a stub POM with no JAR attached, the classpath will contain only the new artifact. This prevents:

  • Duplicate classes on the classpath
  • Class shadowing issues
  • Version conflicts between old and new coordinates

Maven and Gradle both handle this correctly by fetching only the relocated target.

Publishing workflow

The key challenge was Maven Central’s namespace requirement. Our solution:

  1. Main build: Publishes all org.eclipse.xtext artifacts (including the real Xtend artifacts with new groupId)
  2. Separate relocation build: Publishes all org.eclipse.xtend relocation POMs
  3. Validation: We performed dry-run deployments to verify Maven Central would accept the artifacts
  4. Manual upload: For milestone releases, we archived bundles and manually uploaded them to Maven Central

As noted in the PR discussion, we had to update version-bumping scripts to include the new relocation parent directory.

Migration guidance for consumers

Search your builds for the old groupId:
– Maven: mvn dependency:tree | grep org.eclipse.xtend
– Gradle: ./gradlew dependencies --configuration compileClasspath | grep org.eclipse.xtend

Replace org.eclipse.xtend with org.eclipse.xtext in your POMs or build.gradle files:

Run your build and verify the relocation warning disappears

Update any BOM or dependencyManagement entries

Tooling considerations

  • IDEs: Eclipse, IntelliJ IDEA, and other IDEs honor Maven relocation. Refresh your project after migration.
  • Gradle: Fully supports Maven relocation when resolving from Maven repositories.
  • Reproducibility: The relocation POMs are stable and don’t affect build reproducibility.
  • CI/CD: No changes needed; relocation works transparently in CI environments.

Lessons learned

  1. Maven Central namespace enforcement is strict: You cannot publish artifacts with different groupId namespaces in a single deployment, even if they’re in the same monorepo.

  2. Relocation is low-effort and highly effective: Once set up, relocation artifacts are trivial to maintain across versions.

  3. Separate publishing is required: Relocation artifacts must be published in a completely separate Maven deployment due to namespace restrictions.

  4. Testing is crucial: We performed dry-run deployments first to ensure Maven Central would validate the artifacts correctly.

  5. Scripts need updates: Don’t forget to update version-bumping and release automation scripts to include relocation modules.

  6. Communication is important: Clear documentation and release notes help consumers understand and adopt the changes smoothly.

  7. It works across ecosystems: Both Maven and Gradle consumers benefit from relocation automatically, as do IDE integrations.

FAQ

Q: Do I need to change anything immediately?
A: No; builds continue to work with the old coordinates, but you’ll see warnings. Update when convenient to eliminate warnings.

Q: Does relocation affect checksums or reproducible builds?
A: No; the new artifact is authoritative. The stub POM exists only for resolution redirection and contains no actual code.

Q: Can Gradle consumers rely on this?
A: Yes; Gradle honors Maven relocation information when resolving from Maven repositories.

Q: What about IDEs?
A: IDEs (tested with Eclipse and IntelliJ) honor Maven relocation when resolving from Maven repositories. You may need to refresh your project after migration.

Q: What if I use dependencyManagement or BOM entries?
A: Update them to reference the new groupId. Transitive relocation continues working in the meantime.

Q: Will this affect my transitive dependencies?
A: No; if your direct dependencies haven’t migrated yet, their use of old coordinates will be automatically relocated, and you’ll see warnings for those too.

Q: What happens if I have both old and new coordinates in my dependency tree?
A: Maven/Gradle will resolve both to the same artifact (the new one), so you won’t have duplicates on the classpath.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.