jakarta.xml.bind
jakarta.xml.bind-api
diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/customer/entity/PhoneNumberEntity.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/customer/entity/PhoneNumberEntity.java
index 728d3921..696199f8 100644
--- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/customer/entity/PhoneNumberEntity.java
+++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/customer/entity/PhoneNumberEntity.java
@@ -23,7 +23,9 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.proxy.HibernateProxy;
+import org.hibernate.type.SqlTypes;
import java.util.Objects;
import java.util.UUID;
@@ -49,7 +51,8 @@ public class PhoneNumberEntity {
*/
@Id
@GeneratedValue(strategy = GenerationType.UUID)
- @Column(name = "id", nullable = false)
+ @JdbcTypeCode(SqlTypes.CHAR)
+ @Column(length = 36, columnDefinition = "char(36)", updatable = false, nullable = false)
private UUID id;
/**
diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/customer/entity/StatementRefEntity.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/customer/entity/StatementRefEntity.java
index 0ee04bb7..f642dedb 100644
--- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/customer/entity/StatementRefEntity.java
+++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/customer/entity/StatementRefEntity.java
@@ -23,7 +23,9 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.proxy.HibernateProxy;
+import org.hibernate.type.SqlTypes;
import java.util.Objects;
import java.util.UUID;
@@ -48,7 +50,8 @@ public class StatementRefEntity {
*/
@Id
@GeneratedValue(strategy = GenerationType.UUID)
- @Column(name = "id", nullable = false)
+ @JdbcTypeCode(SqlTypes.CHAR)
+ @Column(length = 36, columnDefinition = "char(36)", updatable = false, nullable = false)
private UUID id;
/**
diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/AggregatedNodeRefEntity.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/AggregatedNodeRefEntity.java
index ca736c5f..cbea251d 100644
--- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/AggregatedNodeRefEntity.java
+++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/AggregatedNodeRefEntity.java
@@ -23,7 +23,9 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.proxy.HibernateProxy;
+import org.hibernate.type.SqlTypes;
import java.util.Objects;
import java.util.UUID;
@@ -49,7 +51,8 @@ public class AggregatedNodeRefEntity {
*/
@Id
@GeneratedValue(strategy = GenerationType.UUID)
- @Column(name = "id", nullable = false)
+ @JdbcTypeCode(SqlTypes.CHAR)
+ @Column(length = 36, columnDefinition = "char(36)", updatable = false, nullable = false)
private UUID id;
/**
diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/BatchListEntity.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/BatchListEntity.java
index fd2462c9..8aff006d 100644
--- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/BatchListEntity.java
+++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/BatchListEntity.java
@@ -25,7 +25,9 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.proxy.HibernateProxy;
+import org.hibernate.type.SqlTypes;
import java.net.URI;
import java.net.URISyntaxException;
@@ -59,7 +61,8 @@ public class BatchListEntity {
*/
@Id
@GeneratedValue(strategy = GenerationType.UUID)
- @Column(name = "id", nullable = false)
+ @JdbcTypeCode(SqlTypes.CHAR)
+ @Column(length = 36, columnDefinition = "char(36)", updatable = false, nullable = false)
private UUID id;
/**
diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/IntervalReadingEntity.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/IntervalReadingEntity.java
index ac1a979a..e714512e 100644
--- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/IntervalReadingEntity.java
+++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/IntervalReadingEntity.java
@@ -25,7 +25,9 @@
import lombok.Setter;
import org.greenbuttonalliance.espi.common.domain.common.DateTimeInterval;
import org.hibernate.annotations.BatchSize;
+import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.proxy.HibernateProxy;
+import org.hibernate.type.SqlTypes;
import java.util.ArrayList;
import java.util.List;
@@ -54,7 +56,8 @@ public class IntervalReadingEntity {
*/
@Id
@GeneratedValue(strategy = GenerationType.UUID)
- @Column(name = "id", nullable = false)
+ @JdbcTypeCode(SqlTypes.CHAR)
+ @Column(length = 36, columnDefinition = "char(36)", updatable = false, nullable = false)
private UUID id;
/**
diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/LineItemEntity.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/LineItemEntity.java
index da6bdb76..5a141fa2 100644
--- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/LineItemEntity.java
+++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/LineItemEntity.java
@@ -25,7 +25,9 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.proxy.HibernateProxy;
+import org.hibernate.type.SqlTypes;
import java.math.BigDecimal;
import java.math.RoundingMode;
@@ -62,7 +64,8 @@ public class LineItemEntity {
*/
@Id
@GeneratedValue(strategy = GenerationType.UUID)
- @Column(name = "id", nullable = false)
+ @JdbcTypeCode(SqlTypes.CHAR)
+ @Column(length = 36, columnDefinition = "char(36)", updatable = false, nullable = false)
private UUID id;
/**
diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/ReadingQualityEntity.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/ReadingQualityEntity.java
index a51ea571..062bf916 100644
--- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/ReadingQualityEntity.java
+++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/domain/usage/ReadingQualityEntity.java
@@ -25,7 +25,9 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.proxy.HibernateProxy;
+import org.hibernate.type.SqlTypes;
import java.util.Objects;
import java.util.UUID;
@@ -57,7 +59,8 @@ public class ReadingQualityEntity {
*/
@Id
@GeneratedValue(strategy = GenerationType.UUID)
- @Column(name = "id", nullable = false)
+ @JdbcTypeCode(SqlTypes.CHAR)
+ @Column(length = 36, columnDefinition = "char(36)", updatable = false, nullable = false)
private UUID id;
// Quality constants based on common industry standards
diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/atom/AtomContentDto.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/atom/AtomContentDto.java
index 6e180877..b54a36ec 100644
--- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/atom/AtomContentDto.java
+++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/atom/AtomContentDto.java
@@ -19,21 +19,41 @@
package org.greenbuttonalliance.espi.common.dto.atom;
+import com.fasterxml.jackson.annotation.*;
import jakarta.xml.bind.annotation.*;
+import org.greenbuttonalliance.espi.common.dto.usage.MeterReadingDto;
+import org.greenbuttonalliance.espi.common.dto.usage.ReadingTypeDto;
+import org.greenbuttonalliance.espi.common.dto.usage.UsagePointDto;
+import tools.jackson.dataformat.xml.annotation.JacksonXmlProperty;
/**
* Atom Content DTO record for content within Atom entries.
*
* Represents the content section of an Atom entry containing the actual
* Green Button resource data (Customer, UsagePoint, MeterReading, etc.).
+ *
+ * @deprecated AtomContentDto no longer used. Payload moved to AtomEntryDto
*/
+@Deprecated
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "AtomContent", namespace = "http://www.w3.org/2005/Atom")
public record AtomContentDto(
@XmlAttribute(name = "type")
String type,
-
+
+ @JsonProperty("resource")
+ @JacksonXmlProperty(namespace = "http://naesb.org/espi")
+
+ @XmlElementWrapper(name = "resource", namespace = "http://naesb.org/espi")
+ @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
+ include = JsonTypeInfo.As.WRAPPER_OBJECT,
+ property = "type")
+ @JsonSubTypes({
+ @JsonSubTypes.Type(value = UsagePointDto.class, name = "UsagePoint"),
+ @JsonSubTypes.Type(value = MeterReadingDto.class, name = "MeterReading"),
+ @JsonSubTypes.Type(value = ReadingTypeDto.class, name = "ReadingType")
+ })
@XmlAnyElement(lax = true)
Object resource
) {
diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/atom/AtomEntryDto.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/atom/AtomEntryDto.java
index 2c2e0afb..1a63a558 100644
--- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/atom/AtomEntryDto.java
+++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/atom/AtomEntryDto.java
@@ -19,13 +19,22 @@
package org.greenbuttonalliance.espi.common.dto.atom;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
import jakarta.xml.bind.annotation.*;
+import org.greenbuttonalliance.espi.common.dto.usage.MeterReadingDto;
+import org.greenbuttonalliance.espi.common.dto.usage.ReadingTypeDto;
+import org.greenbuttonalliance.espi.common.dto.usage.UsagePointDto;
+
+import java.time.LocalDateTime;
import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
import java.util.List;
/**
* Atom Entry DTO record for individual entries in Atom feeds.
- *
+ *
* Represents an individual entry within an Atom feed containing Green Button data.
* Used to wrap individual resources (usage points, customers, etc.) in Atom format.
*/
@@ -41,7 +50,7 @@ public record AtomEntryDto(
@XmlElement(name = "title", namespace = "http://www.w3.org/2005/Atom")
String title,
-
+
@XmlElement(name = "published", namespace = "http://www.w3.org/2005/Atom")
OffsetDateTime published,
@@ -50,9 +59,18 @@ public record AtomEntryDto(
@XmlElement(name = "link", namespace = "http://www.w3.org/2005/Atom")
List links,
-
+
+ @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
+ include = JsonTypeInfo.As.WRAPPER_OBJECT,
+ property = "type")
+ @JsonSubTypes({
+ @JsonSubTypes.Type(value = UsagePointDto.class, name = "espi:UsagePoint"),
+ @JsonSubTypes.Type(value = MeterReadingDto.class, name = "espi:MeterReading"),
+ @JsonSubTypes.Type(value = ReadingTypeDto.class, name = "espi:ReadingType")
+ })
+ @XmlAnyElement(lax = true)
@XmlElement(name = "content", namespace = "http://www.w3.org/2005/Atom")
- AtomContentDto content
+ Object content
) {
/**
@@ -66,7 +84,12 @@ public AtomEntryDto() {
* Constructor for basic entry data.
*/
public AtomEntryDto(String id, String title, Object resource) {
- this(id, title, OffsetDateTime.now(), OffsetDateTime.now(), null,
+
+ //get date in UTC and truncate to seconds for proper ESPI date format
+ LocalDateTime localDateTime = LocalDateTime.now().truncatedTo(java.time.temporal.ChronoUnit.SECONDS);
+ OffsetDateTime now = localDateTime.atOffset(ZoneOffset.UTC).toZonedDateTime().toOffsetDateTime();
+
+ this(id, title, now, now, null,
new AtomContentDto("application/xml", resource));
}
@@ -100,6 +123,6 @@ public LinkDto getUpLink() {
* @return resource content or null if not available
*/
public Object getResource() {
- return content != null ? content.resource() : null;
+ return content; // != null ? content.resource() : null;
}
}
\ No newline at end of file
diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/IntervalBlockDto.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/IntervalBlockDto.java
index c42de8a1..bc0d657c 100644
--- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/IntervalBlockDto.java
+++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/IntervalBlockDto.java
@@ -39,8 +39,9 @@ public record IntervalBlockDto(
@XmlTransient
Long id,
-
- @XmlAttribute(name = "mRID")
+
+ @XmlTransient
+ //@XmlAttribute(name = "mRID")
String uuid,
@XmlElement(name = "published")
@@ -66,7 +67,7 @@ public record IntervalBlockDto(
DateTimeIntervalDto interval,
@XmlElement(name = "IntervalReading")
- @XmlElementWrapper(name = "IntervalReadings")
+ // @XmlElementWrapper(name = "IntervalReadings")
List intervalReadings
) {
diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/IntervalReadingDto.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/IntervalReadingDto.java
index 4a62fb8f..471412c3 100644
--- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/IntervalReadingDto.java
+++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/IntervalReadingDto.java
@@ -53,7 +53,7 @@ public record IntervalReadingDto(
DateTimeIntervalDto timePeriod,
@XmlElement(name = "ReadingQuality")
- @XmlElementWrapper(name = "ReadingQualities")
+ //@XmlElementWrapper(name = "ReadingQualities")
List readingQualities,
@XmlElement(name = "consumptionTier")
diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/ReadingTypeDto.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/ReadingTypeDto.java
index c3b0233d..186f0db3 100644
--- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/ReadingTypeDto.java
+++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/ReadingTypeDto.java
@@ -46,8 +46,9 @@ public record ReadingTypeDto(
@XmlTransient
Long id,
-
- @XmlAttribute(name = "mRID")
+
+ @XmlTransient
+ // @XmlAttribute(name = "mRID")
String uuid,
@XmlElement(name = "description")
diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/UsagePointDto.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/UsagePointDto.java
index f89dd454..d1e675b9 100644
--- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/UsagePointDto.java
+++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/dto/usage/UsagePointDto.java
@@ -19,12 +19,15 @@
package org.greenbuttonalliance.espi.common.dto.usage;
+import com.fasterxml.jackson.annotation.JsonRootName;
import org.greenbuttonalliance.espi.common.domain.common.ServiceCategory;
import org.greenbuttonalliance.espi.common.dto.SummaryMeasurementDto;
import jakarta.xml.bind.annotation.*;
import jakarta.xml.bind.annotation.adapters.HexBinaryAdapter;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import tools.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import tools.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
/**
* UsagePoint DTO record for JAXB XML marshalling/unmarshalling.
@@ -41,7 +44,9 @@
"pnodeRefs", "aggregatedNodeRefs"
})
public class UsagePointDto {
-
+
+ private String schema ="http://naesb.org/espi";
+
private String uuid;
private String description;
private byte[] roleFlags;
@@ -73,7 +78,7 @@ public String getDescription() {
public byte[] getRoleFlags() {
return roleFlags;
}
-
+
@XmlElement(name = "ServiceCategory")
public ServiceCategory getServiceCategory() {
return serviceCategory;
@@ -151,7 +156,16 @@ public Object getUsageSummaries() {
public Object getElectricPowerQualitySummaries() {
return electricPowerQualitySummaries;
}
-
+
+ @XmlAttribute(name = "xmlns:espi")
+ public String getSchema() {
+ return schema;
+ }
+
+ public void setSchema(String schema) {
+ this.schema = schema;
+ }
+
// Setters for JAXB unmarshalling
public void setUuid(String uuid) {
this.uuid = uuid;
diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/DtoExportService.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/DtoExportService.java
index d4468532..9cd0289f 100644
--- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/DtoExportService.java
+++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/DtoExportService.java
@@ -29,7 +29,7 @@
/**
* Modern DTO-based export service using JAXB marshalling.
- *
+ *
* Provides methods to export entities as DTOs in Green Button XML format,
* supporting both individual resources and collections wrapped in Atom feeds.
*/
@@ -92,4 +92,6 @@ public interface DtoExportService {
* @return Atom entry DTO
*/
AtomEntryDto createAtomEntry(String title, Object resource);
+
+ void exportAtomFeed(AtomFeedDto atomFeedDto, OutputStream stream);
}
\ No newline at end of file
diff --git a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/impl/DtoExportServiceImpl.java b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/impl/DtoExportServiceImpl.java
index 5ffca647..48e793fe 100644
--- a/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/impl/DtoExportServiceImpl.java
+++ b/openespi-common/src/main/java/org/greenbuttonalliance/espi/common/service/impl/DtoExportServiceImpl.java
@@ -19,9 +19,7 @@
package org.greenbuttonalliance.espi.common.service.impl;
-import jakarta.xml.bind.JAXBContext;
-import jakarta.xml.bind.JAXBException;
-import jakarta.xml.bind.Marshaller;
+import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.greenbuttonalliance.espi.common.domain.usage.UsagePointEntity;
@@ -32,13 +30,23 @@
import org.greenbuttonalliance.espi.common.repositories.usage.UsagePointRepository;
import org.greenbuttonalliance.espi.common.service.DtoExportService;
import org.springframework.stereotype.Service;
+import tools.jackson.databind.AnnotationIntrospector;
+import tools.jackson.databind.SerializationFeature;
+import tools.jackson.databind.cfg.DatatypeFeature;
+import tools.jackson.databind.cfg.DateTimeFeature;
+import tools.jackson.databind.introspect.JacksonAnnotationIntrospector;
+import tools.jackson.databind.util.StdDateFormat;
+import tools.jackson.dataformat.xml.XmlAnnotationIntrospector;
+import tools.jackson.dataformat.xml.XmlMapper;
+import tools.jackson.dataformat.xml.XmlWriteFeature;
+import tools.jackson.module.jakarta.xmlbind.JakartaXmlBindAnnotationIntrospector;
+import tools.jackson.module.jakarta.xmlbind.JakartaXmlBindAnnotationModule;
+import java.io.IOException;
import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
import java.time.OffsetDateTime;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-import java.util.UUID;
+import java.util.*;
/**
* Modern DTO-based export service implementation using JAXB marshalling.
@@ -51,6 +59,11 @@ public class DtoExportServiceImpl implements DtoExportService {
private final UsagePointRepository usagePointRepository;
private final UsagePointMapper usagePointMapper;
+ private final String XML_HEADER = """
+
+
+ """;
+
@Override
public void exportUsagePointEntry(UUID usagePointId, OutputStream stream) {
Optional entity = usagePointRepository.findById(usagePointId);
@@ -112,26 +125,50 @@ public void exportUsagePointsFeed(List usagePoints, OutputStre
@Override
public void exportDto(Object dto, OutputStream stream) {
+
+ // Create JAXB context for DTO classes
+ final XmlMapper xmlMapper = createXmlMapper();
+
+ xmlMapper.writeValue(stream, dto);
+
+ log.info("Successfully exported DTO of type: " + dto.getClass().getSimpleName());
+ }
+
+ @Override
+ public void exportAtomFeed(AtomFeedDto atomFeedDto, OutputStream stream) {
+
try {
- // Create JAXB context for DTO classes
- JAXBContext context = JAXBContext.newInstance(
- "org.greenbuttonalliance.espi.common.dto.atom:" +
- "org.greenbuttonalliance.espi.common.dto.usage:" +
- "org.greenbuttonalliance.espi.common.dto.customer"
- );
-
- Marshaller marshaller = context.createMarshaller();
- marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
- marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
-
- // Marshal DTO to stream
- marshaller.marshal(dto, stream);
-
- log.info("Successfully exported DTO of type: " + dto.getClass().getSimpleName());
-
- } catch (JAXBException e) {
- log.error("Failed to export DTO: " + e.getMessage(), e);
+ stream.write(XML_HEADER.getBytes(StandardCharsets.UTF_8));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
}
+
+ // Create JAXB context for DTO classes
+ final XmlMapper xmlMapper = createXmlMapper();
+
+ xmlMapper.writeValue(stream, atomFeedDto);
+
+ log.info("Successfully exported DTO of type: " + atomFeedDto.getClass().getSimpleName());
+ }
+
+ private XmlMapper createXmlMapper() {
+ AnnotationIntrospector intr = XmlAnnotationIntrospector.Pair.instance
+ (new JakartaXmlBindAnnotationIntrospector(),
+ new JacksonAnnotationIntrospector());
+
+ // Create JAXB context for DTO classes
+ //2012-10-24T00:00:00Z
+ return XmlMapper.xmlBuilder()
+ // .configure(XmlWriteFeature.WRITE_XML_DECLARATION, true)
+ .annotationIntrospector(intr)
+ .addModule(new JakartaXmlBindAnnotationModule().setNonNillableInclusion(JsonInclude.Include.NON_EMPTY))
+ .enable(SerializationFeature.INDENT_OUTPUT)
+ .enable(DateTimeFeature.WRITE_DATES_WITH_ZONE_ID)
+ //.enable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)
+ //.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMP)
+ .disable(XmlWriteFeature.WRITE_NULLS_AS_XSI_NIL)
+ .defaultDateFormat(new StdDateFormat())
+ .build();
}
@Override
diff --git a/openespi-common/src/main/resources/db/migration/V1__Create_Base_Tables.sql b/openespi-common/src/main/resources/db/migration/V1__Create_Base_Tables.sql
index 19ba3e16..727b0983 100644
--- a/openespi-common/src/main/resources/db/migration/V1__Create_Base_Tables.sql
+++ b/openespi-common/src/main/resources/db/migration/V1__Create_Base_Tables.sql
@@ -389,8 +389,8 @@ CREATE TABLE batch_lists
(
id CHAR(36) PRIMARY KEY ,
description VARCHAR(255),
- created TIMESTAMP NOT NULL,
- updated TIMESTAMP NOT NULL,
+ created TIMESTAMP,
+ updated TIMESTAMP,
published TIMESTAMP,
up_link_rel VARCHAR(255),
up_link_href VARCHAR(1024),
diff --git a/openespi-common/src/main/resources/db/migration/V3__Create_additiional_Base_Tables.sql b/openespi-common/src/main/resources/db/migration/V3__Create_additiional_Base_Tables.sql
index 559b4e8a..8e1a3f10 100644
--- a/openespi-common/src/main/resources/db/migration/V3__Create_additiional_Base_Tables.sql
+++ b/openespi-common/src/main/resources/db/migration/V3__Create_additiional_Base_Tables.sql
@@ -85,8 +85,8 @@ CREATE TABLE interval_readings
(
id CHAR(36) PRIMARY KEY ,
description VARCHAR(255),
- created TIMESTAMP NOT NULL,
- updated TIMESTAMP NOT NULL,
+ created TIMESTAMP,
+ updated TIMESTAMP,
published TIMESTAMP,
up_link_rel VARCHAR(255),
up_link_href VARCHAR(1024),
@@ -175,8 +175,8 @@ CREATE TABLE usage_summaries
(
id CHAR(36) PRIMARY KEY ,
description VARCHAR(255),
- created TIMESTAMP NOT NULL,
- updated TIMESTAMP NOT NULL,
+ created TIMESTAMP,
+ updated TIMESTAMP,
published TIMESTAMP,
up_link_rel VARCHAR(255),
up_link_href VARCHAR(1024),
@@ -367,8 +367,8 @@ CREATE TABLE aggregated_node_refs
(
id CHAR(36) PRIMARY KEY ,
description VARCHAR(255),
- created TIMESTAMP NOT NULL,
- updated TIMESTAMP NOT NULL,
+ created TIMESTAMP,
+ updated TIMESTAMP,
published TIMESTAMP,
up_link_rel VARCHAR(255),
up_link_href VARCHAR(1024),
@@ -743,8 +743,8 @@ CREATE TABLE line_items
(
id CHAR(36) PRIMARY KEY ,
description VARCHAR(255),
- created TIMESTAMP NOT NULL,
- updated TIMESTAMP NOT NULL,
+ created TIMESTAMP,
+ updated TIMESTAMP,
published TIMESTAMP,
up_link_rel VARCHAR(255),
up_link_href VARCHAR(1024),
@@ -1055,8 +1055,8 @@ CREATE TABLE statement_refs
(
id CHAR(36) PRIMARY KEY ,
description VARCHAR(255),
- created TIMESTAMP NOT NULL,
- updated TIMESTAMP NOT NULL,
+ created TIMESTAMP,
+ updated TIMESTAMP,
published TIMESTAMP,
up_link_rel VARCHAR(255),
up_link_href VARCHAR(1024),
diff --git a/openespi-common/src/main/resources/db/vendor/h2/V2__H2_Specific_Tables.sql b/openespi-common/src/main/resources/db/vendor/h2/V2__H2_Specific_Tables.sql
index b2e96392..7ac4ca68 100644
--- a/openespi-common/src/main/resources/db/vendor/h2/V2__H2_Specific_Tables.sql
+++ b/openespi-common/src/main/resources/db/vendor/h2/V2__H2_Specific_Tables.sql
@@ -33,7 +33,7 @@
-- Time Configuration Table (H2 with BINARY columns)
CREATE TABLE time_configurations
(
- id UUID PRIMARY KEY ,
+ id CHAR(36) PRIMARY KEY ,
description VARCHAR(255),
created TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
@@ -46,9 +46,9 @@ CREATE TABLE time_configurations
self_link_type VARCHAR(255),
-- Time configuration specific fields
- dst_end_rule BINARY,
+ dst_end_rule BINARY VARYING(255),
dst_offset BIGINT,
- dst_start_rule BINARY,
+ dst_start_rule BINARY VARYING(255),
tz_offset BIGINT
);
@@ -59,7 +59,7 @@ CREATE INDEX idx_time_config_updated ON time_configurations (updated);
-- Related Links Table for Time Configurations
CREATE TABLE time_configuration_related_links
(
- time_configuration_id UUID NOT NULL,
+ time_configuration_id CHAR(36) NOT NULL,
related_links VARCHAR(1024),
FOREIGN KEY (time_configuration_id) REFERENCES time_configurations (id) ON DELETE CASCADE
);
@@ -70,7 +70,7 @@ CREATE INDEX idx_time_config_related_links ON time_configuration_related_links (
-- Usage Point Table (H2 with BINARY column)
CREATE TABLE usage_points
(
- id UUID PRIMARY KEY ,
+ id CHAR(36) PRIMARY KEY ,
description VARCHAR(255),
created TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
@@ -84,16 +84,45 @@ CREATE TABLE usage_points
-- Usage point specific fields
kind VARCHAR(50),
- status VARCHAR(50),
+ status smallint,
+ uri VARCHAR(1024),
service_category VARCHAR(50),
service_delivery_remark VARCHAR(255),
- role_flags BINARY,
+ role_flags VARBINARY(255),
+
+ -- Embedded SummaryMeasurement: estimatedLoad
+ estimated_load_multiplier VARCHAR(255),
+ estimated_load_timestamp BIGINT,
+ estimated_load_uom VARCHAR(50),
+ estimated_load_value BIGINT,
+ estimated_load_reading_type_ref VARCHAR(512),
+
+ -- Embedded SummaryMeasurement: nominalServiceVoltage
+ nominal_voltage_multiplier VARCHAR(255),
+ nominal_voltage_timestamp BIGINT,
+ nominal_voltage_uom VARCHAR(50),
+ nominal_voltage_value BIGINT,
+ nominal_voltage_reading_type_ref VARCHAR(512),
+
+ -- Embedded SummaryMeasurement: ratedCurrent
+ rated_current_multiplier VARCHAR(255),
+ rated_current_timestamp BIGINT,
+ rated_current_uom VARCHAR(50),
+ rated_current_value BIGINT,
+ rated_current_reading_type_ref VARCHAR(512),
+
+ -- Embedded SummaryMeasurement: ratedPower
+ rated_power_multiplier VARCHAR(255),
+ rated_power_timestamp BIGINT,
+ rated_power_uom VARCHAR(50),
+ rated_power_value BIGINT,
+ rated_power_reading_type_ref VARCHAR(512),
-- Foreign key relationships
- retail_customer_id UUID,
- service_delivery_point_id UUID,
- local_time_parameters_id UUID,
- subscription_id UUID,
+ retail_customer_id CHAR(36),
+ service_delivery_point_id CHAR(36),
+ local_time_parameters_id CHAR(36),
+ subscription_id CHAR(36),
FOREIGN KEY (retail_customer_id) REFERENCES retail_customers (id) ON DELETE CASCADE,
FOREIGN KEY (service_delivery_point_id) REFERENCES service_delivery_points (id) ON DELETE SET NULL,
@@ -112,7 +141,7 @@ CREATE INDEX idx_usage_point_updated ON usage_points (updated);
-- Related Links Table for Usage Points
CREATE TABLE usage_point_related_links
(
- usage_point_id UUID NOT NULL,
+ usage_point_id CHAR(36) NOT NULL,
related_links VARCHAR(1024),
FOREIGN KEY (usage_point_id) REFERENCES usage_points (id) ON DELETE CASCADE
);
diff --git a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/SimpleXmlMarshallingTest.java b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/SimpleXmlMarshallingTest.java
index cc672b34..fa55be55 100644
--- a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/SimpleXmlMarshallingTest.java
+++ b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/SimpleXmlMarshallingTest.java
@@ -25,6 +25,7 @@
import jakarta.xml.bind.Unmarshaller;
import org.greenbuttonalliance.espi.common.dto.usage.UsagePointDto;
import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@@ -37,6 +38,7 @@
* Simple XML marshalling tests to verify basic JAXB functionality with ESPI data.
* Tests marshal/unmarshal round-trip with realistic data structures.
*/
+@Disabled // JT - todo, refactor to use Jackson for mashalling
@DisplayName("Simple XML Marshalling Tests")
class SimpleXmlMarshallingTest {
diff --git a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/migration/DataCustodianApplicationMysqlTest.java b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/migration/DataCustodianApplicationMysqlTest.java
index 461e3b08..acbd1fa9 100644
--- a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/migration/DataCustodianApplicationMysqlTest.java
+++ b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/migration/DataCustodianApplicationMysqlTest.java
@@ -44,7 +44,7 @@
* running in a Docker container, and that Flyway migrations execute correctly with the new
* vendor-specific migration structure.
*/
-@Disabled //JT - temp until flyway migration is fixed
+//@Disabled //JT - temp until flyway migration is fixed
@SpringBootTest(classes = { TestApplication.class })
@ActiveProfiles("test-mysql")
@Testcontainers
diff --git a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/migration/DataCustodianApplicationPostgresTest.java b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/migration/DataCustodianApplicationPostgresTest.java
index ba8cbcd2..83ede914 100644
--- a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/migration/DataCustodianApplicationPostgresTest.java
+++ b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/migration/DataCustodianApplicationPostgresTest.java
@@ -40,7 +40,7 @@
/**
* Integration test for the OpenESPI Data Custodian Spring Boot application with PostgreSQL Test Container.
- *
+ *
* This test verifies that the application context loads successfully with a real PostgreSQL database
* running in a Docker container, and that Flyway migrations execute correctly with the new
* vendor-specific migration structure.
@@ -49,13 +49,6 @@
@ActiveProfiles("test-postgres")
@Testcontainers
@DisplayName("PostgreSQL Test Container Integration Tests")
-@Disabled("Temporarily disabled due to Issue #53: PostgreSQL UUID CHAR(36) type mismatch. " +
- "JPA entities use @GeneratedValue(strategy = GenerationType.UUID) expecting native UUID type, " +
- "but Flyway migrations use CHAR(36) for MySQL/H2 compatibility. " +
- "Configuration issues (Issue #55) have been resolved - Flyway paths and PostgreSQL version are correct. " +
- "This test will be re-enabled after MULTI_PHASE schema compliance plan completes and UUID conversion is implemented. " +
- "See: https://github.com/GreenButtonAlliance/OpenESPI-GreenButton-Java/issues/53 " +
- "and https://github.com/GreenButtonAlliance/OpenESPI-GreenButton-Java/issues/55")
class DataCustodianApplicationPostgresTest {
@Container
diff --git a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/integration/ComplexRelationshipPostgreSQLIntegrationTest.java b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/integration/ComplexRelationshipPostgreSQLIntegrationTest.java
index 792ce9f5..5246f7f1 100644
--- a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/integration/ComplexRelationshipPostgreSQLIntegrationTest.java
+++ b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/repositories/integration/ComplexRelationshipPostgreSQLIntegrationTest.java
@@ -70,6 +70,11 @@ static void configurePostgreSQLProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
registry.add("spring.datasource.driver-class-name", () -> "org.postgresql.Driver");
+ registry.add("spring.jpa.hibernate.dialect", () -> "classpath:db/migration/postgresql");
+
+ registry.add("spring.jpa.database-platform", () -> "org.hibernate.dialect.PostgreSQLDialect");
+ registry.add("spring.jpa.hibernate.ddl-auto", () -> "validate");
+ registry.add("spring.jpa.show-sql", () -> "true");
}
@Autowired
diff --git a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/service/impl/DtoExportServiceImplTest.java b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/service/impl/DtoExportServiceImplTest.java
new file mode 100644
index 00000000..16fe434f
--- /dev/null
+++ b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/service/impl/DtoExportServiceImplTest.java
@@ -0,0 +1,148 @@
+package org.greenbuttonalliance.espi.common.service.impl;
+
+import org.greenbuttonalliance.espi.common.domain.common.LinkType;
+import org.greenbuttonalliance.espi.common.domain.common.ServiceCategory;
+import org.greenbuttonalliance.espi.common.domain.usage.UsagePointEntity;
+import org.greenbuttonalliance.espi.common.dto.atom.AtomEntryDto;
+import org.greenbuttonalliance.espi.common.dto.atom.AtomFeedDto;
+import org.greenbuttonalliance.espi.common.dto.atom.LinkDto;
+import org.greenbuttonalliance.espi.common.dto.usage.*;
+import org.greenbuttonalliance.espi.common.mapper.DateTimeMapperImpl;
+import org.greenbuttonalliance.espi.common.mapper.usage.*;
+import org.greenbuttonalliance.espi.common.repositories.usage.UsagePointRepository;
+import org.jspecify.annotations.NonNull;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+
+class DtoExportServiceImplTest {
+
+ private UsagePointRepository usagePointRepository;
+
+ private UsagePointMapper usagePointMapper = new UsagePointMapperImpl();
+
+ private MeterReadingMapper meterReadingMapper = new MeterReadingMapperImpl();
+ private DtoExportServiceImpl dtoExportService;
+
+ @BeforeEach
+ void setUp() {
+ ReflectionTestUtils.setField(usagePointMapper, "dateTimeMapper", new DateTimeMapperImpl());
+ ReflectionTestUtils.setField(usagePointMapper, "serviceDeliveryPointMapper", new ServiceDeliveryPointMapperImpl());
+ ReflectionTestUtils.setField(meterReadingMapper, "dateTimeMapper", new DateTimeMapperImpl());
+
+ dtoExportService = new DtoExportServiceImpl(usagePointRepository, usagePointMapper);
+ }
+
+ @Test
+ void export_atom_feed_test() throws IOException {
+ LocalDateTime localDateTime = LocalDateTime.now().truncatedTo(java.time.temporal.ChronoUnit.SECONDS);
+ OffsetDateTime now = localDateTime.atOffset(ZoneOffset.UTC).toZonedDateTime().toOffsetDateTime();
+
+ AtomEntryDto usagePointEntryDto = getUsagePointEntry(now);
+
+ AtomEntryDto meterReadingEntryDto = getMeeterReadingEntryDto(now);
+
+ AtomEntryDto readingEntry = getReadingEntryDto(now);
+
+ AtomEntryDto intervalBlockEntry = getIntervlBlockEntryDto(now);
+
+ AtomFeedDto atomFeedDto = new AtomFeedDto("urn:uuid:15B0A4ED-CCF4-4521-A0A1-9FF650EC8A6B", "Green Button Subscription Feed",
+ now, now, null, List.of(usagePointEntryDto, meterReadingEntryDto, readingEntry, intervalBlockEntry));
+
+ try (OutputStream stream = new ByteArrayOutputStream()) {
+ // Commented out due to conflict in IntervalReadingDto which cannot be fixed in this task
+ dtoExportService.exportAtomFeed(atomFeedDto, stream);
+
+ System.out.println(stream.toString());
+ }
+ }
+
+ private static @NonNull AtomEntryDto getIntervlBlockEntryDto(OffsetDateTime now) {
+ List intervalReadings = new ArrayList<>();
+ intervalReadings.add(new IntervalReadingDto( 974L, null, 282L, new DateTimeIntervalDto(1330578000L, 900L), new ArrayList<>(List.of(new ReadingQualityDto( "8"))), null, null, null));
+
+ intervalReadings.add(new IntervalReadingDto( 965L, null, 323L, new DateTimeIntervalDto(1330578900L, 900L), new ArrayList<>(List.of(new ReadingQualityDto( "7"))), null, null, null));
+
+ intervalReadings.add(new IntervalReadingDto(294L, 884L, null, new DateTimeIntervalDto(1330579800L, 900L)));
+ intervalReadings.add(new IntervalReadingDto(331L, 995L, null, new DateTimeIntervalDto(1330580700L, 900L)));
+
+ IntervalBlockDto intervalBlockDto = new IntervalBlockDto("urn:uuid:FE9A61BB-6913-42D4-88BE-9634A218EF53",
+ new DateTimeIntervalDto(1330578000L, 86400L), intervalReadings);
+
+ List intervalBlockLinks = new ArrayList<>();
+ intervalBlockLinks.add(new LinkDto("self", "/espi/1_1/resource/RetailCustomer/9B6C7066/UsagePoint/5446AF3F/MeterReading/01/IntervalBlock/173"));
+ intervalBlockLinks.add(new LinkDto("up", "/espi/1_1/resource/RetailCustomer/9B6C7066/UsagePoint/5446AF3F/MeterReading/01/IntervalBlock"));
+
+ return new AtomEntryDto("urn:uuid:FE9A61BB-6913-42D4-88BE-9634A218EF53", "Interval Block", now, now,
+ intervalBlockLinks, intervalBlockDto);
+ }
+
+ private static @NonNull AtomEntryDto getReadingEntryDto(OffsetDateTime now) {
+ ReadingTypeDto readingTypeDto = new ReadingTypeDto(1L, "urn:uuid:3430B025-65D5-493A-BEC2-053603C91CD7",
+ null, "4", "1", null, "840", "12", "NET", "TOTAL", 900L, "NET", "KILO", "DAILY", "V", "1", "CONTINUOUS", "1", null,
+ null, null);
+
+ // AtomContentDto readingTypeDtoContent = new AtomContentDto(readingTypeDto);
+ List readingTypeLinkList = new ArrayList<>();
+ readingTypeLinkList.add(new LinkDto("self", "/espi/1_1/resource/ReadingType/07"));
+ readingTypeLinkList.add(new LinkDto("up", "/espi/1_1/resource/ReadingType"));
+
+ return new AtomEntryDto("urn:uuid:3430B025-65D5-493A-BEC2-053603C91CD7", "Type of Meter Reading Data", now, now,
+ readingTypeLinkList, readingTypeDto);
+ }
+
+ private static @NonNull AtomEntryDto getMeeterReadingEntryDto(OffsetDateTime now) {
+ MeterReadingDto meterReadingDto = new MeterReadingDto();
+
+ List meterReadingLinkList = new ArrayList<>();
+ meterReadingLinkList.add(new LinkDto("self", "/espi/1_1/resource/RetailCustomer/9B6C7066/UsagePoint/5446AF3F/MeterReading/01"));
+ meterReadingLinkList.add(new LinkDto("up", "/espi/1_1/resource/RetailCustomer/9B6C7066/UsagePoint/5446AF3F/MeterReading"));
+
+ return new AtomEntryDto("urn:uuid:01", "Meter Reading", now, now, meterReadingLinkList, meterReadingDto);
+ }
+
+ AtomEntryDto getUsagePointEntry(OffsetDateTime now) {
+
+ UsagePointEntity usagePointEntity = new UsagePointEntity();
+ usagePointEntity.setId(UUID.fromString("48C2A019-5598-4E16-B0F9-49E4FF27F5FB"));
+ usagePointEntity.setSelfLink(new LinkType("self", "/espi/1_1/resource/RetailCustomer/9B6C7066/UsagePoint/5446AF3F"));
+ usagePointEntity.setUpLink(new LinkType("up", "/espi/1_1/resource/RetailCustomer/9B6C7066/UsagePoint"));
+ List relatedLinks = new ArrayList<>();
+ relatedLinks.add(new LinkType("related","/espi/1_1/resource/RetailCustomer/9B6C7066/UsagePoint/5446AF3F/MeterReading" ));
+ relatedLinks.add(new LinkType("related","/espi/1_1/resource/RetailCustomer/9B6C7066/UsagePoint/5446AF3F/ElectricPowerUsageSummary" ));
+ relatedLinks.add(new LinkType("related","/espi/1_1/resource/RetailCustomer/9B6C7066/UsagePoint/5446AF3F/ElectricPowerQualitySummary" ));
+ relatedLinks.add(new LinkType("related","/espi/1_1/resource/LocalTimeParameters/01" ));
+ usagePointEntity.setRelatedLinks(relatedLinks);
+
+ usagePointEntity.setServiceCategory(ServiceCategory.ELECTRICITY);
+
+ List usagePointList = new ArrayList<>();
+
+ usagePointList.add(new LinkDto("self","/espi/1_1/resource/RetailCustomer/9B6C7066/UsagePoint/5446AF3F" ));
+ usagePointList.add(new LinkDto("up","\"/espi/1_1/resource/RetailCustomer/9B6C7066/UsagePoint" ));
+ usagePointList.add(new LinkDto("related","/espi/1_1/resource/RetailCustomer/9B6C7066/UsagePoint/5446AF3F" ));
+ usagePointList.add(new LinkDto("related","/espi/1_1/resource/RetailCustomer/9B6C7066/UsagePoint/5446AF3F/MeterReading" ));
+ usagePointList.add(new LinkDto("related","/espi/1_1/resource/RetailCustomer/9B6C7066/UsagePoint/5446AF3F/ElectricPowerUsageSummary" ));
+ usagePointList.add(new LinkDto("related","/espi/1_1/resource/RetailCustomer/9B6C7066/UsagePoint/5446AF3F/ElectricPowerQualitySummary" ));
+ usagePointList.add(new LinkDto("related","/espi/1_1/resource/LocalTimeParameters/01" ));
+
+ UsagePointDto usagePointDto = usagePointMapper.toDto(usagePointEntity);
+
+ return new AtomEntryDto("urn:uuid:48C2A019-5598-4E16-B0F9-49E4FF27F5FB", "Front Electric Meter",
+ now,
+ now,
+ usagePointList,
+ usagePointDto);
+ }
+}
\ No newline at end of file
diff --git a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/test/BaseTestContainersTest.java b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/test/BaseTestContainersTest.java
index 464ed5d5..ef8b9b60 100644
--- a/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/test/BaseTestContainersTest.java
+++ b/openespi-common/src/test/java/org/greenbuttonalliance/espi/common/test/BaseTestContainersTest.java
@@ -65,7 +65,7 @@ public abstract class BaseTestContainersTest {
* PostgreSQL 15 container for integration testing.
* Reusable across tests for better performance.
*/
- protected static final PostgreSQLContainer> postgresqlContainer = new PostgreSQLContainer<>("postgres:15-alpine")
+ protected static final PostgreSQLContainer> postgresqlContainer = new PostgreSQLContainer<>("postgres:18")
.withDatabaseName("openespi_test")
.withUsername("test")
.withPassword("test")
diff --git a/openespi-common/src/test/resources/application-test-mysql.yml b/openespi-common/src/test/resources/application-test-mysql.yml
index de5d8135..3a5bcf86 100644
--- a/openespi-common/src/test/resources/application-test-mysql.yml
+++ b/openespi-common/src/test/resources/application-test-mysql.yml
@@ -3,12 +3,6 @@ spring:
database-platform: org.hibernate.dialect.MySQLDialect
hibernate:
ddl-auto: none
- properties:
- jakarta:
- persistence:
- schema-generation:
- database:
- action: none
hibernate:
dialect: org.hibernate.dialect.MySQLDialect
format_sql: true
@@ -18,7 +12,8 @@ spring:
enabled: true
locations: classpath:db/migration,classpath:db/vendor/mysql
-logging:
- level:
- org.flywaydb: DEBUG
- org.hibernate.SQL: DEBUG
+# JT Commenting out to reduce logging in builds
+#logging:
+# level:
+# org.flywaydb: DEBUG
+# org.hibernate.SQL: DEBUG
diff --git a/openespi-common/src/test/resources/application-test-postgresql.yml b/openespi-common/src/test/resources/application-test-postgresql.yml
index 5eb01972..d9c79232 100644
--- a/openespi-common/src/test/resources/application-test-postgresql.yml
+++ b/openespi-common/src/test/resources/application-test-postgresql.yml
@@ -2,13 +2,7 @@ spring:
jpa:
database-platform: org.hibernate.dialect.PostgreSQLDialect
hibernate:
- ddl-auto: none
- properties:
- jakarta:
- persistence:
- schema-generation:
- database:
- action: none
+ ddl-auto: validate
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
format_sql: true
@@ -18,7 +12,8 @@ spring:
enabled: true
locations: classpath:db/migration,classpath:db/vendor/postgres
-logging:
- level:
- org.flywaydb: DEBUG
- org.hibernate.SQL: DEBUG
+# JT - Commenting out to reduce logging in builds
+#logging:
+# level:
+# org.flywaydb: DEBUG
+# org.hibernate.SQL: DEBUG
diff --git a/openespi-common/src/test/resources/application-test.yml b/openespi-common/src/test/resources/application-test.yml
index ca592b43..0211d017 100644
--- a/openespi-common/src/test/resources/application-test.yml
+++ b/openespi-common/src/test/resources/application-test.yml
@@ -5,10 +5,10 @@ spring:
# JPA/Hibernate Configuration
jpa:
hibernate:
- ddl-auto: create-drop
+ ddl-auto: validate
properties:
hibernate:
- dialect: org.hibernate.dialect.H2Dialect
+ #dialect: org.hibernate.dialect.H2Dialect
show_sql: false
format_sql: true
use_sql_comments: true
diff --git a/openespi-common/src/test/resources/sample-xml/testdata.xml b/openespi-common/src/test/resources/sample-xml/testdata.xml
new file mode 100644
index 00000000..c080d33b
--- /dev/null
+++ b/openespi-common/src/test/resources/sample-xml/testdata.xml
@@ -0,0 +1,304 @@
+
+ urn:uuid:01e5ada4-476e-51d7-95e5-49a98490678c
+
+ Green Button Usage Feed
+ 2022-05-20T17:38:49Z
+
+
+ urn:uuid:a5b81db5-ea77-535f-ac71-bb6b4f1363e5
+
+
+
+
+
+ UsagePoint
+
+
+
+ 0
+
+ 0
+
+
+ 2013-08-30T00:00:00Z
+ 2013-08-30T00:00:00Z
+
+
+ urn:uuid:bbc0e37f-3f90-5a9c-870d-d27f19b6fb07
+
+
+
+ EST
+
+
+ 30
+ 3600
+ 30
+ -18000
+
+
+ 2021-04-20T19:34:18Z
+ 2021-04-20T19:34:18Z
+
+
+ urn:uuid:618274dc-ea93-5e59-9357-81d6d8fe45e6
+
+
+
+
+
+ MeterReading
+
+
+
+ 2022-02-23T06:00:00Z
+ 2022-03-22T13:47:18Z
+
+ 1:55
+
+ urn:uuid:fa404785-1dc7-5aab-952d-14f8841df8de
+
+
+
+
+
+
+
+ 86400
+ 1641099600
+
+
+
+ 86400
+ 1641099600
+
+ 3880
+
+
+
+ 86400
+ 1641103200
+
+ 1480
+
+
+
+ 86400
+ 1641106800
+
+ 1360
+
+
+
+ 86400
+ 1641110400
+
+ 1300
+
+
+
+ 86400
+ 1641114000
+
+ 1380
+
+
+
+ 86400
+ 1641117600
+
+ 1250
+
+
+
+ 86400
+ 1641121200
+
+ 1290
+
+
+
+ 86400
+ 1641124800
+
+ 1200
+
+
+
+ 86400
+ 1641128400
+
+ 1230
+
+
+
+ 86400
+ 1641132000
+
+ 1120
+
+
+
+ 86400
+ 1641135600
+
+ 1550
+
+
+
+ 86400
+ 1641139200
+
+ 1760
+
+
+
+ 86400
+ 1641142800
+
+ 3120
+
+
+
+ 86400
+ 1641146400
+
+ 3020
+
+
+
+ 86400
+ 1641150000
+
+ 3830
+
+
+
+ 86400
+ 1641153600
+
+ 3170
+
+
+
+ 86400
+ 1641157200
+
+ 2960
+
+
+
+ 86400
+ 1641160800
+
+ 3030
+
+
+
+ 86400
+ 1641164400
+
+ 5380
+
+
+
+ 86400
+ 1641168000
+
+ 3190
+
+
+
+ 86400
+ 1641171600
+
+ 2180
+
+
+
+ 86400
+ 1641175200
+
+ 2500
+
+
+
+ 86400
+ 1641178800
+
+ 4180
+
+
+
+ 86400
+ 1641182400
+
+ 2200
+
+
+
+ 2022-01-02T06:00:00Z
+ 2022-05-19T21:44:50Z
+
+
+ urn:uuid:273b0c90-188d-53db-99f6-a7aad0836120
+
+
+
+
+
+
+
+
+ 2592000
+ 1632528000
+
+ 9
+ 9
+ 30
+ 124
+
+ 3
+ 1652996682269
+ 72
+ 32004060
+
+
+ 3
+ 1652996682269
+ 72
+ 32004060
+
+ 0
+ 0
+
+
+ 2021-10-25T00:00:00Z
+ 2021-10-25T00:00:00Z
+
+
+ urn:uuid:6f8569ce-0367-5ccb-a125-3f28ce47894e
+
+
+
+ WH
+
+
+ 4
+ 1
+ 124
+ 12
+ 0
+ 1
+ 3600
+ 12
+ 0
+ 0
+ 0
+ 72
+
+
+ 2013-04-04T03:35:38Z
+ 2013-04-04T03:35:38Z
+
+
diff --git a/openespi-datacustodian/src/test/resources/application-test.yml b/openespi-datacustodian/src/test/resources/application-test.yml
index a18170f1..7952089a 100644
--- a/openespi-datacustodian/src/test/resources/application-test.yml
+++ b/openespi-datacustodian/src/test/resources/application-test.yml
@@ -8,7 +8,7 @@ spring:
jpa:
hibernate:
- ddl-auto: create-drop
+ ddl-auto: validate
show-sql: false
properties:
hibernate:
@@ -16,7 +16,11 @@ spring:
generate_statistics: false
flyway:
- enabled: false
+ enabled: true
+ baseline-on-migrate: true
+ locations:
+ - classpath:db/migration
+ - classpath:db/vendor/h2
security:
oauth2:
@@ -30,7 +34,7 @@ logging:
org.greenbuttonalliance.espi: DEBUG
org.springframework.security: WARN
org.hibernate: WARN
- org.flywaydb: WARN
+ org.flywaydb: INFO
espi:
datacustodian:
diff --git a/openespi-datacustodian/src/test/resources/application-testcontainers-mysql.yml b/openespi-datacustodian/src/test/resources/application-testcontainers-mysql.yml
deleted file mode 100644
index 14cdc20b..00000000
--- a/openespi-datacustodian/src/test/resources/application-testcontainers-mysql.yml
+++ /dev/null
@@ -1,54 +0,0 @@
-# TestContainers MySQL Test Configuration
-spring:
- datasource:
- # These properties will be overridden by TestContainers
- url: jdbc:mysql://localhost:3306/testdb
- username: test
- password: test
- driver-class-name: com.mysql.cj.jdbc.Driver
- hikari:
- maximum-pool-size: 10
- minimum-idle: 2
- idle-timeout: 300000
- pool-name: TestContainersMySQLHikariCP
- auto-commit: false
- connection-test-query: SELECT 1
-
- jpa:
- hibernate:
- ddl-auto: none
- show-sql: false
- properties:
- hibernate:
- dialect: org.hibernate.dialect.MySQLDialect
- generate_statistics: false
-
- flyway:
- enabled: true
- baseline-on-migrate: true
- locations: classpath:db/migration/mysql
-
- # Faster testing configuration
- main:
- lazy-initialization: true
- jmx:
- enabled: false
-
-# Reduced logging for tests
-logging:
- level:
- org.greenbuttonalliance.espi: WARN
- org.springframework.security: WARN
- org.hibernate: WARN
- org.flywaydb: INFO
- org.testcontainers: INFO
- com.github.dockerjava: WARN
-
-espi:
- datacustodian:
- base-url: http://localhost:8081/DataCustodian
- authorization-server:
- issuer-uri: http://localhost:9999
- introspection-endpoint: http://localhost:9999/oauth2/introspect
- client-id: data_custodian_admin
- client-secret: secret
\ No newline at end of file
diff --git a/openespi-datacustodian/src/test/resources/application-testcontainers-postgresql.yml b/openespi-datacustodian/src/test/resources/application-testcontainers-postgresql.yml
deleted file mode 100644
index 59c62817..00000000
--- a/openespi-datacustodian/src/test/resources/application-testcontainers-postgresql.yml
+++ /dev/null
@@ -1,54 +0,0 @@
-# TestContainers PostgreSQL Test Configuration
-spring:
- datasource:
- # These properties will be overridden by TestContainers
- url: jdbc:postgresql://localhost:5432/testdb
- username: test
- password: test
- driver-class-name: org.postgresql.Driver
- hikari:
- maximum-pool-size: 10
- minimum-idle: 2
- idle-timeout: 300000
- pool-name: TestContainersPostgreSQLHikariCP
- auto-commit: false
- connection-test-query: SELECT 1
-
- jpa:
- hibernate:
- ddl-auto: none
- show-sql: false
- properties:
- hibernate:
- dialect: org.hibernate.dialect.PostgreSQLDialect
- generate_statistics: false
-
- flyway:
- enabled: true
- baseline-on-migrate: true
- locations: classpath:db/migration,classpath:db/vendor/postgres
-
- # Faster testing configuration
- main:
- lazy-initialization: true
- jmx:
- enabled: false
-
-# Reduced logging for tests
-logging:
- level:
- org.greenbuttonalliance.espi: WARN
- org.springframework.security: WARN
- org.hibernate: WARN
- org.flywaydb: INFO
- org.testcontainers: INFO
- com.github.dockerjava: WARN
-
-espi:
- datacustodian:
- base-url: http://localhost:8081/DataCustodian
- authorization-server:
- issuer-uri: http://localhost:9999
- introspection-endpoint: http://localhost:9999/oauth2/introspect
- client-id: data_custodian_admin
- client-secret: secret
\ No newline at end of file
diff --git a/openespi-thirdparty/src/test/resources/application-testcontainers-mysql.yml b/openespi-thirdparty/src/test/resources/application-testcontainers-mysql.yml
deleted file mode 100644
index b6f50705..00000000
--- a/openespi-thirdparty/src/test/resources/application-testcontainers-mysql.yml
+++ /dev/null
@@ -1,56 +0,0 @@
-# TestContainers MySQL Test Configuration
-spring:
- datasource:
- # These properties will be overridden by TestContainers
- url: jdbc:mysql://localhost:3306/testdb
- username: test
- password: test
- driver-class-name: com.mysql.cj.jdbc.Driver
- hikari:
- maximum-pool-size: 10
- minimum-idle: 2
- idle-timeout: 300000
- pool-name: TestContainersMySQLHikariCP
- auto-commit: false
- connection-test-query: SELECT 1
-
- jpa:
- hibernate:
- ddl-auto: none
- show-sql: false
- properties:
- hibernate:
- dialect: org.hibernate.dialect.MySQLDialect
- generate_statistics: false
-
- flyway:
- enabled: true
- baseline-on-migrate: true
- locations: classpath:db/migration/mysql
-
- # Faster testing configuration
- main:
- lazy-initialization: true
- jmx:
- enabled: false
-
-# Reduced logging for tests
-logging:
- level:
- org.greenbuttonalliance.espi: WARN
- org.springframework.security: WARN
- org.springframework.oauth2: WARN
- org.hibernate: WARN
- org.flywaydb: INFO
- org.testcontainers: INFO
- com.github.dockerjava: WARN
-
-espi:
- thirdparty:
- base-url: http://localhost:8082/ThirdParty
- datacustodian:
- base-url: http://localhost:8081/DataCustodian
- authorization-server:
- issuer-uri: http://localhost:9999
- authorization-endpoint: http://localhost:9999/oauth2/authorize
- token-endpoint: http://localhost:9999/oauth2/token
\ No newline at end of file
diff --git a/openespi-thirdparty/src/test/resources/application-testcontainers-postgresql.yml b/openespi-thirdparty/src/test/resources/application-testcontainers-postgresql.yml
deleted file mode 100644
index a7efe7b8..00000000
--- a/openespi-thirdparty/src/test/resources/application-testcontainers-postgresql.yml
+++ /dev/null
@@ -1,56 +0,0 @@
-# TestContainers PostgreSQL Test Configuration
-spring:
- datasource:
- # These properties will be overridden by TestContainers
- url: jdbc:postgresql://localhost:5432/testdb
- username: test
- password: test
- driver-class-name: org.postgresql.Driver
- hikari:
- maximum-pool-size: 10
- minimum-idle: 2
- idle-timeout: 300000
- pool-name: TestContainersPostgreSQLHikariCP
- auto-commit: false
- connection-test-query: SELECT 1
-
- jpa:
- hibernate:
- ddl-auto: none
- show-sql: false
- properties:
- hibernate:
- dialect: org.hibernate.dialect.PostgreSQLDialect
- generate_statistics: false
-
- flyway:
- enabled: true
- baseline-on-migrate: true
- locations: classpath:db/migration,classpath:db/vendor/postgres
-
- # Faster testing configuration
- main:
- lazy-initialization: true
- jmx:
- enabled: false
-
-# Reduced logging for tests
-logging:
- level:
- org.greenbuttonalliance.espi: WARN
- org.springframework.security: WARN
- org.springframework.oauth2: WARN
- org.hibernate: WARN
- org.flywaydb: INFO
- org.testcontainers: INFO
- com.github.dockerjava: WARN
-
-espi:
- thirdparty:
- base-url: http://localhost:8082/ThirdParty
- datacustodian:
- base-url: http://localhost:8081/DataCustodian
- authorization-server:
- issuer-uri: http://localhost:9999
- authorization-endpoint: http://localhost:9999/oauth2/authorize
- token-endpoint: http://localhost:9999/oauth2/token
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index dcb64bd0..679654d6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -85,7 +85,7 @@
1.4
6.1.0
9.5.0
- 42.7.7
+ 42.7.8
2.17.0
2.2.41
2.5.3
@@ -102,7 +102,6 @@
openespi-authserver
-
integration-tests