Permalink
Browse files

Fixes deserialization of Event instances from json

  • Loading branch information...
1 parent 234c97d commit 056d0e821907193632c21c50349ebf29d9face38 @sagemintblue sagemintblue committed Apr 5, 2013
@@ -26,6 +26,7 @@
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.google.common.base.Objects;
import com.twitter.ambrose.util.JSONUtil;
@@ -70,6 +71,28 @@ public synchronized void setSuccessors(Collection<DAGNode<? extends Job>> succes
public synchronized Collection<String> getSuccessorNames() { return successorNames; }
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(name, job, successorNames);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ DAGNode<?> that = (DAGNode<?>) obj;
+ return Objects.equal(name, that.name)
+ && Objects.equal(job, that.job)
+ && Objects.equal(successorNames, that.successorNames);
+ }
+
public String toJson() throws IOException {
return JSONUtil.toJson(this);
}
@@ -15,20 +15,20 @@
*/
package com.twitter.ambrose.model;
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonSubTypes;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.fasterxml.jackson.annotation.JsonTypeName;
-import com.twitter.ambrose.util.JSONUtil;
-
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.core.type.TypeReference;
+import com.twitter.ambrose.util.JSONUtil;
+
/**
* Class that represents a Event of a given Type. Each one of these created will have
* a unique id that increments up for each object. eventIds will always be >= 0.
@@ -37,52 +37,52 @@
* @author billg
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
-@JsonTypeName("default")
@JsonSubTypes({
- @JsonSubTypes.Type(value=com.twitter.ambrose.model.Event.class, name="default"),
- @JsonSubTypes.Type(value=com.twitter.ambrose.model.Event.JobStartedEvent.class, name="job_started"),
+ @JsonSubTypes.Type(value=Event.WorkflowProgressEvent.class, name="WORKFLOW_PROGRESS"),
+ @JsonSubTypes.Type(value=Event.JobStartedEvent.class, name="JOB_STARTED"),
+ @JsonSubTypes.Type(value=Event.JobProgressEvent.class, name="JOB_PROGRESS"),
+ @JsonSubTypes.Type(value=Event.JobFinishedEvent.class, name="JOB_FINISHED"),
+ @JsonSubTypes.Type(value=Event.JobFailedEvent.class, name="JOB_FAILED")
})
public class Event<T> {
private static AtomicInteger NEXT_ID = new AtomicInteger();
- public static enum Type { JOB_STARTED, JOB_FINISHED, JOB_FAILED, JOB_PROGRESS, WORKFLOW_PROGRESS};
+ public static enum Type { JOB_STARTED, JOB_FINISHED, JOB_FAILED, JOB_PROGRESS, WORKFLOW_PROGRESS }
public static enum WorkflowProgressField {
- workflowProgress;
+ workflowProgress
}
- private long timestamp;
private int id;
+ @JsonIgnore
private Type type;
+ private long timestamp;
private T payload;
- protected Event(Type type) { this.type = type; }
-
- private Event(Type type, T payload) {
- this.id = NEXT_ID.incrementAndGet();
- this.timestamp = System.currentTimeMillis();
+ public Event(int eventId, Type type, long timestamp, T payload) {
+ this.id = eventId;
this.type = type;
+ this.timestamp = timestamp;
this.payload = payload;
}
- public Event(int eventId, long timestamp, Type type, T payload) {
- this.id = eventId;
- this.timestamp = timestamp;
- this.type = type;
- this.payload = payload;
+ private Event(Type type, T payload) {
+ this(NEXT_ID.incrementAndGet(), type, System.currentTimeMillis(), payload);
}
- public long getTimestamp() { return timestamp; }
+ public Event() {}
+
public int getId() { return id; }
public Type getType() { return type; }
+ public long getTimestamp() { return timestamp; }
public T getPayload() { return payload; }
public String toJson() throws IOException {
return JSONUtil.toJson(this);
}
public static Event<?> fromJson(String json) throws IOException {
- return JSONUtil.toObject(json, new TypeReference<Event<?>>() { });
+ return JSONUtil.toObject(json, new TypeReference<Event<?>>() {});
}
/**
@@ -111,43 +111,41 @@ public static Event create(Type type, Object data) {
}
}
- @JsonTypeName("job_started")
public static class JobStartedEvent extends Event<DAGNode<? extends Job>> {
@JsonCreator
- public JobStartedEvent() { super(Type.JOB_STARTED); }
-
- public JobStartedEvent(DAGNode<? extends Job> eventData) {
- super(Type.JOB_STARTED, eventData);
+ public JobStartedEvent(@JsonProperty("payload") DAGNode<? extends Job> payload) {
+ super(Type.JOB_STARTED, payload);
}
}
public static class JobProgressEvent extends Event<DAGNode<? extends Job>> {
-
-
- public JobProgressEvent(@JsonProperty("payload") DAGNode<? extends Job> eventData) {
- super(Type.JOB_PROGRESS, eventData);
+ @JsonCreator
+ public JobProgressEvent(@JsonProperty("payload") DAGNode<? extends Job> payload) {
+ super(Type.JOB_PROGRESS, payload);
}
}
public static class JobFinishedEvent extends Event<DAGNode<? extends Job>> {
- public JobFinishedEvent(DAGNode<? extends Job> eventData) {
- super(Type.JOB_FINISHED, eventData);
+ @JsonCreator
+ public JobFinishedEvent(@JsonProperty("payload") DAGNode<? extends Job> payload) {
+ super(Type.JOB_FINISHED, payload);
}
}
public static class JobFailedEvent extends Event<DAGNode<? extends Job>> {
- public JobFailedEvent(DAGNode<? extends Job> eventData) {
- super(Type.JOB_FAILED, eventData);
+ @JsonCreator
+ public JobFailedEvent(@JsonProperty("payload") DAGNode<? extends Job> payload) {
+ super(Type.JOB_FAILED, payload);
}
}
public static class WorkflowProgressEvent extends Event<Map<WorkflowProgressField, String>> {
- public WorkflowProgressEvent(Map<WorkflowProgressField, String> eventData) {
- super(Type.WORKFLOW_PROGRESS, eventData);
+ @JsonCreator
+ public WorkflowProgressEvent(@JsonProperty("payload") Map<WorkflowProgressField, String> payload) {
+ super(Type.WORKFLOW_PROGRESS, payload);
}
}
- @SuppressWarnings("unchecked")
public static void main(String[] args) throws IOException {
String json = JSONUtil.readFile("pig/src/main/resources/web/data/small-events.json");
List<Event> events = JSONUtil.toObject(json, new TypeReference<List<Event>>() { });
@@ -22,6 +22,8 @@
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.core.type.TypeReference;
+import com.google.common.base.Objects;
+
import com.twitter.ambrose.util.JSONUtil;
import java.io.IOException;
@@ -36,9 +38,8 @@
* @author billg
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "runtime")
-@JsonTypeName("default")
@JsonSubTypes({
- @JsonSubTypes.Type(value=com.twitter.ambrose.model.Job.class, name="default"),
+ @JsonSubTypes.Type(value=com.twitter.ambrose.model.Job.class, name="default")
})
public class Job {
private String id;
@@ -49,8 +50,8 @@ protected Job() { }
@JsonCreator
public Job(@JsonProperty("id") String id,
- @JsonProperty("metrics") Map<String, Number> metrics,
- @JsonProperty("configuration") Properties configuration) {
+ @JsonProperty("configuration") Properties configuration,
+ @JsonProperty("metrics") Map<String, Number> metrics) {
this.id = id;
this.metrics = metrics;
this.configuration = configuration;
@@ -65,6 +66,28 @@ public Job(@JsonProperty("id") String id,
public Map<String, Number> getMetrics() { return metrics; }
protected void setMetrics(Map<String, Number> metrics) { this.metrics = metrics; }
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(id, configuration, metrics);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ Job that = (Job) obj;
+ return Objects.equal(id, that.id)
+ && Objects.equal(configuration, that.configuration)
+ && Objects.equal(metrics, that.metrics);
+ }
+
public String toJson() throws IOException {
return JSONUtil.toJson(this);
}
@@ -29,6 +29,7 @@
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
@@ -85,6 +86,10 @@ public static String toJson(Object object) throws IOException {
return mapper.readValue(json, type);
}
+ public static <T> T toObject(String json, JavaType type) throws IOException {
+ return mapper.readValue(json, type);
+ }
+
public static String readFile(String path) throws IOException {
FileInputStream stream = new FileInputStream(new File(path));
try {
@@ -11,18 +11,16 @@
* Unit tests for {@link DAGNodeTest}.
*/
public class DAGNodeTest {
-
private void testRoundTrip(DAGNode expected) throws IOException {
String asJson = expected.toJson();
DAGNode asDAGNodeAgain = DAGNode.fromJson(asJson);
assertEquals(expected.getName(), asDAGNodeAgain.getName());
assertNotNull(asDAGNodeAgain.getJob());
- ModelTestUtils.assertJobEquals(expected.getJob(), asDAGNodeAgain.getJob());
+ assertEquals(expected.getJob(), asDAGNodeAgain.getJob());
}
@Test
public void testRoundTrip() throws IOException {
- DAGNode<Job> node = new DAGNode<Job>("dag name", new Job("scope-123", null, null));
- testRoundTrip(node);
+ testRoundTrip(new DAGNode<Job>("dag name", new Job("scope-123", null, null)));
}
}
@@ -1,10 +1,11 @@
package com.twitter.ambrose.model;
import java.io.IOException;
-import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
+import com.google.common.collect.Maps;
+
import org.junit.Test;
import static org.junit.Assert.assertEquals;
@@ -14,28 +15,25 @@
* Unit tests for {@link EventTest}.
*/
public class EventTest {
-
private void testRoundTrip(Event expected) throws IOException {
String asJson = expected.toJson();
+ System.out.println(asJson);
Event asEventAgain = Event.fromJson(asJson);
assertEquals(expected.getId(), asEventAgain.getId());
assertEquals(expected.getType(), asEventAgain.getType());
assertEquals(expected.getTimestamp(), asEventAgain.getTimestamp());
assertTrue(asEventAgain.getPayload() instanceof DAGNode);
assertEquals(expected.getPayload(), asEventAgain.getPayload());
- ModelTestUtils.assertJobEquals((Job)expected.getPayload(), (Job)asEventAgain.getPayload());
}
@Test
public void testRoundTrip() throws IOException {
- Map<String, Number> metrics = new HashMap<String, Number>();
- metrics.put("somemetric", 6);
Properties properties = new Properties();
properties.setProperty("someprop", "propvalue");
- Job job = new Job("scope-123", metrics, properties);
-
+ Map<String, Number> metrics = Maps.newHashMap();
+ metrics.put("somemetric", 6);
+ Job job = new Job("scope-123", properties, metrics);
DAGNode<Job> node = new DAGNode<Job>("dag name", job);
-
testRoundTrip(new Event.JobStartedEvent(node));
}
-}
+}
@@ -7,25 +7,27 @@
import java.util.Map;
import java.util.Properties;
+import com.google.common.collect.Maps;
+
+import static org.junit.Assert.assertEquals;
+
/**
* Unit tests for {@link com.twitter.ambrose.model.JobTest}.
*/
public class JobTest {
-
private void testRoundTrip(Job expected) throws IOException {
String asJson = expected.toJson();
Job asJobAgain = Job.fromJson(asJson);
- ModelTestUtils.assertJobEquals(expected, asJobAgain);
+ assertEquals(expected, asJobAgain);
}
@Test
public void testRoundTrip() throws IOException {
- Map<String, Number> metrics = new HashMap<String, Number>();
- metrics.put("somemetric", 6);
Properties properties = new Properties();
properties.setProperty("someprop", "propvalue");
- Job job = new Job("scope-123", metrics, properties);
-
+ Map<String, Number> metrics = Maps.newHashMap();
+ metrics.put("somemetric", 6);
+ Job job = new Job("scope-123", properties, metrics);
testRoundTrip(job);
}
}
@@ -89,7 +89,6 @@ public void testGetEventsSince() throws IOException {
private void assertEqualWorkflows(Event expected, Event found) {
assertEquals("Wrong eventId found", expected.getId(), found.getId());
- assertEquals("Wrong eventType found", expected.getType(), found.getType());
assertEquals("Wrong eventData found", expected.getPayload(), found.getPayload());
}
}

0 comments on commit 056d0e8

Please sign in to comment.