open-feature / open-feature/java-sdk
Split OpenFeature Java SDK into API and Implementation Artifacts
- Dominant language
- Java
- Stars
- 128
- Forks
- 61
- Avg merge
- 5h 57m
- Merged PRs (30d)
- 26
Description
## Problem Statement
Currently, the OpenFeature Java SDK provides a single artifact that includes both the API interfaces and the implementation. This creates challenges as we expand the ecosystem:
1. **Gherkin Test Steps Dependencies**: The upcoming Gherkin test steps implementation needs to reference the OpenFeature API but shouldn't depend on a specific implementation
2. **java-sdk-contrib Integration**: Contributors working on `java-sdk-contrib` need access to the API without pulling in unnecessary implementation dependencies
3. **Release Coupling**: API changes (which should be infrequent and stable) are coupled with implementation changes (which may be more frequent)
4. **Dependency Bloat**: Consumers who only need the API surface (like test frameworks or alternative implementations) currently must pull in the full SDK
## Proposed Solution
Split the current single artifact into two separate artifacts:
### 1. `openfeature-api` (New)
- Contains only interfaces, annotations, and core data types
- Defines the stable API contract
- Minimal dependencies
- Follows strict semantic versioning
- Infrequent releases (only when API changes)
### 2. `openfeature-sdk` (Refactored)
- Contains the current implementation
- Depends on `openfeature-api`
- More frequent releases for implementation improvements
- Backward compatible implementation changes don't require API updates
### 3. `openfeature-test-harness` (Future)
- Contains Gherkin test steps
- Depends only on `openfeature-api`
- Can be used by any OpenFeature implementation
- Implementation-agnostic testing utilities
## Benefits
1. **Cleaner Dependencies**: Test frameworks and alternative implementations only pull what they need
2. **Independent Release Cycles**: API stability doesn't block implementation improvements
3. **Better SemVer Compliance**: Clear separation of API breaking changes vs implementation changes
4. **Ecosystem Growth**: Easier for `java-sdk-contrib` and other implementations to integrate
5. **Provider Implementation Flexibility**: Feature flag providers (LaunchDarkly, Flagsmith, Split, etc.) can bind to the stable API instead of the full SDK, enabling:
- Multiple provider versions compatible with the same API version
- Users can mix and match provider versions independently from SDK versions
- Providers don't need to release new versions for every SDK implementation change
- Reduced version conflicts in user applications with multiple providers
6. **Reduced Coupling**: Following established patterns from SLF4J, JAX-RS, etc.
### Provider Implementation Benefits
This split is particularly valuable for the OpenFeature provider ecosystem:
**Current State:**
```xml
dev.openfeature
sdk
1.5.0
```
**After API Split:**
```xml
dev.openfeature
openfeature-api
1.2.0
```
**Real-world scenario:**
- LaunchDarkly provider v2.1.0 targets API v1.2.0
- Flagsmith provider v1.8.0 also targets API v1.2.0
- User can use both providers with SDK v2.5.0 (which implements API v1.2.0)
- No version conflicts, no forced provider upgrades when SDK implementation improves
This mirrors successful patterns like:
- JDBC drivers targeting JDBC API versions
- SLF4J logging implementations targeting SLF4J API
- JAX-RS providers targeting JAX-RS API
### Phase 1: Repository Structure Decision
**Decision needed**: Separate repositories vs monorepo with manifest
#### Option A: Separate Repositories (Recommended)
```
openfeature-java-api/ (API only)
openfeature-java-sdk/ (Implementation)
openfeature-java-test-harness/ (Future - Gherkin steps)
```
**Pros with release-please:**
- Clean release lifecycle per artifact
- Independent conventional commit history
- Focused issues/PRs per component
- Simpler CI/CD pipelines
#### Option B: Monorepo with Release-Please Manifest
```
/api/ (API artifact)
/sdk/ (SDK artifact)
/test-harness/ (Future - Test artifact)
/pom.xml (Parent aggregator)
```
### Phase 2: API Extraction
1. **Create `openfeature-api` module/repo**
- Move all interfaces (`FeatureProvider`, `Client`, `EvaluationContext`, etc.)
- Move core data types (`FlagEvaluationDetails`, `ProviderMetadata`, etc.)
- Move annotations and exceptions
- Create minimal `pom.xml` with only essential dependencies
2. **Update `openfeature-sdk` module/repo**
- Add dependency on `openfeature-api`
- Remove duplicated interfaces/types
- Keep all implementation classes
- Update imports to reference API artifact
3. **Version Strategy**
- Start API at `1.0.0` (stable baseline)
- SDK continues current versioning or resets to align with API major version
- Use version ranges: `[1.0.0,2.0.0)`
### Phase 3: Release-Please Configuration
#### For Separate Repositories:
Each repo gets standard release-please setup:
```yaml
# .github/workflows/release-please.yml
- uses: google-github-actions/release-please-action@v3
with:
release-type: maven
package-name: openfeature-api # or openfeature-sdk
token: ${{ secrets.GITHUB_TOKEN }}
```
#### For Monorepo:
```json
// .release-please-manifest.json
{
"api": "1.0.0",
"sdk": "2.0.0"
}
```
### Phase 4: Documentation & Communication
1. **Update README.md** with new artifact structure
2. **Create migration guide** for existing users
3. **Document version compatibility matrix**:
| SDK Version | Compatible API Versions | Notes |
|-------------|-------------------------|-------|
| 2.x.x | 1.x.x | Current |
4. **Update build badges** and Maven Central links
### Phase 5: Testing & Validation
1. **Compatibility testing** between API and SDK versions
2. **Integration testing** with existing OpenFeature providers
3. **Validate Gherkin steps** work with API-only dependency
4. **Test java-sdk-contrib integration**
## Migration Path for Users
### Current Usage:
```xml
dev.openfeature
sdk
1.x.x
```
### After Split:
```xml
dev.openfeature
openfeature-sdk
2.x.x
dev.openfeature
openfeature-api
1.x.x
```
## Risks & Mitigations
1. **Increased Complexity**: Multiple artifacts to maintain
- *Mitigation*: Clear documentation and automated testing
2. **Version Alignment Challenges**: API/SDK compatibility matrix
- *Mitigation*: Automated compatibility testing in CI
3. **User Confusion**: Which artifact to use?
- *Mitigation*: Clear documentation with usage examples
4. **Release Coordination**: Breaking changes spanning API + SDK
- *Mitigation*: Careful planning of breaking changes, deprecation periods
## Success Criteria
1. ✅ Gherkin test steps can depend only on `openfeature-api`
2. ✅ `java-sdk-contrib` implementations work with API-only dependency
3. ✅ Existing users can migrate with minimal changes
4. ✅ Independent release cycles for API vs implementation
5. ✅ Clear version compatibility documentation
## Next Steps
1. **Decision**: Choose repository structure (separate repos vs monorepo)
2. **Create implementation plan** with detailed timeline
3. **Set up new repositories/modules**
4. **Begin API extraction** following the implementation plan
5. **Update CI/CD pipelines** for new artifact structure
Contributor guide
Assessment
This issue has not been assessed yet.