Skip to content

Commit

Permalink
Merge pull request #5 from netz39/timestamp
Browse files Browse the repository at this point in the history
🔨 Refactor API to use ISO 8601 timestamps
  • Loading branch information
penguineer authored Aug 26, 2022
2 parents a60b8a0 + a5c5c45 commit 653a806
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 15 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ Configuration is done using environment variables:

### Pulse Message

Pulses are encoded as messages with a [UNIX timestamp](https://www.unixtimestamp.com/) in the JSON form
Pulses are encoded as messages with a [ISO 8601 timestamp](https://en.wikipedia.org/wiki/ISO_8601) in the JSON form
```json
{
"timestamp": 1234567890
"timestamp": "2022-08-23T16:54:23Z"
}
```

Expand Down
4 changes: 4 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@
<artifactId>micronaut-jackson-databind</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>io.micronaut.rabbitmq</groupId>
<artifactId>micronaut-rabbitmq</artifactId>
Expand Down
12 changes: 8 additions & 4 deletions src/main/java/de/netz39/svc/pwrMtrPlsGw/PulseMessage.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package de.netz39.svc.pwrMtrPlsGw;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.micronaut.context.annotation.Bean;
import net.jcip.annotations.Immutable;

import java.time.Instant;

/**
* Bean representation of a pulse message.
*
Expand All @@ -17,18 +20,19 @@
@Immutable
@Bean
public class PulseMessage {
static PulseMessage withTimestamp(final long timestamp) {
static PulseMessage withTimestamp(final Instant timestamp) {
return new PulseMessage(timestamp);
}

@JsonProperty("timestamp")
private final long timestamp;
@JsonFormat(shape = JsonFormat.Shape.STRING)
private final Instant timestamp;

PulseMessage(@JsonProperty(value="timestamp", required = true) long timestamp) {
PulseMessage(@JsonProperty(value="timestamp", required = true) Instant timestamp) {
this.timestamp = timestamp;
}

public long getTimestamp() {
public Instant getTimestamp() {
return timestamp;
}
}
10 changes: 6 additions & 4 deletions src/test/java/de/netz39/svc/pwrMtrPlsGw/TestPulseEndpoint.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.time.Instant;

import static org.junit.jupiter.api.Assertions.*;

@Singleton
Expand Down Expand Up @@ -53,7 +55,7 @@ public void resetAmqpTestEmitter() {

@Test
public void testValid() {
final PulseMessage msg = PulseMessage.withTimestamp(0);
final PulseMessage msg = PulseMessage.withTimestamp(Instant.EPOCH);
final HttpRequest<PulseMessage> req = HttpRequest.POST("/pulse", msg);
assertDoesNotThrow(
() -> client.toBlocking().exchange(req)
Expand All @@ -80,7 +82,7 @@ public void testInvalidBody() {
public void testMissingRabbitMQ() {
AmqpTestEmitter.except = new RabbitClientException("Test Exception");

final PulseMessage msg = PulseMessage.withTimestamp(0);
final PulseMessage msg = PulseMessage.withTimestamp(Instant.EPOCH);
final HttpRequest<PulseMessage> req = HttpRequest.POST("/pulse", msg);

final HttpClientResponseException e = assertThrows(
Expand All @@ -93,7 +95,7 @@ public void testMissingRabbitMQ() {
@Test
@Property(name = "api-token", value = "abc")
public void TestValidAuth() {
final PulseMessage msg = PulseMessage.withTimestamp(0);
final PulseMessage msg = PulseMessage.withTimestamp(Instant.EPOCH);
final MutableHttpRequest<PulseMessage> req = HttpRequest.POST("/pulse", msg).bearerAuth("abc");
assertDoesNotThrow(
() -> client.toBlocking().exchange(req)
Expand All @@ -105,7 +107,7 @@ public void TestValidAuth() {
@Test
@Property(name = "api-token", value = "abc")
public void TestInvalidAuth() {
final PulseMessage msg = PulseMessage.withTimestamp(0);
final PulseMessage msg = PulseMessage.withTimestamp(Instant.EPOCH);
final MutableHttpRequest<PulseMessage> req = HttpRequest.POST("/pulse", msg);
final HttpClientResponseException e = assertThrows(
HttpClientResponseException.class,
Expand Down
15 changes: 10 additions & 5 deletions src/test/java/de/netz39/svc/pwrMtrPlsGw/TestPulseMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import org.junit.jupiter.api.Test;

import java.time.Instant;
import java.util.Arrays;

import static org.junit.jupiter.api.Assertions.*;
Expand All @@ -13,7 +15,7 @@
public class TestPulseMessage {
@Test
public void testConstructor() {
for (final long timestamp: Arrays.asList(-1L, 0L, 1660739950000L)){
for (final Instant timestamp: Arrays.asList(Instant.EPOCH, Instant.now())){
final PulseMessage pm = PulseMessage.withTimestamp(timestamp);
assertNotNull(pm);
assertEquals(timestamp, pm.getTimestamp());
Expand All @@ -23,26 +25,29 @@ public void testConstructor() {
@Test
public void testSerialization() {
ObjectMapper mapper = new ObjectMapper();
for (final long timestamp: Arrays.asList(-1L, 0L, 1660739950000L)) {
mapper.registerModule(new JavaTimeModule());

for (final Instant timestamp: Arrays.asList(Instant.EPOCH, Instant.now())){
// Test a valid JSON input
final PulseMessage msg = PulseMessage.withTimestamp(timestamp);
String json = assertDoesNotThrow(
() -> mapper.writeValueAsString(msg)
);
assertNotNull(json);
assertEquals("{\"timestamp\":"+timestamp+"}", json);
assertEquals("{\"timestamp\":\""+timestamp+"\"}", json);
}

}

@Test
public void testDeserialization() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());

for (final long timestamp: Arrays.asList(-1L, 0L, 1660739950000L)) {
for (final Instant timestamp: Arrays.asList(Instant.EPOCH, Instant.now())){
// Test a valid JSON input
final PulseMessage msg = assertDoesNotThrow(
() -> mapper.readValue("{\"timestamp\":"+timestamp+"}",
() -> mapper.readValue("{\"timestamp\":\""+timestamp+"\"}",
PulseMessage.class)
);
assertNotNull(msg);
Expand Down

0 comments on commit 653a806

Please sign in to comment.