Repository: olingo-odata4 Updated Branches: refs/heads/OLINGO-832_StreamSerializerPoC 67494a789 -> 5b6cccfa9
[OLINGO-832] Added WriteContentErrorContext and first tests Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/5b6cccfa Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/5b6cccfa Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/5b6cccfa Branch: refs/heads/OLINGO-832_StreamSerializerPoC Commit: 5b6cccfa9cd38262b57409bdc6204b16406afd0e Parents: 67494a7 Author: Michael Bolz <[email protected]> Authored: Tue Feb 16 15:46:42 2016 +0100 Committer: Michael Bolz <[email protected]> Committed: Tue Feb 16 15:46:42 2016 +0100 ---------------------------------------------------------------------- .../apache/olingo/server/api/ODataContent.java | 1 - .../server/api/WriteContentErrorCallback.java | 2 +- .../server/api/WriteContentErrorContext.java | 25 +++++ .../server/core/ODataWritableContent.java | 50 +++++++-- .../serializer/json/ODataJsonSerializer.java | 7 +- .../json/ODataJsonSerializerTest.java | 104 ++++++++++++++++++- 6 files changed, 173 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5b6cccfa/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataContent.java ---------------------------------------------------------------------- diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataContent.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataContent.java index d7e7ec3..e237bf3 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataContent.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataContent.java @@ -19,7 +19,6 @@ package org.apache.olingo.server.api; import java.io.OutputStream; -import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; public interface ODataContent { http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5b6cccfa/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorCallback.java ---------------------------------------------------------------------- diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorCallback.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorCallback.java index 4219b8f..abc500a 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorCallback.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorCallback.java @@ -21,5 +21,5 @@ package org.apache.olingo.server.api; import java.nio.channels.WritableByteChannel; public interface WriteContentErrorCallback { - void handleError(ODataContent content, WritableByteChannel channel); + void handleError(WriteContentErrorContext context, WritableByteChannel channel); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5b6cccfa/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorContext.java ---------------------------------------------------------------------- diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorContext.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorContext.java new file mode 100644 index 0000000..d773df1 --- /dev/null +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/WriteContentErrorContext.java @@ -0,0 +1,25 @@ +/* + * 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.olingo.server.api; + +public interface WriteContentErrorContext { + Exception getException(); + ODataLibraryException getODataLibraryException(); +// Object getParameter(String name); +} http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5b6cccfa/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataWritableContent.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataWritableContent.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataWritableContent.java index ba7025c..1b9cb30 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataWritableContent.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataWritableContent.java @@ -25,14 +25,19 @@ import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.nio.charset.Charset; +import java.util.HashMap; +import java.util.Map; import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntityIterator; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.ex.ODataRuntimeException; import org.apache.olingo.server.api.ODataContent; +import org.apache.olingo.server.api.ODataLibraryException; import org.apache.olingo.server.api.ServiceMetadata; -import org.apache.olingo.server.api.serializer.EntitySerializerOptions; +import org.apache.olingo.server.api.WriteContentErrorCallback; +import org.apache.olingo.server.api.WriteContentErrorContext; +import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions; import org.apache.olingo.server.api.serializer.SerializerException; import org.apache.olingo.server.api.serializer.SerializerStreamResult; import org.apache.olingo.server.core.serializer.SerializerStreamResultImpl; @@ -53,11 +58,11 @@ public class ODataWritableContent implements ODataContent { private EntityIterator coll; private ServiceMetadata metadata; private EdmEntityType entityType; - private EntitySerializerOptions options; + private EntityCollectionSerializerOptions options; public StreamChannel(EntityIterator coll, EdmEntityType entityType, String head, ODataJsonSerializer jsonSerializer, ServiceMetadata metadata, - EntitySerializerOptions options, String tail) { + EntityCollectionSerializerOptions options, String tail) { this.coll = coll; this.entityType = entityType; this.head = ByteBuffer.wrap(head.getBytes(DEFAULT)); @@ -81,6 +86,11 @@ public class ODataWritableContent implements ODataContent { } return true; } catch (SerializerException e) { + final WriteContentErrorCallback errorCallback = options.getWriteContentErrorCallback(); + if(errorCallback != null) { + final ErrorContext errorContext = new ErrorContext(e).setParameter("Sample", "Some exception happened."); + errorCallback.handleError(errorContext, Channels.newChannel(out)); + } } } else if(tail.hasRemaining()) { out.write(tail.array()); @@ -215,22 +225,50 @@ public class ODataWritableContent implements ODataContent { public static ODataWritableContentBuilder with(EntityIterator coll, EdmEntityType entityType, ODataJsonSerializer jsonSerializer, - ServiceMetadata metadata, EntitySerializerOptions options) { + ServiceMetadata metadata, EntityCollectionSerializerOptions options) { return new ODataWritableContentBuilder(coll, entityType, jsonSerializer, metadata, options); } + public static class ErrorContext implements WriteContentErrorContext { + private ODataLibraryException exception; + final private Map<String, Object> parameters = new HashMap<String, Object>(); + + public ErrorContext(ODataLibraryException exception) { + this.exception = exception; + } + + @Override + public Exception getException() { + return exception; + } + @Override + public ODataLibraryException getODataLibraryException() { + return exception; + } + + public ErrorContext setParameter(String name, Object value) { + parameters.put(name, value); + return this; + } + +// @Override + public Object getParameter(String name) { + return parameters.get(name); + } + } + public static class ODataWritableContentBuilder { private ODataJsonSerializer jsonSerializer; private EntityIterator entities; private ServiceMetadata metadata; private EdmEntityType entityType; - private EntitySerializerOptions options; + private EntityCollectionSerializerOptions options; private String head; private String tail; public ODataWritableContentBuilder(EntityIterator entities, EdmEntityType entityType, ODataJsonSerializer jsonSerializer, - ServiceMetadata metadata, EntitySerializerOptions options) { + ServiceMetadata metadata, EntityCollectionSerializerOptions options) { this.entities = entities; this.entityType = entityType; this.jsonSerializer = jsonSerializer; http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5b6cccfa/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java ---------------------------------------------------------------------- diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java index ba32ab6..df2ee84 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java @@ -211,12 +211,7 @@ public class ODataJsonSerializer extends AbstractODataSerializer { outputStream.close(); String tail = new String(outputStream.toByteArray(), Charset.forName("UTF-8")); - EntitySerializerOptions.Builder opt = EntitySerializerOptions.with(); - if(options != null) { - opt.expand(options.getExpand()).select(options - .getSelect()).writeOnlyReferences(options.getWriteOnlyReferences()); - } - return ODataWritableContent.with(entities, entityType, this, metadata, opt.build()) + return ODataWritableContent.with(entities, entityType, this, metadata, options) .addHead(head).addTail(tail).build(); } catch (final IOException e) { cachedException = http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/5b6cccfa/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java ---------------------------------------------------------------------- diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java index df6e472..4211819 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java @@ -18,18 +18,25 @@ */ package org.apache.olingo.server.core.serializer.json; +import java.io.IOException; import java.io.InputStream; import java.net.URI; +import java.nio.ByteBuffer; +import java.nio.channels.WritableByteChannel; import java.util.Arrays; import java.util.Collections; +import java.util.Iterator; +import java.util.Locale; import java.util.TimeZone; import org.apache.commons.io.IOUtils; +import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.olingo.commons.api.data.ComplexValue; import org.apache.olingo.commons.api.data.ContextURL; import org.apache.olingo.commons.api.data.ContextURL.Suffix; import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntityCollection; +import org.apache.olingo.commons.api.data.EntityIterator; import org.apache.olingo.commons.api.data.Property; import org.apache.olingo.commons.api.data.ValueType; import org.apache.olingo.commons.api.edm.EdmComplexType; @@ -40,7 +47,10 @@ import org.apache.olingo.commons.api.edm.EdmPrimitiveType; import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.ODataContent; import org.apache.olingo.server.api.ServiceMetadata; +import org.apache.olingo.server.api.WriteContentErrorCallback; +import org.apache.olingo.server.api.WriteContentErrorContext; import org.apache.olingo.server.api.edmx.EdmxReference; import org.apache.olingo.server.api.serializer.ComplexSerializerOptions; import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions; @@ -85,12 +95,12 @@ public class ODataJsonSerializerTest { public void setup() { TimeZone.setDefault(TimeZone.getTimeZone("GMT")); } - + @After public void teardown() { TimeZone.setDefault(TimeZone.getDefault()); } - + @Test public void entitySimple() throws Exception { final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); @@ -208,6 +218,96 @@ public class ODataJsonSerializerTest { } @Test + public void entityCollectionStreamed() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EntityIterator entityIterator = new EntityIterator() { + Iterator<Entity> innerIterator = data.readAll(edmEntitySet).iterator(); + @Override + public boolean hasNext() { + return innerIterator.hasNext(); + } + @Override + public Entity next() { + return innerIterator.next(); + } + }; + CountOption countOption = Mockito.mock(CountOption.class); + Mockito.when(countOption.getValue()).thenReturn(true); + + ODataContent result = serializer.entityCollectionStreamed( + metadata, edmEntitySet.getEntityType(), entityIterator, + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .build()).getODataContent(); + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + result.write(bout); + final String resultString = new String(bout.toByteArray(), "UTF-8"); + + Assert.assertThat(resultString, CoreMatchers.startsWith("{" + + "\"@odata.context\":\"$metadata#ESAllPrim\"," + + "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":[{\"PropertyInt16\":32767,\"PropertyString\"")); + Assert.assertThat(resultString, CoreMatchers.endsWith( + "\"PropertyTimeOfDay\":\"00:01:01\"}]}")); + + int count = 0; + int index = -1; + while ((index = resultString.indexOf("PropertyInt16\":", ++index)) > 0) { + count++; + } + Assert.assertEquals(3, count); + } + + @Test + public void entityCollectionStreamedWithError() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESAllPrim"); + final EntityIterator entityIterator = new EntityIterator() { + Iterator<Entity> innerIterator = data.readAll(edmEntitySet).iterator(); + @Override + public boolean hasNext() { + return innerIterator.hasNext(); + } + @Override + public Entity next() { + return new Entity(); + } + }; + CountOption countOption = Mockito.mock(CountOption.class); + Mockito.when(countOption.getValue()).thenReturn(true); + + WriteContentErrorCallback errorCallback = new WriteContentErrorCallback() { + @Override + public void handleError(WriteContentErrorContext context, WritableByteChannel channel) { + try { + String msgKey = context.getODataLibraryException().getMessageKey().getKey(); + String toChannel = "ERROR: " + msgKey; + channel.write(ByteBuffer.wrap(toChannel.getBytes("UTF-8"))); + } catch (IOException e) { + throw new RuntimeException("Error in error."); + } + } + }; + + ODataContent result = serializer.entityCollectionStreamed( + metadata, edmEntitySet.getEntityType(), entityIterator, + EntityCollectionSerializerOptions.with() + .writeContentErrorCallback(errorCallback) + .contextURL(ContextURL.with().entitySet(edmEntitySet).build()) + .build()).getODataContent(); + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + result.write(bout); + final String resultString = new String(bout.toByteArray(), "UTF-8"); + + Assert.assertThat(resultString, CoreMatchers.startsWith("{" + + "\"@odata.context\":\"$metadata#ESAllPrim\"," + + "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\"," + + "\"value\":")); + Assert.assertThat(resultString, CoreMatchers.endsWith( + "[ERROR: MISSING_PROPERTY")); + } + + + @Test public void entityCollAllPrim() throws Exception { final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESCollAllPrim"); final Entity entity = data.readAll(edmEntitySet).getEntities().get(0);
