Skip to content

Latest commit

 

History

History
393 lines (310 loc) · 17.1 KB

File metadata and controls

393 lines (310 loc) · 17.1 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

OpenESPI-GreenButton-Java is a monorepo implementation of the NAESB Energy Services Provider Interface (ESPI) 4.0 specification for Green Button energy data standards. The project has been migrated to Java 25, Jakarta EE 10+, and Spring Boot 4.0.

Build and Test Commands

Build All Modules

# From repository root - builds all modules (common, datacustodian, thirdparty, authserver)
mvn clean install

# Build only core modules (common, datacustodian, thirdparty) - omits authserver
mvn clean install -Pspring-boot-only

Run Tests

# Test all modules
mvn test

# Test specific module with dependencies
mvn test -pl openespi-datacustodian -am

# Test specific module only
cd openespi-common && mvn test

# Integration tests with TestContainers (requires Docker)
mvn verify -pl openespi-common -Pintegration-tests

Run Applications

# Data Custodian (default: dev-mysql profile)
cd openespi-datacustodian && mvn spring-boot:run

# With specific profile
cd openespi-datacustodian && mvn spring-boot:run -Dspring-boot.run.profiles=dev-postgresql

# Authorization Server
cd openespi-authserver && mvn spring-boot:run

# Third Party
cd openespi-thirdparty && mvn spring-boot:run

Run Single Test

# Run specific test class
mvn test -Dtest=UsagePointRepositoryTest

# Run specific test method
mvn test -Dtest=UsagePointRepositoryTest#testFindById

# Run test in specific module
mvn test -pl openespi-common -Dtest=UsagePointRepositoryTest

Architecture

Module Dependencies

The monorepo follows a layered architecture with these dependencies:

  • openespi-common → Foundation library (no dependencies on other modules)
  • openespi-datacustodian → Depends on openespi-common
  • openespi-authserver → Independent module (NO dependency on openespi-common)
  • openespi-thirdparty → Depends on openespi-common

IMPORTANT: The Authorization Server (openespi-authserver) is completely independent and does NOT depend on openespi-common. It has its own entity definitions, repositories, and services for OAuth2 authorization.

Domain Model Structure

The domain model is organized in openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/:

  • domain/common/ - Shared base entities (IdentifiedObject, LinkType, etc.)
  • domain/usage/ - ESPI energy usage entities (UsagePoint, MeterReading, IntervalBlock, ReadingType, RetailCustomer, etc.)
  • domain/customer/ - Customer entities from customer.xsd schema (CustomerAccount, CustomerAgreement, ServiceSupplier, Meter, etc.)

All ESPI domain entities extend IdentifiedObject which provides:

  • UUID primary key (id)
  • Self-reference URI (selfLink)
  • Up-reference URI (upLink)
  • XML marshalling support

Service Layer Pattern

Services follow a consistent interface-implementation pattern:

  • Interfaces: openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/
  • Implementations: openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/impl/

Services are organized by domain:

Usage Domain Services (energy data from usage.xsd):

  • UsagePointService - Energy usage point management
  • MeterReadingService - Meter reading data
  • IntervalBlockService - Time-series interval data
  • ReadingTypeService - Reading type metadata
  • UsageSummaryService - Usage aggregation summaries
  • ElectricPowerQualitySummaryService - Power quality metrics
  • TimeConfigurationService - Timezone and time parameters
  • RetailCustomerService - Retail customer management (part of usage.xsd)

Customer Domain Services (from customer.xsd, in service/customer/):

  • CustomerAccountService - Customer account management
  • CustomerService - Customer information
  • MeterService - Meter device information
  • ServiceLocationService - Service location data
  • StatementService - Billing statements

Note: Entities exist for CustomerAgreement and ServiceSupplier but services have not been implemented yet.

Cross-Cutting Services:

  • AuthorizationService - OAuth2 authorization management
  • SubscriptionService - Third-party subscriptions
  • ApplicationInformationService - Application registration
  • NotificationService - Event notifications
  • BatchListService - Batch operations
  • DtoExportService - Entity to DTO mapping and XML export

REST API Structure

REST controllers are in openespi-datacustodian/src/main/java/org/greenbuttonalliance/espi/datacustodian/web/:

  • web/api/ - ESPI RESTful API endpoints (many currently .disabled during migration)
  • web/custodian/ - Data custodian-specific endpoints
  • web/customer/ - Retail customer portal endpoints

Note: Many REST controllers have .disabled extension during the Spring Boot 4.0 migration. They need to be re-enabled and tested after core functionality is validated.

DTO and Mapping Layer

The project uses MapStruct for entity-to-DTO mappings:

  • DTOs: openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/
  • Mappers: openespi-common/src/main/java/org/greenbuttonalliance/espi/common/mapper/

DTOs mirror ESPI XML schema structure and are used exclusively for XML representations. JSON is only used by openespi-authserver for OAuth2 operations.

JAXB Annotation Guidelines

CRITICAL: JAXB annotations MUST only be applied to DTO classes, NEVER to entity or embeddable classes.

  • Entity/Embeddable Classes (domain/ packages):

    • Use JPA annotations only: @Entity, @Table, @Column, @Embeddable, etc.
    • ABSOLUTELY NO JAXB annotations: Do not use @XmlType, @XmlAccessorType, @XmlElement, @XmlRootElement
    • Purpose: JPA persistence layer only
  • DTO Classes (dto/ packages):

    • Use JAXB annotations: @XmlType, @XmlAccessorType, @XmlElement, @XmlRootElement
    • NO JPA annotations
    • Purpose: XML marshalling/unmarshalling only

If an embeddable class needs XML serialization but has no DTO: Create a corresponding DTO class rather than adding JAXB annotations to the embeddable. This rule has NO exceptions.

Rationale: When both entity and DTO classes have JAXB annotations with the same XML type name and namespace, JAXB throws IllegalAnnotationsException due to duplicate type definitions when both are loaded in the same context. This strict separation ensures:

  1. Clean architecture (persistence vs. presentation layers)
  2. No JAXB namespace conflicts
  3. Entities can be refactored without affecting XML schema
  4. DTOs can be optimized for XML without affecting database schema

Database Management

Supported Databases

  • MySQL 8.0+ (primary development database)
  • PostgreSQL 15+ (production recommended)
  • H2 (testing only via TestContainers)

Spring Profiles

Application behavior is controlled via Spring profiles:

  • dev-mysql - MySQL development (default)
  • dev-postgresql - PostgreSQL development
  • local - Local development settings
  • docker - Docker container deployment
  • prod - Production settings
  • test - Test configuration with H2
  • testcontainers - Integration tests with TestContainers

Database Migrations

Flyway manages database schema migrations:

  • Location: openespi-common/src/main/resources/db/migration/
  • MySQL scripts: V1__Create_Base_Tables.sql, V3__Create_additiional_Base_Tables.sql
  • Run migrations: Automatically on application startup with spring.flyway.enabled=true

IMPORTANT: When adding/modifying entities, ensure Flyway migration scripts are updated to match JPA entity definitions.

Key Technologies

Spring Boot 4.0 Stack

  • Spring Boot: 4.0.1
  • Spring Security: 7.x (OAuth2 Resource Server and Client)
  • Spring Data JPA: 4.x with Hibernate 7.x
  • Spring Authorization Server: Latest (for openespi-authserver only)

Persistence

  • JPA/Hibernate: 7.x with Jakarta Persistence API 3.2
  • UUID Primary Keys: All entities use UUID Version 5 instead of Long IDs
  • Flyway: Database migration management
  • HikariCP: Connection pooling

Testing

  • JUnit 5: Test framework
  • Mockito: Mocking framework
  • TestContainers: Docker-based integration testing for MySQL and PostgreSQL
  • Spring Boot Test: Auto-configuration for testing

Build Tools

  • Maven: 3.9+
  • MapStruct: 1.6.3 for DTO mapping
  • Lombok: 1.18.42 for reducing boilerplate

ESPI 4.0 Compliance

This codebase implements the NAESB ESPI 4.0 specification for Green Button data exchange.

XML Schema Files

  • Location: openespi-common/src/main/resources/schema/ESPI_4.0/
  • Files: espi.xsd (usage data), customer.xsd (customer data)

Atom Feed Format

ESPI uses Atom XML feeds for data exchange. Key patterns:

  • Each resource has both feed (collection) and entry (single item) representations
  • Feed and Entry self-links use pattern: https://{host}/DataCustodian/espi/1_1/resource/{resource}/{id} (where {resource} is the entity being received or sent)
  • Entry links include rel="self" (resource URL), rel="up" (parent collection), rel="related" (related resources)
  • All IDs are Type 5 UUIDs in format: urn:uuid:xxxxxxxx-xxxx-5xxx-xxxx-xxxxxxxxxxxx
  • Link type attributes use espi-entry/{resource} or espi-feed/{resource} format

Core ESPI Resources

Usage Domain Resources (from usage.xsd):

  • UsagePoint: Represents a metering point (e.g., electric meter)
  • MeterReading: Collection of interval blocks for a usage point
  • IntervalBlock: Time-series data with individual reading intervals
  • ReadingType: Metadata describing measurement characteristics
  • ElectricPowerQualitySummary: Power quality metrics
  • UsageSummary: Aggregated usage statistics
  • LocalTimeParameters: Timezone configuration
  • RetailCustomer: Retail customer information

Customer Domain Resources (from customer.xsd):

  • CustomerAccount: Customer billing account
  • CustomerAgreement: Agreement between customer and supplier
  • ServiceSupplier: Utility or energy service provider
  • Meter: Physical meter device information
  • ServiceLocation: Physical location of service delivery
  • Statement: Billing statement information

Development Workflow

Branch Strategy

  • Main branch: main (production-ready code)
  • Feature branches: feature/description for new features
  • Bug fixes: fix/description for bug fixes
  • Always create feature branch before making changes - never commit directly to main
  • See BRANCH_STRATEGY.md for detailed workflow

Testing Requirements

  • All tests must pass before committing: mvn test
  • Run tests for affected module and its dependents: mvn test -pl <module> -am
  • Integration tests should pass before PR merge: mvn verify -Pfull-integration
  • IMPORTANT: Use AssertJ chained assertions - combine all assertions for a single object into one assertion chain
    • Good: assertThat(retrieved).isPresent().hasValueSatisfying(device -> assertThat(device).extracting(...).containsExactly(...))
    • Bad: Multiple separate assertThat() statements for the same object
    • This improves readability and provides better failure messages

Common Development Patterns

File Modification Best Practices

CRITICAL: Always use the Edit tool with visible diffs instead of sed/awk for file modifications

  • NEVER use sed, awk, or bash text manipulation for modifying source code or test files

  • ALWAYS use the Edit tool which shows explicit diffs for review

  • Benefits of Edit tool:

    • Changes are visible and reviewable before execution
    • Prevents cascading errors from bulk updates
    • Easy to verify correctness with explicit old_string → new_string diff
    • Catches errors immediately rather than discovering them during compilation
  • When multiple files need the same change:

    • Use multiple Edit tool calls (one per file) in a single message
    • Show exactly what's changing in each file
    • Do NOT use sed/awk loops even if it seems more efficient
  • Exception: Only use bash text tools (grep, find) for searching/analysis, never for modifications

Example - WRONG approach:

# DON'T DO THIS - sed makes changes invisibly
sed -i '' 's/OldClass/NewClass/g' src/**/*.java

Example - CORRECT approach:

# DO THIS - Use Edit tool with explicit diffs
Edit tool call showing:
old_string: "import com.example.OldClass;"
new_string: "import com.example.NewClass;"

This practice prevents issues like missing imports, broken references, and compilation errors that are difficult to track down.

Adding New ESPI Entity

  1. Create entity in openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/ (or /customer/)
  2. Extend IdentifiedObject base class
  3. Add JPA annotations (@Entity, @Table, @Column)
  4. Create repository interface in repositories/
  5. Create service interface and implementation in service/ and service/impl/
  6. Create DTO in dto/ package
  7. Create MapStruct mapper interface in mapper/
  8. Add Flyway migration script in db/migration/
  9. Write unit tests and integration tests

JPA Mapping Guidelines

  • All entities use @Id with UUID type, not Long
  • Use @JoinColumn for foreign keys with explicit name attribute
  • Avoid @Where annotation conflicts with @JoinColumn on the same field
  • Be careful with @ElementCollection and @CollectionTable for embedded collections
  • Phone numbers and addresses are embedded collections using @ElementCollection
  • toString() method sequencing: Entity toString() methods MUST follow the exact database field sequence from Flyway migration scripts. Standard sequence is: id, description, created, updated, published, upLink, selfLink, [type-specific fields in database column order], relatedLinks (if present as last field). Always verify toString() matches the CREATE TABLE statement column order.

REST Controller Development

  • Controllers in openespi-datacustodian implement ESPI REST API
  • Use @RestController and @RequestMapping annotations
  • Follow existing patterns in enabled controllers (e.g., UsagePointController, MeterReadingController)
  • Many controllers currently disabled (.disabled extension) - re-enable after testing core functionality

Migration Status

The codebase has been migrated to Spring Boot 4.0.1 and Java 25. Key migration achievements:

  • Java 25 upgrade complete across all modules
  • Jakarta EE 10+ migration complete (javax → jakarta namespace)
  • Spring Boot 4.0.1 migration complete for common, datacustodian, authserver
  • UUID Version 5 primary keys migrated from Long IDs
  • OAuth2 modernized with Spring Security 7.x patterns
  • RestTemplate replaced with WebClient
  • Spring Data JPA 4.x with Hibernate 7.x

Known Issues

Check migration status documents for current issues:

  • 2025-07-15_Claude_Code_Spring_Boot_3.5_Migration_Plan.md - Historical migration plan
  • openespi-common/SPRING_BOOT_3.5_MIGRATION_STATUS.md - Historical common module status
  • openespi-authserver/MIGRATION_ROADMAP.md - Auth server status

Current Technology Stack

Current versions:

  • Java: 25
  • Spring Boot: 4.0.1
  • Spring Security: 7.x
  • Spring Data JPA: 4.x
  • Hibernate: 7.x
  • Jakarta EE: 10+

OAuth2 Security

Authorization Flow

The system implements OAuth2 authorization code flow:

  1. Third-party application requests authorization
  2. Retail customer authenticates with openespi-authserver
  3. Authorization server issues authorization code
  4. Third-party exchanges code for access token
  5. Third-party accesses data custodian resources with token

Security Configuration

  • Authorization Server: openespi-authserver - Spring Authorization Server (independent module)
  • Resource Server: openespi-datacustodian - Validates OAuth2 tokens
  • OAuth2 Client: openespi-thirdparty - Third-party application using WebClient with OAuth2

Troubleshooting

Build Failures

  • Ensure Java 25 is installed: java -version
  • Clean build: mvn clean install
  • Check for profile-specific issues: review active Spring profile

Test Failures

  • Ensure Docker is running for TestContainers tests
  • Check database connection settings in application-test.yml
  • Review test logs in target/surefire-reports/

Application Startup Issues

  • Check Spring profile is correctly set: SPRING_PROFILES_ACTIVE
  • Verify database is accessible and schema is current
  • Review application logs for JPA mapping errors
  • Check for duplicate column mappings in entities

JPA Mapping Errors

  • Look for duplicate @Column or @JoinColumn definitions
  • Check for conflicts between @Where and relationship mappings
  • Verify Flyway migration scripts match entity definitions
  • Review entity inheritance structure for mapping conflicts

Additional Documentation

  • README.md - Project overview and quick start
  • BRANCH_STRATEGY.md - Git workflow and branching strategy
  • 2025-07-15_Claude_Code_Spring_Boot_3.5_Migration_Plan.md - Historical migration status (Spring Boot 3.5 to 4.0)
  • openespi-common/CONTRIBUTING.md - Contribution guidelines
  • openespi-authserver/DEPLOYMENT_GUIDE.md - Production deployment
  • openespi-authserver/CERTIFICATE_AUTHENTICATION.md - Client certificate auth