Skip to content

Latest commit

 

History

History
395 lines (284 loc) · 13.2 KB

File metadata and controls

395 lines (284 loc) · 13.2 KB

Contributing to xAPI Java

Thank you for your interest in contributing to xAPI Java! This document provides guidelines and instructions for contributing to this project.

Table of Contents

Code of Conduct

This project adheres to a Code of Conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to [email protected].

Getting Started

Prerequisites

xAPI Java requires Java 25 or newer.

Installing Java 25

We recommend using SDKMAN! to install and manage Java versions:

# Install SDKMAN (if not already installed)
curl -s "https://get.sdkman.io" | bash

# Install Java 25 (Temurin distribution recommended)
sdk install java 25.0.1-tem

# Verify installation
java -version

Note: The exact identifier (e.g., 25.0.1-tem) may vary by platform and availability. Run sdk list java to see available Java 25 versions for your system and choose the appropriate one for your platform.

Setting Up Your Development Environment

  1. Fork the repository on GitHub

  2. Clone your fork locally:

    git clone https://github.com/YOUR_USERNAME/xapi-java.git
    cd xapi-java
  3. Add the upstream repository as a remote:

    git remote add upstream https://github.com/BerryCloud/xapi-java.git
  4. Verify your setup:

    ./mvnw clean verify

Development Workflow

Building the Project

xAPI Java uses Maven with the Maven Wrapper (./mvnw). The following build commands are available:

# Clean build with tests
./mvnw clean verify

# Build without tests (faster, for quick checks)
./mvnw clean verify -DskipTests

# Run tests only
./mvnw test

# Run integration tests
./mvnw verify

Best Practice: Always run the full build (./mvnw clean verify) before starting work to ensure you understand the current state of the project.

Running Tests

xAPI Java has over 300 unit tests ensuring conformance with the xAPI specification. Tests use:

  • JUnit 5 (Jupiter) for test framework
  • Hamcrest matchers for assertions
  • MockWebServer (OkHttp) for testing HTTP interactions in xapi-client

To run tests:

# Run all tests
./mvnw test

# Run tests for a specific module
./mvnw test -pl xapi-model

# Run a specific test class
./mvnw test -Dtest=StatementTest

Code Style and Formatting

xAPI Java strictly follows the Google Java Style Guide.

Automated Formatting

The project uses the Spotify fmt-maven-plugin to automatically format Java code according to the Google Java Style Guide.

Recommended: Install Git Hooks

To automatically format your code before each commit, install the pre-commit hook:

./install-git-hooks.sh

This ensures your code is always formatted correctly before committing. The hook runs ./mvnw com.spotify.fmt:fmt-maven-plugin:format automatically.

Manual Formatting

If you prefer not to use the git hook, you can manually format your code at any time:

# Format all Java files in the project
./mvnw com.spotify.fmt:fmt-maven-plugin:format

Important: Run the formatter before committing your changes to avoid formatting issues in pull requests.

Automated Enforcement

  • CheckStyle is configured to enforce the Google Java Style Guide automatically during the build
  • CheckStyle validation runs as part of ./mvnw verify
  • All CheckStyle violations must be resolved before submitting a pull request

Code Quality Tools

The project uses several automated code quality tools:

  • SonarCloud: Performs automatic pull request reviews and tracks code quality metrics
  • CodeQL: Scans for security vulnerabilities
  • JaCoCo: Measures code coverage (viewable in SonarCloud)

These tools run automatically on pull requests via GitHub Actions.

Key Style Points

  • Use Lombok annotations to reduce boilerplate (@Builder, @Value, @Getter, etc.)
  • All model classes are immutable with fluent interface patterns
  • Use Jakarta Bean Validation annotations for validation (@NotNull, custom validators)
  • Follow existing code patterns and conventions in the module you're modifying

Making Changes

Creating a Branch

Create a feature branch from the latest main:

git checkout main
git pull upstream main
git checkout -b feature/your-feature-name

Use descriptive branch names:

  • feature/add-something for new features
  • fix/issue-number-description for bug fixes
  • docs/update-readme for documentation changes
  • chore/update-dependencies for maintenance tasks

Writing Code

Follow the Fluent Interface Pattern

All xAPI model objects are immutable and use a fluent interface pattern:

Statement statement = Statement.builder()
    .agentActor(a -> a.name("A N Other").mbox("mailto:[email protected]"))
    .verb(Verb.ATTEMPTED)
    .activityObject(o -> o.id("https://example.com/activity/simplestatement")
        .definition(d -> d.addName(Locale.ENGLISH, "Simple Statement")))
    .build();

To create modified versions of immutable objects, use toBuilder():

Statement completedStatement = attemptedStatement.toBuilder()
    .verb(Verb.COMPLETED)
    .build();

Validation

  • Use Jakarta Bean Validation annotations for model validation
  • Custom validators are in dev.learning.xapi.model.validation.constraints
  • Ensure validation conforms to the xAPI specification

Jackson Serialization

Custom Jackson modules ensure strict xAPI compliance:

  • XapiStrictLocaleModule: Validates locale formats
  • XapiStrictNullValuesModule: Handles null value validation
  • XapiStrictObjectTypeModule: Validates objectType fields
  • XapiStrictTimestampModule: Validates timestamp formats

Writing Tests

All new functionality must include tests.

Test Structure

@Test
@DisplayName("When Statement Has All Properties Then Serialization Works")
void testStatementSerialization() throws JsonProcessingException {
    Statement statement = Statement.builder()
        .agentActor(a -> a.name("Test User").mbox("mailto:[email protected]"))
        .verb(Verb.COMPLETED)
        .activityObject(o -> o.id("https://example.com/activity/1"))
        .build();

    String json = objectMapper.writeValueAsString(statement);

    assertThat(json, hasJsonPath("$.actor.name", is("Test User")));
    assertThat(json, hasJsonPath("$.verb.id"));
}

Test Guidelines

  • Use JUnit 5 annotations (@Test, @DisplayName)
  • Use Hamcrest matchers for assertions (assertThat, is, notNullValue)
  • Use JSON path matchers for verifying serialization (hasJsonPath, hasNoJsonPath)
  • Ensure tests verify xAPI specification compliance
  • Follow existing test patterns in the module

Documentation

JavaDoc Guidelines

All public APIs must be documented with comprehensive JavaDoc comments:

  • Classes and interfaces: Include a brief description and link to relevant xAPI specification sections
  • Public methods: Document purpose, parameters (@param), return values (@return), and exceptions (@throws)
  • Validation annotations: Include @return tags for message(), groups(), and payload() methods
  • Constructor parameters: Document all constructor parameters with @param tags

Important: Lombok-generated code (builders, constructors) may produce unavoidable javadoc warnings. These are suppressed via Maven configuration and do not need manual documentation.

Example:

/**
 * Gets a Statement from the LRS.
 * <p>
 * The returned ResponseEntity contains the response headers and the Statement.
 * </p>
 *
 * @param request the get statement request
 *
 * @return the ResponseEntity
 *
 * @see <a href="https://github.com/adlnet/xAPI-Spec/blob/master/xAPI-Communication.md#213-get-statements">xAPI GET Statements</a>
 */
public Mono<ResponseEntity<Statement>> getStatement(GetStatementRequest request) {
  // implementation
}

Generating JavaDoc: Run ./mvnw javadoc:javadoc to verify documentation quality.

  • README: Update if your changes affect usage examples or getting started instructions
  • Code Comments: Add comments only when necessary to explain complex logic (match existing style)
  • Maintain copyright headers in all source files: Copyright 2016-2025 Berry Cloud Ltd. All rights reserved.

Submitting Changes

Pull Request Process

  1. Ensure all tests pass locally:

    ./mvnw clean verify
  2. Commit your changes with clear, descriptive commit messages:

    git commit -m "Add feature: brief description of change"
  3. Push to your fork:

    git push origin feature/your-feature-name
  4. Create a pull request on GitHub from your fork to the main branch of BerryCloud/xapi-java

  5. Fill out the pull request template completely, including:

    • Summary of changes
    • Issue number being resolved
    • Checklist confirmation

Pull Request Checklist

Before submitting your pull request, verify:

  • Code has been formatted using ./mvnw com.spotify.fmt:fmt-maven-plugin:format (or use the git hook)
  • Public methods are documented with JavaDoc
  • Public methods are tested with unit tests
  • New and existing tests pass when run locally (./mvnw clean verify)
  • There are no CheckStyle warnings or errors
  • Code follows the Google Java Style Guide
  • Changes maintain backward compatibility (unless discussed with maintainers)
  • Commit messages are clear and descriptive
  • Pull request description references the related issue

Note: Pull requests cannot be merged unless all status checks pass (tests, CheckStyle, SonarCloud, CodeQL).

Code Review Process

  1. Automated Checks: GitHub Actions will automatically run:

    • Build and tests
    • CheckStyle validation
    • SonarCloud analysis
    • CodeQL security scanning
  2. Maintainer Review: A project maintainer will review your code for:

    • Correctness and quality
    • Adherence to project conventions
    • Test coverage
    • Documentation completeness
  3. Feedback and Iteration:

    • Address any requested changes
    • Push updates to your branch (the PR will update automatically)
    • Discuss any questions or concerns in the PR comments
  4. Approval and Merge: Once approved and all checks pass, a maintainer will merge your PR

Project Structure

xAPI Java is a monorepo containing multiple Maven modules:

  • xapi-model/: Core xAPI data models (Statement, Actor, Verb, Activity, etc.)

    • All classes are immutable with builder pattern
    • Extensive validation annotations
    • Custom validators for xAPI-specific rules
  • xapi-client/: Spring WebClient-based reactive client for LRS communication

    • Implements Statement, State, Agent Profile, and Activity Profile resources
    • Fluent request builders
    • Auto-configuration via Spring Boot
  • xapi-model-spring-boot-starter/: Spring Boot autoconfiguration

    • Configurable validation rules
    • Properties prefix: xapi.model.
  • samples/: Example applications demonstrating xAPI client usage

    • Useful as reference for common patterns

Additional Resources


Questions or need help? Feel free to:

  • Open an issue for bugs or feature requests
  • Ask questions in pull request comments
  • Reach out to the maintainers listed in pom.xml

Thank you for contributing to xAPI Java! 🎉