Thank you for your interest in contributing to platform-java! We welcome contributions from the community.
- Code of Conduct
- How to Contribute
- Reporting Bugs
- Suggesting Features
- Pull Request Process
- Development Setup
- Code Style
- Testing Requirements
- Commit Message Guidelines
- License
This project adheres to a Code of Conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to the project maintainers.
There are many ways to contribute to platform-java:
- Report bugs - Help us identify and fix issues
- Suggest features - Share ideas for improvements
- Write code - Submit pull requests with bug fixes or new features
- Improve documentation - Help make our docs clearer and more comprehensive
- Review pull requests - Provide feedback on open PRs
- Answer questions - Help other users in discussions and issues
Before creating a bug report, please check the existing issues to avoid duplicates.
When filing a bug report, please include:
- Clear title - Brief description of the problem
- Description - Detailed explanation of the issue
- Steps to reproduce - Numbered steps to recreate the bug
- Expected behavior - What you expected to happen
- Actual behavior - What actually happened
- Environment - OS, Java version, platform-java version
- Logs/Screenshots - Any relevant output or error messages
Example:
**Title**: ApplicationManager throws NPE when deploying with null descriptor
**Description**: Calling `manager.deploy(null)` causes a NullPointerException instead of throwing IllegalArgumentException.
**Steps to Reproduce**:
1. Create ApplicationManager instance
2. Call `manager.deploy(null)`
3. Observe NPE
**Expected**: Should throw IllegalArgumentException with message "descriptor cannot be null"
**Actual**: Throws NPE at line 123 of ApplicationManager.java
**Environment**:
- OS: Ubuntu 22.04
- Java: OpenJDK 21.0.1
- platform-java: 1.1
**Logs**:java.lang.NullPointerException at org.flossware.platform.core.ApplicationManager.deploy(ApplicationManager.java:123)
Feature requests are welcome! Before creating a feature request:
- Check existing issues for similar requests
- Consider if it fits the project's scope and goals
- Think about backwards compatibility
When suggesting a feature, please include:
- Use case - Why is this feature needed?
- Proposed solution - How should it work?
- Alternatives - What other approaches did you consider?
- Examples - Code examples or mockups if applicable
# Fork the repository on GitHub, then:
git clone https://github.com/YOUR-USERNAME/platform-java.git
cd platform-java
git remote add upstream https://github.com/FlossWare/platform-java.gitUse a descriptive branch name:
git checkout -b fix/issue-123-npe-in-deploy
# or
git checkout -b feature/add-jwt-authenticationBranch naming convention:
fix/issue-XXX-description- Bug fixesfeature/description- New featuresdocs/description- Documentation changesrefactor/description- Code refactoring
- Write clean, readable code
- Follow the code style guidelines
- Add tests for new functionality
- Update documentation as needed
- Keep commits focused and atomic
# Run all tests
mvn clean verify
# Check code coverage (should be ≥93%)
mvn clean test jacoco:report
open target/site/jacoco/index.html
# Run quality checks
mvn checkstyle:check pmd:check spotbugs:checkAll quality gates must pass before submitting a PR.
Follow the commit message guidelines:
git add .
git commit -m "fix: resolve NPE when deploying null descriptor (#123)"git push origin fix/issue-123-npe-in-deployThen create a Pull Request on GitHub with:
- Clear title - Summarize the change
- Description - Explain what and why
- Issue reference - Link to related issue(s)
- Testing - Describe how you tested
- Screenshots - For UI changes
PR Template:
## Description
Fixes #123 - ApplicationManager now validates descriptor parameter and throws IllegalArgumentException instead of NPE.
## Changes
- Added null check in `ApplicationManager.deploy()`
- Added unit test for null descriptor
- Updated JavaDoc
## Testing
- Added `ApplicationManagerTest.testDeployNullDescriptor()`
- All existing tests pass
- Coverage: 94% (increased from 93%)
## Checklist
- [x] Tests added/updated
- [x] Documentation updated
- [x] Code follows style guidelines
- [x] All quality checks pass- Address all review comments
- Push additional commits to the same branch
- Request re-review when ready
Maintainers will squash commits when merging. Your PR title becomes the commit message, so make it clear and descriptive.
- Java 21+ - OpenJDK or Oracle JDK
- Maven 3.9+ - Build tool
- Git - Version control
# Clone the repository
git clone https://github.com/FlossWare/platform-java.git
cd platform-java
# Build all modules
mvn clean install
# Build specific module
cd platform-core
mvn clean install
# Skip tests (faster, but not recommended)
mvn clean install -DskipTests
# Run with all quality checks
mvn clean verify# Basic launcher
java -jar platform-launcher/target/platform-launcher-1.1.jar
# With REST API
java -jar platform-launcher/target/platform-launcher-1.1.jar --rest-api
# With all features
java -jar platform-launcher/target/platform-launcher-1.1.jar \
--rest-api --web-console --jmx-port 9999 --prometheus- Open project:
File → Open → Select platform-java directory - Import as Maven project
- Enable annotation processing:
Settings → Build → Compiler → Annotation Processors - Install Checkstyle plugin:
Settings → Plugins → Checkstyle-IDEA - Configure Checkstyle:
Settings → Tools → Checkstyle → Configuration File → checkstyle.xml
File → Import → Maven → Existing Maven Projects- Select
platform-javadirectory - Install Checkstyle plugin from Marketplace
- Configure:
Window → Preferences → Checkstyle → New → checkstyle.xml
- Install extensions:
- Language Support for Java
- Maven for Java
- Checkstyle for Java
- Open folder:
File → Open Folder → platform-java
We follow Google Java Style enforced by Spotless and Checkstyle:
Code is automatically formatted using Spotless with Google Java Format:
# Auto-format all code before committing
mvn spotless:apply
# Check formatting without changing files
mvn spotless:checkKey Formatting Rules:
- Indentation: 2 spaces (not tabs) - enforced by Google Java Format
- Line length: 120 characters max
- Braces: K&R style (opening brace on same line)
// Good (Google Java Style - 2 space indent)
public void myMethod() {
if (condition) {
doSomething();
}
}
// Bad - wrong indentation
public void myMethod() {
if (condition) {
doSomething();
}
}
// Bad - wrong brace style
public void myMethod()
{
if (condition)
{
doSomething();
}
}- Classes:
PascalCase(e.g.,ApplicationManager) - Methods:
camelCase(e.g.,deployApplication()) - Constants:
UPPER_SNAKE_CASE(e.g.,MAX_RETRY_COUNT) - Packages: lowercase, no underscores (e.g.,
org.flossware.platform.core)
- One class per file
- Package-private by default, public only when necessary
- Final by default for local variables and parameters
- Static imports only for constants and utility methods
- JavaDoc for all public classes and methods
- No commented-out code (use git history instead)
- Explain WHY, not WHAT - code should be self-documenting
// Good - explains why
// Retry 3 times because network may be temporarily unavailable
private static final int MAX_RETRY_COUNT = 3;
// Bad - restates the obvious
// Maximum retry count is 3
private static final int MAX_RETRY_COUNT = 3;- Don't catch generic Exception - catch specific types
- Don't swallow exceptions - log or rethrow
- Use meaningful error messages
// Good
try {
deployApplication(descriptor);
} catch (ClassNotFoundException e) {
throw new DeploymentException("Main class not found: " + descriptor.getMainClass(), e);
}
// Bad
try {
deployApplication(descriptor);
} catch (Exception e) {
// ignore
}- Use SLF4J, not System.out
- Appropriate log levels: DEBUG, INFO, WARN, ERROR
- Parameterized messages for better performance
// Good
logger.info("Deploying application: {}", appId);
// Bad
System.out.println("Deploying application: " + appId);Spotless automatically formats code to Google Java Style:
# Format all code (run before committing)
mvn spotless:apply
# Check if code is formatted correctly
mvn spotless:check
# Runs automatically during verify phase
mvn clean verifyWhat Spotless Does:
- Applies Google Java Format
- Removes unused imports
- Trims trailing whitespace
- Ensures file ends with newline
All code must pass Checkstyle validation:
# Check code style
mvn checkstyle:check
# Runs automatically during validate phase
mvn clean verifyConfiguration: checkstyle.xml (based on Google Java Style with FlossWare conventions)
Key Rules:
- No wildcard imports (
import java.util.*) - Missing
@Overrideannotations detected - Method length limit: 150 lines
- Parameter count limit: 7
- Nested block depth limits
- Javadoc required for public APIs
Common violations to avoid:
- Wildcard imports (
import java.util.*;) - Missing
@Overrideannotations - Incorrect indentation
- Line too long (>120 chars)
- Missing JavaDoc on public methods
- Minimum coverage: 93% instruction coverage (enforced by JaCoCo)
- New code requirement: 80%+ coverage for all new code
- All new code must have tests
- Tests must be meaningful, not just coverage boosters
Follow the Arrange-Act-Assert pattern:
@Test
void shouldDeployApplicationSuccessfully() {
// Arrange
ApplicationManager manager = new ApplicationManager();
ApplicationDescriptor descriptor = createTestDescriptor();
// Act
manager.deploy(descriptor);
// Assert
assertEquals(ApplicationState.DEPLOYED,
manager.getApplicationContext("test-app").getState());
}All tests must be tagged as either unit or integration tests:
// Unit tests - fast, isolated, no external dependencies
@Test
@Tag("unit")
void shouldValidateDescriptorFields() { ... }
// Integration tests - involve multiple components or external systems
@Test
@Tag("integration")
void shouldDeployToRemoteRegistry() { ... }Run specific test categories:
# Run only unit tests
mvn test -Dgroups="unit"
# Run only integration tests
mvn test -Dgroups="integration"
# Run all tests
mvn testUse descriptive names following should<ExpectedBehavior>When<StateUnderTest> pattern:
@Test
@Tag("unit")
void shouldThrowExceptionWhenDescriptorIsNull() { ... }
@Test
@Tag("unit")
void shouldStartApplicationWhenInDeployedState() { ... }
@Test
@Tag("integration")
void shouldRejectDuplicateApplicationId() { ... }- One test class per production class
- Group related tests with
@Nestedclasses - Use
@BeforeEachfor common setup
class ApplicationManagerTest {
private ApplicationManager manager;
@BeforeEach
void setUp() {
manager = new ApplicationManager();
}
@Nested
class DeploymentTests {
@Test
@Tag("unit")
void shouldDeployApplication() { ... }
@Test
@Tag("unit")
void shouldRejectDuplicateId() { ... }
}
@Nested
class LifecycleTests {
@Test
@Tag("integration")
void shouldStartDeployedApplication() { ... }
}
}Use Mockito for mocking dependencies:
@ExtendWith(MockitoExtension.class)
class ApplicationManagerTest {
@Mock
private ClassLoaderFactory classLoaderFactory;
@InjectMocks
private ApplicationManager manager;
@Test
void shouldCreateIsolatedClassLoader() {
when(classLoaderFactory.createClassLoader(any()))
.thenReturn(mock(ClassLoader.class));
manager.deploy(descriptor);
verify(classLoaderFactory).createClassLoader(any());
}
}# Run all tests
mvn test
# Run specific test class
mvn test -Dtest=ApplicationManagerTest
# Run specific test method
mvn test -Dtest=ApplicationManagerTest#shouldDeployApplication
# Run tests with coverage
mvn clean test jacoco:report
# Skip tests (not recommended)
mvn install -DskipTestsWe follow the Conventional Commits specification.
<type>(<scope>): <subject>
<body>
<footer>
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style (formatting, no logic change)refactor: Code refactoringtest: Adding or updating testschore: Maintenance tasks (build, dependencies)perf: Performance improvements
The module or component affected: core, api, security, monitoring, etc.
feat(api): add JWT authentication support
Implements JWT-based authentication for REST API endpoints.
- Add JwtAuthFilter for token validation
- Add JwtConfig for configuration
- Update REST API documentation
Closes #311
fix(core): resolve NPE in ApplicationManager.deploy()
Add null check for descriptor parameter and throw
IllegalArgumentException with descriptive message.
Fixes #123
docs(readme): update quick start guide
Add Docker deployment instructions and update
REST API examples.
When pair programming or collaborating:
feat(security): implement role-based access control
Co-authored-by: Jane Doe <jane@example.com>
By contributing to platform-java, you agree that your contributions will be licensed under the GNU General Public License v3.0.
All contributed code must:
- Include appropriate copyright headers
- Be your original work or properly attributed
- Not violate any third-party licenses
- Documentation: See README.md and docs/
- Issues: Browse existing issues
- Discussions: Ask questions in GitHub Discussions
Thank you for contributing to platform-java! 🎉