You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2016/02/13 13:31:06 UTC
[19/37] incubator-tinkerpop git commit: Improved GraphSON support of
java.time.* packages.
Improved GraphSON support of java.time.* packages.
Serialized all classes currently serialized by Gryo using ISO-8061 format. Using the embedded type option actually allow serialization back to java.time.* classes rather than coercing them to other types.
Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/cee96fdb
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/cee96fdb
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/cee96fdb
Branch: refs/heads/master
Commit: cee96fdb29fe354837845da961c0f6252e007b5a
Parents: e157514
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri Feb 12 08:11:42 2016 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Fri Feb 12 08:11:42 2016 -0500
----------------------------------------------------------------------
CHANGELOG.asciidoc | 2 +
.../structure/io/graphson/GraphSONModule.java | 47 ++-
.../io/graphson/GraphSONSerializers.java | 50 +--
.../io/graphson/JavaTimeSerializers.java | 326 +++++++++++++++++++
.../io/graphson/JavaUtilSerializers.java | 86 +++++
.../GraphSONMapperEmbeddedTypeTest.java | 134 ++++++++
.../io/graphson/GraphSONMapperTest.java | 133 ++++++++
.../structure/io/gryo/GryoMapperTest.java | 1 -
.../handler/HttpGremlinEndpointHandler.java | 18 +-
.../server/GremlinServerHttpIntegrateTest.java | 23 +-
10 files changed, 764 insertions(+), 56 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/cee96fdb/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index caccb0f..106639e 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,8 @@ image::https://raw.githubusercontent.com/apache/incubator-tinkerpop/master/docs/
TinkerPop 3.1.2 (NOT OFFICIALLY RELEASED YET)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* Added GraphSON serializers for the `java.time.*` classes.
+* Improved the logging of the Gremlin Server REST endpoint as it pertained to script execution failures.
* `TraversalExplanation` is now `Serializable` and registered with `GryoMapper`.
* Deprecated `ScriptElementFactory` and made the local `StarGraph` globally available for `ScriptInputFormat`'s `parse()` method.
* Optimized memory-usage in `TraversalVertexProgram`.
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/cee96fdb/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
index dba774e..ba9d9ac 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
@@ -27,6 +27,19 @@ import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.apache.tinkerpop.gremlin.structure.util.star.StarGraphGraphSONSerializer;
import org.apache.tinkerpop.shaded.jackson.databind.module.SimpleModule;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.MonthDay;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.Period;
+import java.time.Year;
+import java.time.YearMonth;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
import java.util.Map;
/**
@@ -55,6 +68,7 @@ abstract class GraphSONModule extends SimpleModule {
*/
protected GraphSONModuleV1d0(final boolean normalize) {
super("graphson-1.0");
+ // graph
addSerializer(Edge.class, new GraphSONSerializers.EdgeJacksonSerializer(normalize));
addSerializer(Vertex.class, new GraphSONSerializers.VertexJacksonSerializer(normalize));
addSerializer(VertexProperty.class, new GraphSONSerializers.VertexPropertyJacksonSerializer(normalize));
@@ -62,7 +76,38 @@ abstract class GraphSONModule extends SimpleModule {
addSerializer(TraversalMetrics.class, new GraphSONSerializers.TraversalMetricsJacksonSerializer());
addSerializer(Path.class, new GraphSONSerializers.PathJacksonSerializer());
addSerializer(StarGraphGraphSONSerializer.DirectionalStarGraph.class, new StarGraphGraphSONSerializer(normalize));
- addSerializer(Map.Entry.class, new GraphSONSerializers.MapEntryJacksonSerializer());
+
+ // java.util
+ addSerializer(Map.Entry.class, new JavaUtilSerializers.MapEntryJacksonSerializer());
+
+ // java.time
+ addSerializer(Duration.class, new JavaTimeSerializers.DurationJacksonSerializer());
+ addSerializer(Instant.class, new JavaTimeSerializers.InstantJacksonSerializer());
+ addSerializer(LocalDate.class, new JavaTimeSerializers.LocalDateJacksonSerializer());
+ addSerializer(LocalDateTime.class, new JavaTimeSerializers.LocalDateTimeJacksonSerializer());
+ addSerializer(LocalTime.class, new JavaTimeSerializers.LocalTimeJacksonSerializer());
+ addSerializer(MonthDay.class, new JavaTimeSerializers.MonthDayJacksonSerializer());
+ addSerializer(OffsetDateTime.class, new JavaTimeSerializers.OffsetDateTimeJacksonSerializer());
+ addSerializer(OffsetTime.class, new JavaTimeSerializers.OffsetTimeJacksonSerializer());
+ addSerializer(Period.class, new JavaTimeSerializers.PeriodJacksonSerializer());
+ addSerializer(Year.class, new JavaTimeSerializers.YearJacksonSerializer());
+ addSerializer(YearMonth.class, new JavaTimeSerializers.YearMonthJacksonSerializer());
+ addSerializer(ZonedDateTime.class, new JavaTimeSerializers.ZonedDateTimeJacksonSerializer());
+ addSerializer(ZoneOffset.class, new JavaTimeSerializers.ZoneOffsetJacksonSerializer());
+
+ addDeserializer(Duration.class, new JavaTimeSerializers.DurationJacksonDeserializer());
+ addDeserializer(Instant.class, new JavaTimeSerializers.InstantJacksonDeserializer());
+ addDeserializer(LocalDate.class, new JavaTimeSerializers.LocalDateJacksonDeserializer());
+ addDeserializer(LocalDateTime.class, new JavaTimeSerializers.LocalDateTimeJacksonDeserializer());
+ addDeserializer(LocalTime.class, new JavaTimeSerializers.LocalTimeJacksonDeserializer());
+ addDeserializer(MonthDay.class, new JavaTimeSerializers.MonthDayJacksonDeserializer());
+ addDeserializer(OffsetDateTime.class, new JavaTimeSerializers.OffsetDateTimeJacksonDeserializer());
+ addDeserializer(OffsetTime.class, new JavaTimeSerializers.OffsetTimeJacksonDeserializer());
+ addDeserializer(Period.class, new JavaTimeSerializers.PeriodJacksonDeserializer());
+ addDeserializer(Year.class, new JavaTimeSerializers.YearJacksonDeserializer());
+ addDeserializer(YearMonth.class, new JavaTimeSerializers.YearMonthJacksonDeserializer());
+ addDeserializer(ZonedDateTime.class, new JavaTimeSerializers.ZonedDateTimeJacksonDeserializer());
+ addDeserializer(ZoneOffset.class, new JavaTimeSerializers.ZoneOffsetJacksonDeserializer());
}
public static Builder build() {
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/cee96fdb/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializers.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializers.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializers.java
index 010ca74..5b2a8b7 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializers.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONSerializers.java
@@ -32,7 +32,6 @@ import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
import org.apache.tinkerpop.shaded.jackson.core.JsonGenerationException;
import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator;
import org.apache.tinkerpop.shaded.jackson.core.JsonProcessingException;
-import org.apache.tinkerpop.shaded.jackson.databind.SerializationFeature;
import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider;
import org.apache.tinkerpop.shaded.jackson.databind.jsontype.TypeSerializer;
import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdKeySerializer;
@@ -41,7 +40,6 @@ import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
-import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -49,7 +47,7 @@ import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
- * Class used to serialize graph-based objects such as vertices, edges, properties, and paths. These serializers
+ * GraphSON serializers for graph-based objects such as vertices, edges, properties, and paths. These serializers
* present a generalized way to serialize the implementations of core interfaces.
*
* @author Stephen Mallette (http://stephen.genoprime.com)
@@ -328,52 +326,6 @@ final class GraphSONSerializers {
}
}
- final static class MapEntryJacksonSerializer extends StdSerializer<Map.Entry> {
-
- public MapEntryJacksonSerializer() {
- super(Map.Entry.class);
- }
-
- @Override
- public void serialize(final Map.Entry entry, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
- throws IOException {
- ser(entry, jsonGenerator, serializerProvider, null);
- }
- @Override
- public void serializeWithType(final Map.Entry entry, final JsonGenerator jsonGenerator,
- final SerializerProvider serializerProvider, final TypeSerializer typeSerializer) throws IOException {
- ser(entry, jsonGenerator, serializerProvider, typeSerializer);
- }
-
- private static void ser(final Map.Entry entry, final JsonGenerator jsonGenerator,
- final SerializerProvider serializerProvider, final TypeSerializer typeSerializer) throws IOException {
- jsonGenerator.writeStartObject();
- if (typeSerializer != null) jsonGenerator.writeStringField(GraphSONTokens.CLASS, HashMap.class.getName());
-
- // this treatment of keys is consistent with the current GraphSONKeySerializer which extends the
- // StdKeySerializer
- final Object key = entry.getKey();
- final Class cls = key.getClass();
- String k;
- if (cls == String.class)
- k = (String) key;
- else if (Element.class.isAssignableFrom(cls))
- k = ((Element) key).id().toString();
- else if(Date.class.isAssignableFrom(cls)) {
- if (serializerProvider.isEnabled(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS))
- k = String.valueOf(((Date) key).getTime());
- else
- k = serializerProvider.getConfig().getDateFormat().format((Date) key);
- } else if(cls == Class.class)
- k = ((Class) key).getName();
- else
- k = key.toString();
-
- serializerProvider.defaultSerializeField(k, entry.getValue(), jsonGenerator);
- jsonGenerator.writeEndObject();
- }
- }
-
private static void serializerVertexProperty(final VertexProperty property, final JsonGenerator jsonGenerator,
final SerializerProvider serializerProvider,
final TypeSerializer typeSerializer, final boolean normalize,
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/cee96fdb/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaTimeSerializers.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaTimeSerializers.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaTimeSerializers.java
new file mode 100644
index 0000000..7ceae94
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaTimeSerializers.java
@@ -0,0 +1,326 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.structure.io.graphson;
+
+import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator;
+import org.apache.tinkerpop.shaded.jackson.core.JsonParser;
+import org.apache.tinkerpop.shaded.jackson.databind.DeserializationContext;
+import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider;
+import org.apache.tinkerpop.shaded.jackson.databind.deser.std.StdDeserializer;
+import org.apache.tinkerpop.shaded.jackson.databind.jsontype.TypeSerializer;
+import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdSerializer;
+
+import java.io.IOException;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.MonthDay;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.Period;
+import java.time.Year;
+import java.time.YearMonth;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+
+/**
+ * GraphSON serializers for classes in {@code java.time.*}.
+ */
+final class JavaTimeSerializers {
+
+ private JavaTimeSerializers() {}
+
+ /**
+ * Base class for serializing the {@code java.time.*} to ISO-8061 formats.
+ */
+ static abstract class AbstractJavaTimeSerializer<T> extends StdSerializer<T> {
+
+ public AbstractJavaTimeSerializer(final Class<T> clazz) {
+ super(clazz);
+ }
+
+ @Override
+ public void serialize(final T value, final JsonGenerator gen,
+ final SerializerProvider serializerProvider) throws IOException {
+ gen.writeString(value.toString());
+ }
+
+ @Override
+ public void serializeWithType(final T value, final JsonGenerator gen,
+ final SerializerProvider serializers, final TypeSerializer typeSer) throws IOException {
+ typeSer.writeTypePrefixForObject(value, gen);
+ gen.writeStringField(GraphSONTokens.VALUE, value.toString());
+ typeSer.writeTypeSuffixForObject(value, gen);
+ }
+ }
+ /**
+ * Base class for serializing the {@code java.time.*} from ISO-8061 formats.
+ */
+ abstract static class AbstractJavaTimeJacksonDeserializer<T> extends StdDeserializer<T> {
+ public AbstractJavaTimeJacksonDeserializer(final Class<T> clazz) {
+ super(clazz);
+ }
+
+ public abstract T parse(final String val);
+
+ @Override
+ public T deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException {
+ if (!jsonParser.getText().equals(GraphSONTokens.VALUE))
+ throw new IOException(String.format("Invalid format for %s - expecting '%s' with a text value in ISO-8061 format", _valueClass.getSimpleName(), GraphSONTokens.VALUE));
+
+ return parse(jsonParser.nextTextValue());
+ }
+ }
+
+ final static class DurationJacksonSerializer extends AbstractJavaTimeSerializer<Duration> {
+
+ public DurationJacksonSerializer() {
+ super(Duration.class);
+ }
+ }
+
+ final static class DurationJacksonDeserializer extends AbstractJavaTimeJacksonDeserializer<Duration> {
+ public DurationJacksonDeserializer() {
+ super(Duration.class);
+ }
+
+ @Override
+ public Duration parse(final String val) {
+ return Duration.parse(val);
+ }
+ }
+
+ final static class InstantJacksonSerializer extends AbstractJavaTimeSerializer<Instant> {
+
+ public InstantJacksonSerializer() {
+ super(Instant.class);
+ }
+ }
+
+ final static class InstantJacksonDeserializer extends AbstractJavaTimeJacksonDeserializer<Instant> {
+ public InstantJacksonDeserializer() {
+ super(Instant.class);
+ }
+
+ @Override
+ public Instant parse(final String val) {
+ return Instant.parse(val);
+ }
+ }
+
+ final static class LocalDateJacksonSerializer extends AbstractJavaTimeSerializer<LocalDate> {
+
+ public LocalDateJacksonSerializer() {
+ super(LocalDate.class);
+ }
+ }
+
+ final static class LocalDateJacksonDeserializer extends AbstractJavaTimeJacksonDeserializer<LocalDate> {
+ public LocalDateJacksonDeserializer() {
+ super(LocalDate.class);
+ }
+
+ @Override
+ public LocalDate parse(final String val) {
+ return LocalDate.parse(val);
+ }
+ }
+
+ final static class LocalDateTimeJacksonSerializer extends AbstractJavaTimeSerializer<LocalDateTime> {
+
+ public LocalDateTimeJacksonSerializer() {
+ super(LocalDateTime.class);
+ }
+ }
+
+ final static class LocalDateTimeJacksonDeserializer extends AbstractJavaTimeJacksonDeserializer<LocalDateTime> {
+ public LocalDateTimeJacksonDeserializer() {
+ super(LocalDateTime.class);
+ }
+
+ @Override
+ public LocalDateTime parse(final String val) {
+ return LocalDateTime.parse(val);
+ }
+ }
+
+ final static class LocalTimeJacksonSerializer extends AbstractJavaTimeSerializer<LocalTime> {
+
+ public LocalTimeJacksonSerializer() {
+ super(LocalTime.class);
+ }
+ }
+
+ final static class LocalTimeJacksonDeserializer extends AbstractJavaTimeJacksonDeserializer<LocalTime> {
+ public LocalTimeJacksonDeserializer() {
+ super(LocalTime.class);
+ }
+
+ @Override
+ public LocalTime parse(final String val) {
+ return LocalTime.parse(val);
+ }
+ }
+
+ final static class MonthDayJacksonSerializer extends AbstractJavaTimeSerializer<MonthDay> {
+
+ public MonthDayJacksonSerializer() {
+ super(MonthDay.class);
+ }
+ }
+
+ final static class MonthDayJacksonDeserializer extends AbstractJavaTimeJacksonDeserializer<MonthDay> {
+ public MonthDayJacksonDeserializer() {
+ super(MonthDay.class);
+ }
+
+ @Override
+ public MonthDay parse(final String val) {
+ return MonthDay.parse(val);
+ }
+ }
+
+ final static class OffsetDateTimeJacksonSerializer extends AbstractJavaTimeSerializer<OffsetDateTime> {
+
+ public OffsetDateTimeJacksonSerializer() {
+ super(OffsetDateTime.class);
+ }
+ }
+
+ final static class OffsetDateTimeJacksonDeserializer extends AbstractJavaTimeJacksonDeserializer<OffsetDateTime> {
+ public OffsetDateTimeJacksonDeserializer() {
+ super(OffsetDateTime.class);
+ }
+
+ @Override
+ public OffsetDateTime parse(final String val) {
+ return OffsetDateTime.parse(val);
+ }
+ }
+
+ final static class OffsetTimeJacksonSerializer extends AbstractJavaTimeSerializer<OffsetTime> {
+
+ public OffsetTimeJacksonSerializer() {
+ super(OffsetTime.class);
+ }
+ }
+
+ final static class OffsetTimeJacksonDeserializer extends AbstractJavaTimeJacksonDeserializer<OffsetTime> {
+ public OffsetTimeJacksonDeserializer() {
+ super(OffsetTime.class);
+ }
+
+ @Override
+ public OffsetTime parse(final String val) {
+ return OffsetTime.parse(val);
+ }
+ }
+
+ final static class PeriodJacksonSerializer extends AbstractJavaTimeSerializer<Period> {
+
+ public PeriodJacksonSerializer() {
+ super(Period.class);
+ }
+ }
+
+ final static class PeriodJacksonDeserializer extends AbstractJavaTimeJacksonDeserializer<Period> {
+ public PeriodJacksonDeserializer() {
+ super(Period.class);
+ }
+
+ @Override
+ public Period parse(final String val) {
+ return Period.parse(val);
+ }
+ }
+
+ final static class YearJacksonSerializer extends AbstractJavaTimeSerializer<Year> {
+
+ public YearJacksonSerializer() {
+ super(Year.class);
+ }
+ }
+
+ final static class YearJacksonDeserializer extends AbstractJavaTimeJacksonDeserializer<Year> {
+ public YearJacksonDeserializer() {
+ super(Year.class);
+ }
+
+ @Override
+ public Year parse(final String val) {
+ return Year.parse(val);
+ }
+ }
+
+ final static class YearMonthJacksonSerializer extends AbstractJavaTimeSerializer<YearMonth> {
+
+ public YearMonthJacksonSerializer() {
+ super(YearMonth.class);
+ }
+ }
+
+ final static class YearMonthJacksonDeserializer extends AbstractJavaTimeJacksonDeserializer<YearMonth> {
+ public YearMonthJacksonDeserializer() {
+ super(YearMonth.class);
+ }
+
+ @Override
+ public YearMonth parse(final String val) {
+ return YearMonth.parse(val);
+ }
+ }
+
+ final static class ZonedDateTimeJacksonSerializer extends AbstractJavaTimeSerializer<ZonedDateTime> {
+
+ public ZonedDateTimeJacksonSerializer() {
+ super(ZonedDateTime.class);
+ }
+ }
+
+ final static class ZonedDateTimeJacksonDeserializer extends AbstractJavaTimeJacksonDeserializer<ZonedDateTime> {
+ public ZonedDateTimeJacksonDeserializer() {
+ super(ZonedDateTime.class);
+ }
+
+ @Override
+ public ZonedDateTime parse(final String val) {
+ return ZonedDateTime.parse(val);
+ }
+ }
+
+ final static class ZoneOffsetJacksonSerializer extends AbstractJavaTimeSerializer<ZoneOffset> {
+
+ public ZoneOffsetJacksonSerializer() {
+ super(ZoneOffset.class);
+ }
+ }
+
+ final static class ZoneOffsetJacksonDeserializer extends AbstractJavaTimeJacksonDeserializer<ZoneOffset> {
+ public ZoneOffsetJacksonDeserializer() {
+ super(ZoneOffset.class);
+ }
+
+ @Override
+ public ZoneOffset parse(final String val) {
+ return ZoneOffset.of(val);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/cee96fdb/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaUtilSerializers.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaUtilSerializers.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaUtilSerializers.java
new file mode 100644
index 0000000..4f2f5da
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/JavaUtilSerializers.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.structure.io.graphson;
+
+import org.apache.tinkerpop.gremlin.structure.Element;
+import org.apache.tinkerpop.shaded.jackson.core.JsonGenerator;
+import org.apache.tinkerpop.shaded.jackson.databind.SerializationFeature;
+import org.apache.tinkerpop.shaded.jackson.databind.SerializerProvider;
+import org.apache.tinkerpop.shaded.jackson.databind.jsontype.TypeSerializer;
+import org.apache.tinkerpop.shaded.jackson.databind.ser.std.StdSerializer;
+
+import java.io.IOException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * GraphSON serializers for classes in {@code java.util.*}.
+ */
+final class JavaUtilSerializers {
+
+ private JavaUtilSerializers() {}
+
+ final static class MapEntryJacksonSerializer extends StdSerializer<Map.Entry> {
+
+ public MapEntryJacksonSerializer() {
+ super(Map.Entry.class);
+ }
+
+ @Override
+ public void serialize(final Map.Entry entry, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider)
+ throws IOException {
+ ser(entry, jsonGenerator, serializerProvider, null);
+ }
+
+ @Override
+ public void serializeWithType(final Map.Entry entry, final JsonGenerator jsonGenerator,
+ final SerializerProvider serializerProvider, final TypeSerializer typeSerializer) throws IOException {
+ ser(entry, jsonGenerator, serializerProvider, typeSerializer);
+ }
+
+ private static void ser(final Map.Entry entry, final JsonGenerator jsonGenerator,
+ final SerializerProvider serializerProvider, final TypeSerializer typeSerializer) throws IOException {
+ jsonGenerator.writeStartObject();
+ if (typeSerializer != null) jsonGenerator.writeStringField(GraphSONTokens.CLASS, HashMap.class.getName());
+
+ // this treatment of keys is consistent with the current GraphSONKeySerializer which extends the
+ // StdKeySerializer
+ final Object key = entry.getKey();
+ final Class cls = key.getClass();
+ String k;
+ if (cls == String.class)
+ k = (String) key;
+ else if (Element.class.isAssignableFrom(cls))
+ k = ((Element) key).id().toString();
+ else if(Date.class.isAssignableFrom(cls)) {
+ if (serializerProvider.isEnabled(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS))
+ k = String.valueOf(((Date) key).getTime());
+ else
+ k = serializerProvider.getConfig().getDateFormat().format((Date) key);
+ } else if(cls == Class.class)
+ k = ((Class) key).getName();
+ else
+ k = key.toString();
+
+ serializerProvider.defaultSerializeField(k, entry.getValue(), jsonGenerator);
+ jsonGenerator.writeEndObject();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/cee96fdb/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperEmbeddedTypeTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperEmbeddedTypeTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperEmbeddedTypeTest.java
new file mode 100644
index 0000000..c7549f9
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperEmbeddedTypeTest.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.structure.io.graphson;
+
+import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
+import org.apache.tinkerpop.shaded.kryo.io.Input;
+import org.apache.tinkerpop.shaded.kryo.io.Output;
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.MonthDay;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.Period;
+import java.time.Year;
+import java.time.YearMonth;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+
+import static org.junit.Assert.assertEquals;
+
+public class GraphSONMapperEmbeddedTypeTest {
+ private final ObjectMapper mapper = GraphSONMapper.build().embedTypes(true).create().createMapper();
+
+ @Test
+ public void shouldHandleDuration()throws Exception {
+ final Duration o = Duration.ZERO;
+ assertEquals(o, serializeDeserialize(o, Duration.class));
+ }
+ @Test
+ public void shouldHandleInstant()throws Exception {
+ final Instant o = Instant.ofEpochMilli(System.currentTimeMillis());
+ assertEquals(o, serializeDeserialize(o, Instant.class));
+ }
+
+ @Test
+ public void shouldHandleLocalDate()throws Exception {
+ final LocalDate o = LocalDate.now();
+ assertEquals(o, serializeDeserialize(o, LocalDate.class));
+ }
+
+ @Test
+ public void shouldHandleLocalDateTime()throws Exception {
+ final LocalDateTime o = LocalDateTime.now();
+ assertEquals(o, serializeDeserialize(o, LocalDateTime.class));
+ }
+
+ @Test
+ public void shouldHandleLocalTime()throws Exception {
+ final LocalTime o = LocalTime.now();
+ assertEquals(o, serializeDeserialize(o, LocalTime.class));
+ }
+
+ @Test
+ public void shouldHandleMonthDay()throws Exception {
+ final MonthDay o = MonthDay.now();
+ assertEquals(o, serializeDeserialize(o, MonthDay.class));
+ }
+
+ @Test
+ public void shouldHandleOffsetDateTime()throws Exception {
+ final OffsetDateTime o = OffsetDateTime.now();
+ assertEquals(o, serializeDeserialize(o, OffsetDateTime.class));
+ }
+
+ @Test
+ public void shouldHandleOffsetTime()throws Exception {
+ final OffsetTime o = OffsetTime.now();
+ assertEquals(o, serializeDeserialize(o, OffsetTime.class));
+ }
+
+ @Test
+ public void shouldHandlePeriod()throws Exception {
+ final Period o = Period.ofDays(3);
+ assertEquals(o, serializeDeserialize(o, Period.class));
+ }
+
+ @Test
+ public void shouldHandleYear()throws Exception {
+ final Year o = Year.now();
+ assertEquals(o, serializeDeserialize(o, Year.class));
+ }
+
+ @Test
+ public void shouldHandleYearMonth()throws Exception {
+ final YearMonth o = YearMonth.now();
+ assertEquals(o, serializeDeserialize(o, YearMonth.class));
+ }
+
+ @Test
+ public void shouldHandleZonedDateTime()throws Exception {
+ final ZonedDateTime o = ZonedDateTime.now();
+ assertEquals(o, serializeDeserialize(o, ZonedDateTime.class));
+ }
+
+ @Test
+ public void shouldHandleZonedOffset()throws Exception {
+ final ZoneOffset o = ZonedDateTime.now().getOffset();
+ assertEquals(o, serializeDeserialize(o, ZoneOffset.class));
+ }
+
+ public <T> T serializeDeserialize(final Object o, final Class<T> clazz) throws Exception {
+ try (final ByteArrayOutputStream stream = new ByteArrayOutputStream()) {
+ mapper.writeValue(stream, o);
+
+ try (final InputStream inputStream = new ByteArrayInputStream(stream.toByteArray())) {
+ return mapper.readValue(inputStream, clazz);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/cee96fdb/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperTest.java
new file mode 100644
index 0000000..0a16a4e
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONMapperTest.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.structure.io.graphson;
+
+import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
+import org.junit.Test;
+
+import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.MonthDay;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.Period;
+import java.time.Year;
+import java.time.YearMonth;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+
+import static org.junit.Assert.assertEquals;
+
+public class GraphSONMapperTest {
+ private final ObjectMapper mapper = GraphSONMapper.build().embedTypes(false).create().createMapper();
+
+ @Test
+ public void shouldHandleDuration()throws Exception {
+ final Duration o = Duration.ZERO;
+ final String json = mapper.writeValueAsString(o);
+ assertEquals("\"" + o.toString() + "\"", json);
+ }
+
+ @Test
+ public void shouldHandleInstant()throws Exception {
+ final Instant o = Instant.ofEpochMilli(System.currentTimeMillis());
+ final String json = mapper.writeValueAsString(o);
+ assertEquals("\"" + o.toString() + "\"", json);
+ }
+
+ @Test
+ public void shouldHandleLocalDate()throws Exception {
+ final LocalDate o = LocalDate.now();
+ final String json = mapper.writeValueAsString(o);
+ assertEquals("\"" + o.toString() + "\"", json);
+ }
+
+ @Test
+ public void shouldHandleLocalDateTime()throws Exception {
+ final LocalDateTime o = LocalDateTime.now();
+ final String json = mapper.writeValueAsString(o);
+ assertEquals("\"" + o.toString() + "\"", json);
+ }
+
+ @Test
+ public void shouldHandleLocalTime()throws Exception {
+ final LocalTime o = LocalTime.now();
+ final String json = mapper.writeValueAsString(o);
+ assertEquals("\"" + o.toString() + "\"", json);
+ }
+
+ @Test
+ public void shouldHandleMonthDay()throws Exception {
+ final MonthDay o = MonthDay.now();
+ final String json = mapper.writeValueAsString(o);
+ assertEquals("\"" + o.toString() + "\"", json);
+ }
+
+ @Test
+ public void shouldHandleOffsetDateTime()throws Exception {
+ final OffsetDateTime o = OffsetDateTime.now();
+ final String json = mapper.writeValueAsString(o);
+ assertEquals("\"" + o.toString() + "\"", json);
+ }
+
+ @Test
+ public void shouldHandleOffsetTime()throws Exception {
+ final OffsetTime o = OffsetTime.now();
+ final String json = mapper.writeValueAsString(o);
+ assertEquals("\"" + o.toString() + "\"", json);
+ }
+
+ @Test
+ public void shouldHandlePeriod()throws Exception {
+ final Period o = Period.ofDays(3);
+ final String json = mapper.writeValueAsString(o);
+ assertEquals("\"" + o.toString() + "\"", json);
+ }
+
+ @Test
+ public void shouldHandleYear()throws Exception {
+ final Year o = Year.now();
+ final String json = mapper.writeValueAsString(o);
+ assertEquals("\"" + o.toString() + "\"", json);
+ }
+
+ @Test
+ public void shouldHandleYearMonth()throws Exception {
+ final YearMonth o = YearMonth.now();
+ final String json = mapper.writeValueAsString(o);
+ assertEquals("\"" + o.toString() + "\"", json);
+ }
+
+ @Test
+ public void shouldHandleZonedDateTime()throws Exception {
+ final ZonedDateTime o = ZonedDateTime.now();
+ final String json = mapper.writeValueAsString(o);
+ assertEquals("\"" + o.toString() + "\"", json);
+ }
+
+ @Test
+ public void shouldHandleZoneOffset()throws Exception {
+ final ZoneOffset o = ZonedDateTime.now().getOffset();
+ final String json = mapper.writeValueAsString(o);
+ assertEquals("\"" + o.toString() + "\"", json);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/cee96fdb/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapperTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapperTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapperTest.java
index a915797..e92eaf9 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapperTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoMapperTest.java
@@ -47,7 +47,6 @@ import java.time.OffsetTime;
import java.time.Period;
import java.time.Year;
import java.time.YearMonth;
-import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/cee96fdb/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
index f03f9c2..d37a1bc 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/HttpGremlinEndpointHandler.java
@@ -253,7 +253,8 @@ public class HttpGremlinEndpointHandler extends ChannelInboundHandlerAdapter {
}));
evalFuture.exceptionally(t -> {
- sendError(ctx, INTERNAL_SERVER_ERROR, String.format("Error encountered evaluating script: %s", requestArguments.getValue0()));
+ sendError(ctx, INTERNAL_SERVER_ERROR,
+ String.format("Error encountered evaluating script: %s", requestArguments.getValue0()), Optional.of(t));
promise.setFailure(t);
return null;
});
@@ -437,8 +438,19 @@ public class HttpGremlinEndpointHandler extends ChannelInboundHandlerAdapter {
return node.asText();
}
- private static void sendError(final ChannelHandlerContext ctx, final HttpResponseStatus status, final String message) {
- logger.warn("Invalid request - responding with {} and {}", status, message);
+
+ private static void sendError(final ChannelHandlerContext ctx, final HttpResponseStatus status,
+ final String message) {
+ sendError(ctx, status, message, Optional.empty());
+ }
+
+ private static void sendError(final ChannelHandlerContext ctx, final HttpResponseStatus status,
+ final String message, final Optional<Throwable> t) {
+ if (t.isPresent())
+ logger.warn(String.format("Invalid request - responding with %s and %s", status, message), t.get());
+ else
+ logger.warn(String.format("Invalid request - responding with %s and %s", status, message));
+
errorMeter.mark();
final ObjectNode node = mapper.createObjectNode();
node.put("message", message);
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/cee96fdb/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java
index 00e757c..f8efda9 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerHttpIntegrateTest.java
@@ -34,8 +34,9 @@ import org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper;
import org.junit.Test;
import java.io.File;
-import java.util.Arrays;
+import java.time.Instant;
import java.util.Base64;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -64,7 +65,7 @@ public class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra
case "should200OnPOSTWithGremlinJsonEndcodedBodyWithIteratorResult":
case "should200OnPOSTWithGremlinJsonEndcodedBodyWithIteratorResultAndAliases":
case "should200OnGETWithGremlinQueryStringArgumentWithIteratorResultAndAliases":
- settings.scriptEngines.get("gremlin-groovy").scripts = Arrays.asList("scripts/generate-classic.groovy");
+ settings.scriptEngines.get("gremlin-groovy").scripts = Collections.singletonList("scripts/generate-classic.groovy");
break;
case "should200OnPOSTTransactionalGraph":
deleteDirectory(new File("/tmp/neo4j"));
@@ -428,6 +429,24 @@ public class GremlinServerHttpIntegrateTest extends AbstractGremlinServerIntegra
}
@Test
+ public void should200OnPOSTWithGremlinJsonEndcodedBodyForJavaTime() throws Exception {
+ // basic test of java.time.* serialization over JSON from the server perspective. more complete tests
+ // exist in gremlin-core
+ final CloseableHttpClient httpclient = HttpClients.createDefault();
+ final HttpPost httppost = new HttpPost("http://localhost:8182");
+ httppost.addHeader("Content-Type", "application/json");
+ httppost.setEntity(new StringEntity("{\"gremlin\":\"java.time.Instant.MAX\"}", Consts.UTF_8));
+
+ try (final CloseableHttpResponse response = httpclient.execute(httppost)) {
+ assertEquals(200, response.getStatusLine().getStatusCode());
+ assertEquals("application/json", response.getEntity().getContentType().getValue());
+ final String json = EntityUtils.toString(response.getEntity());
+ final JsonNode node = mapper.readTree(json);
+ assertEquals(Instant.MAX, Instant.parse(node.get("result").get("data").get(0).asText()));
+ }
+ }
+
+ @Test
public void should200OnPOSTTransactionalGraph() throws Exception {
assumeNeo4jIsPresent();