diff --git a/pom.xml b/pom.xml
index 19ce112..39447fa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,6 +69,10 @@
org.apache.camel.springboot
camel-jackson-starter
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+
org.flywaydb
diff --git a/postman/eventhub-esper-poc.postman_collection.json b/postman/eventhub-esper-poc.postman_collection.json
index 784e338..ee30532 100644
--- a/postman/eventhub-esper-poc.postman_collection.json
+++ b/postman/eventhub-esper-poc.postman_collection.json
@@ -631,6 +631,121 @@
}
}
]
+ },
+ {
+ "name": "Tachograph composite sessions",
+ "item": [
+ {
+ "name": "Create tachograph composite session",
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "value": "application/json"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{\n \"sessionIds\": [\n \"{{sessionId}}\",\n \"{{additionalSessionId}}\"\n ],\n \"label\": \"{{compositeSessionLabel}}\"\n}"
+ },
+ "url": {
+ "raw": "{{baseUrl}}/api/eventhub/tachograph-composite-sessions",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "api",
+ "eventhub",
+ "tachograph-composite-sessions"
+ ]
+ }
+ }
+ },
+ {
+ "name": "Get tachograph composite session",
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "{{baseUrl}}/api/eventhub/tachograph-composite-sessions/{{compositeSessionId}}",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "api",
+ "eventhub",
+ "tachograph-composite-sessions",
+ "{{compositeSessionId}}"
+ ]
+ }
+ }
+ },
+ {
+ "name": "List tachograph composite session drivers",
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "{{baseUrl}}/api/eventhub/tachograph-composite-sessions/{{compositeSessionId}}/drivers",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "api",
+ "eventhub",
+ "tachograph-composite-sessions",
+ "{{compositeSessionId}}",
+ "drivers"
+ ]
+ }
+ }
+ },
+ {
+ "name": "Load tachograph composite driver events",
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "{{baseUrl}}/api/eventhub/tachograph-composite-sessions/{{compositeSessionId}}/drivers/{{driverKey}}/events",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "api",
+ "eventhub",
+ "tachograph-composite-sessions",
+ "{{compositeSessionId}}",
+ "drivers",
+ "{{driverKey}}",
+ "events"
+ ]
+ }
+ }
+ },
+ {
+ "name": "Load tachograph composite driver timeline",
+ "request": {
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "{{baseUrl}}/api/eventhub/tachograph-composite-sessions/{{compositeSessionId}}/drivers/{{driverKey}}/timeline",
+ "host": [
+ "{{baseUrl}}"
+ ],
+ "path": [
+ "api",
+ "eventhub",
+ "tachograph-composite-sessions",
+ "{{compositeSessionId}}",
+ "drivers",
+ "{{driverKey}}",
+ "timeline"
+ ]
+ }
+ }
+ }
+ ]
}
],
"variable": [
@@ -670,6 +785,18 @@
"key": "sessionId",
"value": "00000000-0000-0000-0000-000000000000"
},
+ {
+ "key": "additionalSessionId",
+ "value": "00000000-0000-0000-0000-000000000001"
+ },
+ {
+ "key": "compositeSessionId",
+ "value": "00000000-0000-0000-0000-000000000100"
+ },
+ {
+ "key": "compositeSessionLabel",
+ "value": "driver-multi-file sample"
+ },
{
"key": "driverKey",
"value": "12:12345678901200"
diff --git a/src/main/java/at/procon/eventhub/config/JacksonConfig.java b/src/main/java/at/procon/eventhub/config/JacksonConfig.java
index ce6a3ad..6f08fec 100644
--- a/src/main/java/at/procon/eventhub/config/JacksonConfig.java
+++ b/src/main/java/at/procon/eventhub/config/JacksonConfig.java
@@ -1,6 +1,8 @@
package at.procon.eventhub.config;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -11,7 +13,9 @@ public class JacksonConfig {
@Bean
@ConditionalOnMissingBean(ObjectMapper.class)
public ObjectMapper objectMapper() {
- return new ObjectMapper().findAndRegisterModules();
+ return new ObjectMapper()
+ .registerModule(new JavaTimeModule())
+ .findAndRegisterModules()
+ .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}
}
-
diff --git a/src/main/java/at/procon/eventhub/persistence/EventHubEventReadRepository.java b/src/main/java/at/procon/eventhub/persistence/EventHubEventReadRepository.java
index c4595fc..7fee1b5 100644
--- a/src/main/java/at/procon/eventhub/persistence/EventHubEventReadRepository.java
+++ b/src/main/java/at/procon/eventhub/persistence/EventHubEventReadRepository.java
@@ -442,16 +442,34 @@ public class EventHubEventReadRepository {
return Integer.parseInt(value.toString());
}
- private JsonNode json(String value) {
+ static JsonNode parseJsonColumn(ObjectMapper objectMapper, String value) {
try {
- return value == null || value.isBlank()
+ JsonNode node = value == null || value.isBlank()
? objectMapper.createObjectNode()
: objectMapper.readTree(value);
+ while (node != null
+ && node.isTextual()
+ && looksLikeEmbeddedJson(node.textValue())) {
+ node = objectMapper.readTree(node.textValue());
+ }
+ return node;
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("Failed to parse JSON column.", e);
}
}
+ private JsonNode json(String value) {
+ return parseJsonColumn(objectMapper, value);
+ }
+
+ private static boolean looksLikeEmbeddedJson(String value) {
+ if (value == null) {
+ return false;
+ }
+ String trimmed = value.trim();
+ return trimmed.startsWith("{") || trimmed.startsWith("[");
+ }
+
private String syntheticId(String prefix, UUID id) {
return id == null ? null : prefix + ":" + id;
}
diff --git a/src/main/java/at/procon/eventhub/tachographfilesession/api/TachographFileSessionExceptionHandler.java b/src/main/java/at/procon/eventhub/tachographfilesession/api/TachographFileSessionExceptionHandler.java
index 34e6962..abe140c 100644
--- a/src/main/java/at/procon/eventhub/tachographfilesession/api/TachographFileSessionExceptionHandler.java
+++ b/src/main/java/at/procon/eventhub/tachographfilesession/api/TachographFileSessionExceptionHandler.java
@@ -1,8 +1,10 @@
package at.procon.eventhub.tachographfilesession.api;
import at.procon.eventhub.tachographfilesession.service.DriverNotFoundInSessionException;
+import at.procon.eventhub.tachographfilesession.service.DriverNotFoundInCompositeSessionException;
import at.procon.eventhub.tachographfilesession.service.LegalRequirementsUploadException;
import at.procon.eventhub.tachographfilesession.service.LegalRequirementsXmlDownloadException;
+import at.procon.eventhub.tachographfilesession.service.TachographCompositeSessionNotFoundException;
import at.procon.eventhub.tachographfilesession.service.TachographFileSessionNotFoundException;
import at.procon.eventhub.tachographfilesession.service.TachographXmlValidationException;
import at.procon.eventhub.tachographfilesession.service.UnsupportedTachographFileTypeException;
@@ -13,12 +15,17 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
-@RestControllerAdvice(basePackageClasses = TachographFileSessionController.class)
+@RestControllerAdvice(basePackageClasses = {
+ TachographFileSessionController.class,
+ TachographCompositeSessionController.class
+})
public class TachographFileSessionExceptionHandler {
@ExceptionHandler({
TachographFileSessionNotFoundException.class,
- DriverNotFoundInSessionException.class
+ TachographCompositeSessionNotFoundException.class,
+ DriverNotFoundInSessionException.class,
+ DriverNotFoundInCompositeSessionException.class
})
public ResponseEntity