Skip to content

Implement comprehensive JAXB unmarshalling support for XML import #89

@dfcoffin

Description

@dfcoffin

Overview

The openespi-common module currently supports marshalling (Java → XML export) for Green Button data, which is used by openespi-datacustodian. However, unmarshalling (XML → Java import) support is incomplete and required for openespi-thirdparty to import Green Button data from data custodians.

Current State

✅ Working: Marshalling (Export)

  • All DTOs successfully marshal to XML
  • Domain-specific export services implemented (UsageExportService, CustomerExportService)
  • Proper namespace prefix handling (atom:, espi:, cust:)
  • 23/23 JAXB marshalling tests passing

⚠️ Partial: Unmarshalling (Import)

  • OffsetDateTime: ✅ Adapter implemented (OffsetDateTimeAdapter)
  • Other Java 8+ time types: ❌ Need adapters
  • Full round-trip: ✅ Working for OffsetDateTime fields
  • Full round-trip: ❌ Untested for other complex types

Problem

JAXB 3.x requires no-arg constructors for unmarshalling. Java 8+ time types (OffsetDateTime, LocalDateTime, ZonedDateTime, etc.) do not have public no-arg constructors, causing unmarshalling to fail with:

java.lang.NoSuchMethodException: java.time.OffsetDateTime.<init>()

Solution Template

We've implemented OffsetDateTimeAdapter as a template:

Location: openespi-common/src/main/java/org/greenbuttonalliance/espi/common/utils/OffsetDateTimeAdapter.java

public class OffsetDateTimeAdapter extends XmlAdapter<String, OffsetDateTime> {
    @Override
    public OffsetDateTime unmarshal(String value) {
        if (value == null || value.trim().isEmpty()) {
            return null;
        }
        return OffsetDateTime.parse(value, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
    }

    @Override
    public String marshal(OffsetDateTime value) {
        if (value == null) {
            return null;
        }
        return value.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME);
    }
}

Usage:

@XmlElement(name = "published")
@XmlJavaTypeAdapter(OffsetDateTimeAdapter.class)
private OffsetDateTime published;

Required Work

1. Create Additional Time Type Adapters

Following the OffsetDateTimeAdapter template, create adapters for:

  • LocalDateTimeAdapter - For LocalDateTime fields
  • ZonedDateTimeAdapter - For ZonedDateTime fields
  • InstantAdapter - For Instant fields
  • LocalDateAdapter - For LocalDate fields
  • LocalTimeAdapter - For LocalTime fields

2. Scan DTOs for Time Type Fields

Identify all DTO fields using Java time types:

grep -r "LocalDateTime\|ZonedDateTime\|Instant\|LocalDate\|LocalTime" \
  openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/ \
  --include="*.java" | grep "private\|protected"

3. Apply Adapters to DTO Fields

Add @XmlJavaTypeAdapter annotations to all time type fields in DTOs.

Example locations:

  • DateTimeIntervalDto - May have LocalDateTime fields
  • LineItemDto - Has dateTime field
  • StatementDto - May have date/time fields
  • CustomerAgreementDto - May have date/time fields

4. Add Comprehensive Round-Trip Tests

Extend JaxbXmlMarshallingTest to cover:

  • All time type adapters (marshal + unmarshal)
  • Complex nested structures with time fields
  • Null handling for optional time fields
  • Edge cases (timezones, DST transitions, etc.)

5. Test Import Scenarios

Create integration tests simulating openespi-thirdparty import use cases:

  • Import Green Button UsagePoint XML
  • Import Green Button MeterReading XML
  • Import Green Button Customer XML
  • Import complete feed with multiple entries

Success Criteria

  • All Java 8+ time type fields have @XmlJavaTypeAdapter annotations
  • All adapter classes created and tested
  • Round-trip tests passing for all time types
  • Integration tests demonstrate full XML import capability
  • openespi-thirdparty can successfully import real Green Button XML files

Files Created (Reference)

Already completed for OffsetDateTime:

  • openespi-common/src/main/java/org/greenbuttonalliance/espi/common/utils/OffsetDateTimeAdapter.java
  • openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/atom/AtomEntryDto.java (applied adapter)
  • openespi-common/src/test/java/org/greenbuttonalliance/espi/common/JaxbXmlMarshallingTest.java (round-trip tests)

Related Work

Priority

Medium - Required for openespi-thirdparty to import Green Button data, but not blocking current schema compliance work (Phases 20+).

Labels

enhancement, jaxb, unmarshalling, openespi-thirdparty

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions