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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions