diff --git a/CHANGELOG.md b/CHANGELOG.md
index de32017..150eeb2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,14 @@
## unreleased
+### Deprecations
+* `get...TimeString()` methods on various model classes are now deprecated
+
### Fix
* Fixed JSON type conversion in `SecretResponse#get(String, Class)` (#67)
+### Improvements
+* Parse timestamps as `ZonedDateTime` instead of `String` representation
+
## 1.1.4 (2023-06-15)
diff --git a/pom.xml b/pom.xml
index 458a141..e4fd371 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
de.stklcode.jvault
jvault-connector
- 1.1.5-SNAPSHOT
+ 1.2.0-SNAPSHOT
jar
@@ -51,6 +51,11 @@
jackson-databind
2.15.2
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+ 2.15.2
+
org.junit.jupiter
@@ -170,6 +175,7 @@
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.model.response=ALL-UNNAMED
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.model.response.embedded=ALL-UNNAMED
--add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.test=com.fasterxml.jackson.databind
+ --add-opens de.stklcode.jvault.connector/de.stklcode.jvault.connector.test=com.fasterxml.jackson.datatype.jsr310
diff --git a/src/main/java/de/stklcode/jvault/connector/internal/RequestHelper.java b/src/main/java/de/stklcode/jvault/connector/internal/RequestHelper.java
index 724640f..ec047dc 100644
--- a/src/main/java/de/stklcode/jvault/connector/internal/RequestHelper.java
+++ b/src/main/java/de/stklcode/jvault/connector/internal/RequestHelper.java
@@ -1,7 +1,10 @@
package de.stklcode.jvault.connector.internal;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import de.stklcode.jvault.connector.exception.*;
import de.stklcode.jvault.connector.model.response.ErrorResponse;
@@ -62,7 +65,10 @@ public final class RequestHelper implements Serializable {
this.timeout = timeout;
this.tlsVersion = tlsVersion;
this.trustedCaCert = trustedCaCert;
- this.jsonMapper = new ObjectMapper();
+ this.jsonMapper = new ObjectMapper()
+ .registerModule(new JavaTimeModule())
+ .enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
+ .disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
}
/**
diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/SecretResponse.java b/src/main/java/de/stklcode/jvault/connector/model/response/SecretResponse.java
index c50a301..b256371 100644
--- a/src/main/java/de/stklcode/jvault/connector/model/response/SecretResponse.java
+++ b/src/main/java/de/stklcode/jvault/connector/model/response/SecretResponse.java
@@ -17,7 +17,10 @@
package de.stklcode.jvault.connector.model.response;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import de.stklcode.jvault.connector.exception.InvalidResponseException;
import de.stklcode.jvault.connector.model.response.embedded.VersionMetadata;
@@ -82,7 +85,11 @@ public abstract class SecretResponse extends VaultDataResponse {
} else if (type.isInstance(rawValue)) {
return type.cast(rawValue);
} else {
- var om = new ObjectMapper();
+ var om = new ObjectMapper()
+ .registerModule(new JavaTimeModule())
+ .enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
+ .disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
+
if (rawValue instanceof String) {
return om.readValue((String) rawValue, type);
} else {
diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/SecretMetadata.java b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/SecretMetadata.java
index 2773bcb..503aaad 100644
--- a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/SecretMetadata.java
+++ b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/SecretMetadata.java
@@ -22,7 +22,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
-import java.time.format.DateTimeParseException;
import java.util.Map;
import java.util.Objects;
@@ -35,13 +34,13 @@ import java.util.Objects;
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public final class SecretMetadata implements Serializable {
- private static final long serialVersionUID = 1684891108903409038L;
+ private static final long serialVersionUID = -4967896264361344676L;
private static final DateTimeFormatter TIME_FORMAT =
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSXXX");
@JsonProperty("created_time")
- private String createdTimeString;
+ private ZonedDateTime createdTime;
@JsonProperty("current_version")
private Integer currentVersion;
@@ -53,31 +52,29 @@ public final class SecretMetadata implements Serializable {
private Integer oldestVersion;
@JsonProperty("updated_time")
- private String updatedTime;
+ private ZonedDateTime updatedTime;
@JsonProperty("versions")
private Map versions;
/**
* @return Time of secret creation as raw string representation.
+ * @deprecated Method left for backwards compatibility only. Use {@link #getCreatedTime()} instead.
*/
+ @Deprecated(since = "1.2", forRemoval = true)
public String getCreatedTimeString() {
- return createdTimeString;
+ if (createdTime != null) {
+ return TIME_FORMAT.format(createdTime);
+ }
+
+ return null;
}
/**
* @return Time of secret creation.
*/
public ZonedDateTime getCreatedTime() {
- if (createdTimeString != null && !createdTimeString.isEmpty()) {
- try {
- return ZonedDateTime.parse(createdTimeString, TIME_FORMAT);
- } catch (DateTimeParseException e) {
- // Ignore.
- }
- }
-
- return null;
+ return createdTime;
}
/**
@@ -103,26 +100,24 @@ public final class SecretMetadata implements Serializable {
/**
* @return Time of secret update as raw string representation.
+ * @deprecated Method left for backwards compatibility only. Use {@link #getUpdatedTime()} instead.
*/
+ @Deprecated(since = "1.2", forRemoval = true)
public String getUpdatedTimeString() {
- return updatedTime;
- }
-
- /**
- * @return Time of secret update..
- */
- public ZonedDateTime getUpdatedTime() {
- if (updatedTime != null && !updatedTime.isEmpty()) {
- try {
- return ZonedDateTime.parse(updatedTime, TIME_FORMAT);
- } catch (DateTimeParseException e) {
- // Ignore.
- }
+ if (updatedTime != null) {
+ return TIME_FORMAT.format(updatedTime);
}
return null;
}
+ /**
+ * @return Time of secret update.
+ */
+ public ZonedDateTime getUpdatedTime() {
+ return updatedTime;
+ }
+
/**
* @return Version of the entry.
*/
@@ -138,7 +133,7 @@ public final class SecretMetadata implements Serializable {
return false;
}
SecretMetadata that = (SecretMetadata) o;
- return Objects.equals(createdTimeString, that.createdTimeString) &&
+ return Objects.equals(createdTime, that.createdTime) &&
Objects.equals(currentVersion, that.currentVersion) &&
Objects.equals(maxVersions, that.maxVersions) &&
Objects.equals(oldestVersion, that.oldestVersion) &&
@@ -148,6 +143,6 @@ public final class SecretMetadata implements Serializable {
@Override
public int hashCode() {
- return Objects.hash(createdTimeString, currentVersion, maxVersions, oldestVersion, updatedTime, versions);
+ return Objects.hash(createdTime, currentVersion, maxVersions, oldestVersion, updatedTime, versions);
}
}
diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/TokenData.java b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/TokenData.java
index 39d6de1..a7d5fda 100644
--- a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/TokenData.java
+++ b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/TokenData.java
@@ -21,6 +21,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -34,7 +35,10 @@ import java.util.Objects;
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public final class TokenData implements Serializable {
- private static final long serialVersionUID = 2915180734313753649L;
+ private static final long serialVersionUID = -5749716740973138916L;
+
+ private static final DateTimeFormatter TIME_FORMAT =
+ DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSXXX");
@JsonProperty("accessor")
private String accessor;
@@ -52,7 +56,7 @@ public final class TokenData implements Serializable {
private String entityId;
@JsonProperty("expire_time")
- private String expireTime;
+ private ZonedDateTime expireTime;
@JsonProperty("explicit_max_ttl")
private Integer explicitMaxTtl;
@@ -61,7 +65,7 @@ public final class TokenData implements Serializable {
private String id;
@JsonProperty("issue_time")
- private String issueTime;
+ private ZonedDateTime issueTime;
@JsonProperty("meta")
private Map meta;
@@ -126,9 +130,15 @@ public final class TokenData implements Serializable {
/**
* @return Expire time as raw string value
* @since 0.9
+ * @deprecated Method left for backwards compatibility only. Use {@link #getExpireTime()} instead.
*/
+ @Deprecated(since = "1.2", forRemoval = true)
public String getExpireTimeString() {
- return expireTime;
+ if (expireTime != null) {
+ return TIME_FORMAT.format(expireTime);
+ }
+
+ return null;
}
/**
@@ -136,11 +146,7 @@ public final class TokenData implements Serializable {
* @since 0.9
*/
public ZonedDateTime getExpireTime() {
- if (expireTime == null) {
- return null;
- } else {
- return ZonedDateTime.parse(expireTime);
- }
+ return expireTime;
}
/**
@@ -161,9 +167,15 @@ public final class TokenData implements Serializable {
/**
* @return Issue time as raw string value
* @since 0.9
+ * @deprecated Method left for backwards compatibility only. Use {@link #getIssueTime()} instead.
*/
+ @Deprecated(since = "1.2", forRemoval = true)
public String getIssueTimeString() {
- return issueTime;
+ if (issueTime != null) {
+ return TIME_FORMAT.format(issueTime);
+ }
+
+ return null;
}
/**
@@ -171,11 +183,7 @@ public final class TokenData implements Serializable {
* @since 0.9
*/
public ZonedDateTime getIssueTime() {
- if (issueTime == null) {
- return null;
- } else {
- return ZonedDateTime.parse(issueTime);
- }
+ return issueTime;
}
/**
diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/VersionMetadata.java b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/VersionMetadata.java
index be9f3f9..5f1d3d1 100644
--- a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/VersionMetadata.java
+++ b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/VersionMetadata.java
@@ -22,7 +22,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
-import java.time.format.DateTimeParseException;
import java.util.Objects;
/**
@@ -34,16 +33,16 @@ import java.util.Objects;
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public final class VersionMetadata implements Serializable {
- private static final long serialVersionUID = -5286693953873839611L;
+ private static final long serialVersionUID = -6815731513868586713L;
private static final DateTimeFormatter TIME_FORMAT =
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSSXXX");
@JsonProperty("created_time")
- private String createdTimeString;
+ private ZonedDateTime createdTime;
@JsonProperty("deletion_time")
- private String deletionTimeString;
+ private ZonedDateTime deletionTime;
@JsonProperty("destroyed")
private boolean destroyed;
@@ -53,46 +52,42 @@ public final class VersionMetadata implements Serializable {
/**
* @return Time of secret creation as raw string representation.
+ * @deprecated Method left for backwards compatibility only. Use {@link #getCreatedTime()} instead.
*/
+ @Deprecated(since = "1.2", forRemoval = true)
public String getCreatedTimeString() {
- return createdTimeString;
+ if (createdTime != null) {
+ return TIME_FORMAT.format(createdTime);
+ }
+
+ return null;
}
/**
* @return Time of secret creation.
*/
public ZonedDateTime getCreatedTime() {
- if (createdTimeString != null && !createdTimeString.isEmpty()) {
- try {
- return ZonedDateTime.parse(createdTimeString, TIME_FORMAT);
- } catch (DateTimeParseException e) {
- // Ignore.
- }
- }
-
- return null;
+ return createdTime;
}
/**
* @return Time for secret deletion as raw string representation.
+ * @deprecated Method left for backwards compatibility only. Use {@link #getDeletionTime()} instead.
*/
+ @Deprecated(since = "1.2", forRemoval = true)
public String getDeletionTimeString() {
- return deletionTimeString;
+ if (deletionTime != null) {
+ return TIME_FORMAT.format(deletionTime);
+ }
+
+ return null;
}
/**
* @return Time for secret deletion.
*/
public ZonedDateTime getDeletionTime() {
- if (deletionTimeString != null && !deletionTimeString.isEmpty()) {
- try {
- return ZonedDateTime.parse(deletionTimeString, TIME_FORMAT);
- } catch (DateTimeParseException e) {
- // Ignore.
- }
- }
-
- return null;
+ return deletionTime;
}
/**
@@ -118,13 +113,13 @@ public final class VersionMetadata implements Serializable {
}
VersionMetadata that = (VersionMetadata) o;
return destroyed == that.destroyed &&
- Objects.equals(createdTimeString, that.createdTimeString) &&
- Objects.equals(deletionTimeString, that.deletionTimeString) &&
+ Objects.equals(createdTime, that.createdTime) &&
+ Objects.equals(deletionTime, that.deletionTime) &&
Objects.equals(version, that.version);
}
@Override
public int hashCode() {
- return Objects.hash(createdTimeString, deletionTimeString, destroyed, version);
+ return Objects.hash(createdTime, deletionTime, destroyed, version);
}
}
diff --git a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/WrapInfo.java b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/WrapInfo.java
index d89eee4..64ebeb5 100644
--- a/src/main/java/de/stklcode/jvault/connector/model/response/embedded/WrapInfo.java
+++ b/src/main/java/de/stklcode/jvault/connector/model/response/embedded/WrapInfo.java
@@ -19,6 +19,7 @@ package de.stklcode.jvault.connector.model.response.embedded;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.Serializable;
+import java.time.ZonedDateTime;
import java.util.Objects;
/**
@@ -28,7 +29,7 @@ import java.util.Objects;
* @since 1.1
*/
public class WrapInfo implements Serializable {
- private static final long serialVersionUID = -7764500642913116581L;
+ private static final long serialVersionUID = 4864973237090355607L;
@JsonProperty("token")
private String token;
@@ -37,7 +38,7 @@ public class WrapInfo implements Serializable {
private Integer ttl;
@JsonProperty("creation_time")
- private String creationTime;
+ private ZonedDateTime creationTime;
@JsonProperty("creation_path")
private String creationPath;
@@ -59,7 +60,7 @@ public class WrapInfo implements Serializable {
/**
* @return Creation time
*/
- public String getCreationTime() {
+ public ZonedDateTime getCreationTime() {
return creationTime;
}
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index 1067c2a..42648bc 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -33,4 +33,5 @@ module de.stklcode.jvault.connector {
requires java.base;
requires java.net.http;
requires com.fasterxml.jackson.databind;
+ requires com.fasterxml.jackson.datatype.jsr310;
}
diff --git a/src/test/java/de/stklcode/jvault/connector/model/AbstractModelTest.java b/src/test/java/de/stklcode/jvault/connector/model/AbstractModelTest.java
index 0ea2bed..2974339 100644
--- a/src/test/java/de/stklcode/jvault/connector/model/AbstractModelTest.java
+++ b/src/test/java/de/stklcode/jvault/connector/model/AbstractModelTest.java
@@ -1,6 +1,9 @@
package de.stklcode.jvault.connector.model;
+import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import nl.jqno.equalsverifier.EqualsVerifier;
import org.junit.jupiter.api.Test;
@@ -26,7 +29,10 @@ public abstract class AbstractModelTest {
*/
protected AbstractModelTest(Class modelClass) {
this.modelClass = modelClass;
- this.objectMapper = new ObjectMapper();
+ this.objectMapper = new ObjectMapper()
+ .registerModule(new JavaTimeModule())
+ .enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
+ .disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
}
/**
diff --git a/src/test/java/de/stklcode/jvault/connector/model/response/MetaSecretResponseTest.java b/src/test/java/de/stklcode/jvault/connector/model/response/MetaSecretResponseTest.java
index bdc360e..42ffffc 100644
--- a/src/test/java/de/stklcode/jvault/connector/model/response/MetaSecretResponseTest.java
+++ b/src/test/java/de/stklcode/jvault/connector/model/response/MetaSecretResponseTest.java
@@ -109,7 +109,7 @@ class MetaSecretResponseTest extends AbstractModelTest {
assertNotNull(res.getMetadata(), "SecretResponse does not contain metadata");
assertEquals(SECRET_META_CREATED, res.getMetadata().getCreatedTimeString(), "Incorrect creation date string");
assertNotNull(res.getMetadata().getCreatedTime(), "Creation date parsing failed");
- assertEquals("", res.getMetadata().getDeletionTimeString(), "Incorrect deletion date string");
+ assertNull(res.getMetadata().getDeletionTimeString(), "Incorrect deletion date string");
assertNull(res.getMetadata().getDeletionTime(), "Incorrect deletion date");
assertFalse(res.getMetadata().isDestroyed(), "Secret destroyed when not expected");
assertEquals(1, res.getMetadata().getVersion(), "Incorrect secret version");