diff --git a/fit/src/test/java/org/apache/olingo/fit/base/ErrorResponseTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/base/ErrorResponseTestITCase.java deleted file mode 100644 index d386bbed3..000000000 --- a/fit/src/test/java/org/apache/olingo/fit/base/ErrorResponseTestITCase.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.fit.base; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - -import java.net.URI; -import java.util.Map; - -import org.apache.olingo.client.api.communication.ODataClientErrorException; -import org.apache.olingo.commons.api.ex.ODataError; -import org.apache.olingo.commons.api.ex.ODataErrorDetail; -import org.apache.olingo.commons.api.format.ContentType; -import org.junit.Test; - -public class ErrorResponseTestITCase extends AbstractTestITCase { - - @Test - public void jsonError() { - final URI readURI = getClient().newURIBuilder(testStaticServiceRootURL). - appendEntitySetSegment("Customers").appendKeySegment(32). - build(); - - try { - read(ContentType.JSON, readURI); - fail("should have got exception"); - } catch (Exception ex) { - final ODataError err = ((ODataClientErrorException) ex).getODataError(); - - // verify details - final ODataErrorDetail detail = err.getDetails().get(0); - assertEquals("Code should be correct", "301", detail.getCode()); - assertEquals("Target should be correct", "$search", detail.getTarget()); - assertEquals("Message should be correct", "$search query option not supported", detail.getMessage()); - - // verify inner error dictionary - final Map innerErr = err.getInnerError(); - assertEquals("innerError dictionary size should be correct", 2, innerErr.size()); - assertEquals("innerError['context'] should be correct", - "{\"key1\":\"for debug deployment only\"}", innerErr.get("context")); - assertEquals("innerError['trace'] should be correct", - "[\"callmethod1 etc\",\"callmethod2 etc\"]", innerErr.get("trace")); - } - } -} diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java index 6bc9f324f..101f8a98a 100644 --- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java @@ -296,7 +296,7 @@ public class BasicITCase extends AbstractParamTecSvcITCase { assertEquals(HttpStatusCode.BAD_REQUEST.getStatusCode(), e.getStatusLine().getStatusCode()); final ODataError error = e.getODataError(); assertThat(error.getMessage(), containsString("key")); - } + } } @Test diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/AtomDeserializer.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/AtomDeserializer.java index 83a93d1e3..0fa17365b 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/AtomDeserializer.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/AtomDeserializer.java @@ -64,6 +64,7 @@ import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.core.edm.EdmTypeInfo; import com.fasterxml.aalto.stax.InputFactoryImpl; +import org.apache.olingo.commons.api.ex.ODataErrorDetail; public class AtomDeserializer implements ODataDeserializer { @@ -86,6 +87,7 @@ public class AtomDeserializer implements ODataDeserializer { protected static final QName errorCodeQName = new QName(Constants.NS_METADATA, Constants.ERROR_CODE); protected static final QName errorMessageQName = new QName(Constants.NS_METADATA, Constants.ERROR_MESSAGE); protected static final QName errorTargetQName = new QName(Constants.NS_METADATA, Constants.ERROR_TARGET); + protected static final QName errorDetailQName = new QName(Constants.NS_METADATA, Constants.ERROR_DETAIL); protected static final QName deletedEntryQName = new QName(Constants.NS_ATOM_TOMBSTONE, Constants.ATOM_ELEM_DELETED_ENTRY); @@ -826,18 +828,21 @@ public class AtomDeserializer implements ODataDeserializer { private ODataError error(final XMLEventReader reader, final StartElement start) throws XMLStreamException { final ODataError error = new ODataError(); - + error.setDetails(new ArrayList(0)); + ODataErrorDetail errorDetail = null; + boolean setCode = false; boolean codeSet = false; boolean setMessage = false; boolean messageSet = false; boolean setTarget = false; boolean targetSet = false; + boolean isDetails = false; boolean foundEndElement = false; while (reader.hasNext() && !foundEndElement) { final XMLEvent event = reader.nextEvent(); - + if (event.isStartElement()) { if (errorCodeQName.equals(event.asStartElement().getName())) { setCode = true; @@ -845,6 +850,9 @@ public class AtomDeserializer implements ODataDeserializer { setMessage = true; } else if (errorTargetQName.equals(event.asStartElement().getName())) { setTarget = true; + } else if (errorDetailQName.equals(event.asStartElement().getName())){ + isDetails = true; + errorDetail = new ODataErrorDetail(); } } @@ -864,8 +872,26 @@ public class AtomDeserializer implements ODataDeserializer { setTarget = false; targetSet = true; } + // DETAIL Error + if(setCode && isDetails){ + errorDetail.setCode(event.asCharacters().getData()); + setCode = false; + } + if(setMessage && isDetails){ + errorDetail.setMessage(event.asCharacters().getData()); + setMessage = false; + } + if(setTarget && isDetails){ + errorDetail.setTarget(event.asCharacters().getData()); + setTarget = false; + } } - + + if(event.isEndElement() && errorDetailQName.equals(event.asEndElement().getName())){ + isDetails = false; + error.getDetails().add(errorDetail); + } + if (event.isEndElement() && start.getName().equals(event.asEndElement().getName())) { foundEndElement = true; } diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/ErrorTest.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/ErrorTest.java index 60bbcd047..b930464dc 100644 --- a/lib/client-core/src/test/java/org/apache/olingo/client/core/ErrorTest.java +++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/ErrorTest.java @@ -18,12 +18,14 @@ */ package org.apache.olingo.client.core; -import static org.junit.Assert.assertEquals; +import java.util.Map; import static org.junit.Assert.assertNotNull; import org.apache.olingo.client.api.serialization.ODataDeserializerException; import org.apache.olingo.commons.api.ex.ODataError; +import org.apache.olingo.commons.api.ex.ODataErrorDetail; import org.apache.olingo.commons.api.format.ContentType; +import static org.junit.Assert.assertEquals; import org.junit.Test; public class ErrorTest extends AbstractTest { @@ -35,16 +37,31 @@ public class ErrorTest extends AbstractTest { return error; } - private void simple(final ContentType contentType) throws ODataDeserializerException { + private ODataError simple(final ContentType contentType) throws ODataDeserializerException { final ODataError error = error("error", contentType); assertEquals("501", error.getCode()); assertEquals("Unsupported functionality", error.getMessage()); assertEquals("query", error.getTarget()); + + // verify details + final ODataErrorDetail detail = error.getDetails().get(0); + assertEquals("Code should be correct", "301", detail.getCode()); + assertEquals("Target should be correct", "$search", detail.getTarget()); + assertEquals("Message should be correct", "$search query option not supported", detail.getMessage()); + return error; } @Test public void jsonSimple() throws Exception { - simple(ContentType.JSON); + final ODataError error = simple(ContentType.JSON); + + // verify inner error dictionary + final Map innerErr = error.getInnerError(); + assertEquals("innerError dictionary size should be correct", 2, innerErr.size()); + assertEquals("innerError['context'] should be correct", + "{\"key1\":\"for debug deployment only\"}", innerErr.get("context")); + assertEquals("innerError['trace'] should be correct", + "[\"callmethod1 etc\",\"callmethod2 etc\"]", innerErr.get("trace")); } @Test diff --git a/lib/client-core/src/test/resources/org/apache/olingo/client/core/error.json b/lib/client-core/src/test/resources/org/apache/olingo/client/core/error.json index 30a50d874..ddee0c229 100644 --- a/lib/client-core/src/test/resources/org/apache/olingo/client/core/error.json +++ b/lib/client-core/src/test/resources/org/apache/olingo/client/core/error.json @@ -9,6 +9,10 @@ "target": "$search", "message": "$search query option not supported" } - ] + ], + "innererror": { + "trace": ["callmethod1 etc", "callmethod2 etc"], + "context": {"key1": "for debug deployment only"} + } } } \ No newline at end of file diff --git a/lib/client-core/src/test/resources/org/apache/olingo/client/core/error.xml b/lib/client-core/src/test/resources/org/apache/olingo/client/core/error.xml index 149b799b3..6126023f9 100644 --- a/lib/client-core/src/test/resources/org/apache/olingo/client/core/error.xml +++ b/lib/client-core/src/test/resources/org/apache/olingo/client/core/error.xml @@ -28,4 +28,4 @@ under the License. $search - + \ No newline at end of file diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/Constants.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/Constants.java index 74db088f4..fb8a6b342 100644 --- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/Constants.java +++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/Constants.java @@ -302,6 +302,8 @@ public interface Constants { String ERROR_DETAILS = "details"; + String ERROR_DETAIL = "detail"; + String ERROR_INNERERROR = "innererror"; // canonical functions to be applied via dynamic annotation Apply