JNexus uses semantic versioning (X.Y.Z) with strict API compatibility guarantees for the jnexus-core module, which is consumed by Android and other platforms.
Current Version: 2.0.0
Breaking changes that require code updates:
- Interface signature changes - Method parameters, return types
- Removed deprecated features - Features deprecated for 2+ minor versions
- Minimum version bumps - Java, Android SDK, Kotlin requirements
- Behavioral changes - Changes to core functionality semantics
Example: 1.x → 2.0.0
- Added
forceRefreshparameter tolistComponents() - Removed deprecated
clearCache(repository)overload - Minimum Android SDK: 26 → 28
Migration Guide: Provided in CHANGELOG.md with code examples
Backward-compatible new features:
- New methods - Additional methods on existing interfaces
- New interfaces - New optional APIs
- Performance improvements - No API changes
- New platforms - iOS, macOS support
- Default methods - Added to interfaces (Java 8+)
Example: 2.0.0 → 2.1.0
- Added
listComponentsWithMetadata()method - Added
ComponentMetadatarecord - Added
SearchCriteriabuilder
Compatibility: Code written for 2.0.0 works with 2.1.0 without changes
Bug fixes and non-breaking improvements:
- Bug fixes - Corrected behavior
- Documentation updates - Javadoc, README
- Security patches - Vulnerability fixes
- Performance fixes - No API changes
- Internal refactoring - No public API impact
Example: 2.0.0 → 2.0.1
- Fixed cache expiration calculation
- Updated Javadoc for
deleteComponent() - Security: Upgraded Jackson version
Compatibility: Drop-in replacement
Stable APIs are guaranteed backward compatible within major version:
/**
* HTTP client interface for Nexus Repository Manager.
*
* @since 2.0.0
* @apiNote Stable - safe for production use
*/
public interface NexusHttpClient {
List<RepoRecord> listComponents(String repository, boolean forceRefresh)
throws IOException, InterruptedException;
}Guarantees:
- Method signatures won't change in minor/patch versions
- Existing methods won't be removed until next major version
- Behavior changes documented in CHANGELOG.md
- 2+ minor version deprecation notice before removal
Current Stable APIs:
org.flossware.jnexus.NexusHttpClientorg.flossware.jnexus.Credentialsorg.flossware.jnexus.RepoRecordorg.flossware.jnexus.ComponentMetadataorg.flossware.jnexus.SearchCriteriaorg.flossware.jnexus.RepositoryStats
Experimental APIs may change in minor versions:
/**
* Advanced search with ML-powered relevance ranking.
*
* @since 2.1.0
* @apiNote Experimental - API may change without notice
*/
@Experimental
public interface MLSearchEngine {
// May change in 2.2.0, 2.3.0, etc.
}Warnings:
- Use at your own risk
- May change signature in minor versions
- May be removed in minor versions
- Not recommended for production code
Current Experimental APIs:
- None (as of 2.0.0)
Internal implementation classes are NOT part of the public API:
// org.flossware.jnexus.internal.* - NOT public API
class InternalCacheImpl {
// Can change without notice
}No Guarantees:
- May change in any version
- May be removed without deprecation
- Do not depend on these classes
JNexus uses a 3-version deprecation policy for stable APIs:
Introduce new method alongside old one:
// Version 2.1.0
// New recommended method
List<ComponentMetadata> listComponentsWithMetadata(String repository, boolean forceRefresh);
// Old method - still works
List<RepoRecord> listComponents(String repository, boolean forceRefresh);Deprecate old method with migration guidance:
// Version 2.1.0
/**
* @deprecated Use {@link #listComponentsWithMetadata(String, boolean)} instead.
* This method will be removed in version 3.0.0.
*/
@Deprecated(since = "2.1.0", forRemoval = true)
List<RepoRecord> listComponents(String repository, boolean forceRefresh);Behavior: Still fully functional, but:
- Javadoc warns of deprecation
- IDEs show strike-through
- Compiler warnings (
-Xlint:deprecation)
Add runtime deprecation warnings:
// Version 2.2.0
@Deprecated(since = "2.1.0", forRemoval = true)
public List<RepoRecord> listComponents(String repository, boolean forceRefresh) {
logger.warn("listComponents() is deprecated and will be removed in 3.0.0. "
+ "Use listComponentsWithMetadata() instead.");
// Delegate to new implementation
return listComponentsWithMetadata(repository, forceRefresh).stream()
.map(m -> new RepoRecord(m.id(), m.fileSize(), m.path()))
.toList();
}Remove deprecated method:
// Version 3.0.0
// listComponents() DELETED - use listComponentsWithMetadata()Timeline: Minimum 2 minor versions before removal
- Deprecated in 2.1.0
- Warning in 2.2.0
- Removed in 3.0.0
| Your Code | JNexus Version | Compatible? | Action Required |
|---|---|---|---|
| 1.x | 1.x | ✅ Yes | None |
| 1.x | 2.x | Check CHANGELOG for breaking changes | |
| 2.0.0 | 2.0.x | ✅ Yes | None - drop-in replacement |
| 2.0.0 | 2.1.0 | ✅ Yes | None - backward compatible |
| 2.1.0 | 2.0.0 | ❌ No | Downgrade not supported |
| 2.x | 3.x | Migration guide required |
Good: Adding optional parameters with defaults
// Version 2.0.0
void deleteComponent(String componentId);
// Version 2.1.0 - Add overload
void deleteComponent(String componentId);
void deleteComponent(String componentId, DeleteOptions options); // NEWBad: Changing existing signatures
// Version 2.0.0
void deleteComponent(String componentId);
// Version 2.1.0 - WRONG (breaking change)
void deleteComponent(String componentId, boolean dryRun); // BREAKS 2.0.0 callersGood: Adding default methods to interfaces
// Version 2.0.0
interface NexusHttpClient {
List<RepoRecord> listComponents(String repository, boolean forceRefresh);
}
// Version 2.1.0 - Add with default
interface NexusHttpClient {
List<RepoRecord> listComponents(String repository, boolean forceRefresh);
default boolean supportsMetadata() {
return false; // Safe default
}
}Good: Using builders for extensibility
SearchCriteria criteria = new SearchCriteria.Builder()
.repository("maven-releases")
.minSize(1_000_000L)
.build();
// Version 2.2.0 - Add new filter (backward compatible)
SearchCriteria criteria = new SearchCriteria.Builder()
.repository("maven-releases")
.minSize(1_000_000L)
.author("john.doe") // NEW - old code still works
.build();Good: Using records for immutable DTOs
// Version 2.0.0
public record RepoRecord(String id, long fileSize, String path) {
// Cannot be subclassed - stable contract
}Test that code written for older versions still works:
@Test
void testBackwardCompatibility_2_0_0() {
// Simulate code written for 2.0.0
NexusHttpClient client = new NexusClient(credentials);
List<RepoRecord> records = client.listComponents("repo", false);
assertNotNull(records);
assertFalse(records.isEmpty());
}Ensure deprecated methods still work:
@Test
void testDeprecatedMethodStillWorks() {
@SuppressWarnings("deprecation")
var result = client.oldMethod();
assertEquals(expected, result);
}Before making a breaking change, verify:
- Is this change absolutely necessary?
- Can it be done additively instead?
- Has the old API been deprecated for 2+ minor versions?
- Is a migration guide provided in CHANGELOG.md?
- Are code examples provided for the upgrade?
- Is the major version number incremented?
- Are all deprecation warnings removed?
| Version | Status | Support Until | Notes |
|---|---|---|---|
| 2.x | ✅ Active | Ongoing | Current stable release |
| 1.x | 2027-01-01 | Security fixes only | |
| 0.x | ❌ Unsupported | N/A | Alpha/Beta - no support |
Support Levels:
- Active: New features, bug fixes, security patches
- Maintenance: Critical bug fixes and security patches only
- Unsupported: No updates
Breaking Changes:
-
Added forceRefresh parameter
// 1.x client.listComponents("repo"); // 2.0.0 client.listComponents("repo", false); // false = use cache
-
Credentials interface changes
// 1.x Credentials creds = new Credentials(); // 2.0.0 Credentials creds = new Credentials(); // Works the same // OR with profile Credentials creds = new Credentials("dev");
Recommended Actions:
- Search for
listComponents(in your code - Add
falseas second parameter (to maintain caching behavior) - Test thoroughly before deploying
Q: Can I use 2.1.0 as a drop-in replacement for 2.0.0?
A: Yes - minor versions are backward compatible.
Q: Will my code break if I upgrade from 2.0.0 to 2.5.0?
A: No - all 2.x versions are compatible. New features are additive only.
Q: When will deprecated methods be removed?
A: After 2+ minor versions, in the next major version. Minimum 6-12 months notice.
Q: Can I depend on internal classes?
A: No - only classes in org.flossware.jnexus (top-level) are public API.
Q: How do I know which version to use?
A: Use the latest 2.x version for new projects. Check CHANGELOG.md for migration guides.
Questions about API compatibility?
- Open a GitHub Discussion
- File an Issue for compatibility bugs