You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2014/05/07 06:43:18 UTC
git commit: [OLINGO-274] fix V4 json error response's deserializing
("details" & "innererror")
Repository: olingo-odata4
Updated Branches:
refs/heads/olingo274 f02d9a07e -> 6f1f4d05b
[OLINGO-274] fix V4 json error response's deserializing ("details" & "innererror")
Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/6f1f4d05
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/6f1f4d05
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/6f1f4d05
Branch: refs/heads/olingo274
Commit: 6f1f4d05bda2f3ee75bf2f6fa6a8668f8ab0b18f
Parents: f02d9a0
Author: challenh <ch...@apache.org>
Authored: Wed May 7 12:42:01 2014 +0800
Committer: challenh <ch...@apache.org>
Committed: Wed May 7 12:42:01 2014 +0800
----------------------------------------------------------------------
fit/src/main/resources/V40/badRequest.json | 50 ++++++++-----
fit/src/main/resources/V40/notFound.json | 44 +++++++++---
.../olingo/fit/v4/ErrorResponseTestITCase.java | 76 ++++++++++++++++++++
.../apache/olingo/commons/api/Constants.java | 4 ++
.../olingo/commons/api/domain/ODataError.java | 17 +++++
.../commons/api/domain/ODataErrorDetail.java | 48 +++++++++++++
.../commons/core/data/AbstractODataError.java | 32 +++++++--
.../core/data/JSONODataErrorDeserializer.java | 34 ++++++++-
.../data/JSONODataErrorDetailDeserializer.java | 66 +++++++++++++++++
.../core/data/JSONODataErrorDetailImpl.java | 62 ++++++++++++++++
10 files changed, 402 insertions(+), 31 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6f1f4d05/fit/src/main/resources/V40/badRequest.json
----------------------------------------------------------------------
diff --git a/fit/src/main/resources/V40/badRequest.json b/fit/src/main/resources/V40/badRequest.json
index b6bc3ac..fbc0c63 100644
--- a/fit/src/main/resources/V40/badRequest.json
+++ b/fit/src/main/resources/V40/badRequest.json
@@ -1,17 +1,35 @@
{
- "odata.error":
- {
- "code": "",
- "message":
- {
- "lang": "en-US",
- "value": "Bad request."
- },
- "innererror":
- {
- "message": "Bad request.",
- "type": "Microsoft.Data.OData.BadRequest",
- "stacktrace": " at Microsoft.Data.OData.MediaTypeUtils.GetContentTypeFromSettings...."
- }
- }
-}
\ No newline at end of file
+
+ "error": {
+
+ "code": "400",
+
+ "message": "Bad request.",
+
+ "target": "query",
+
+ "details": [
+
+ {
+
+ "code": "400",
+
+ "target": "$search" ,
+
+ "message": "Microsoft.Data.OData.BadRequest"
+
+ }
+
+ ],
+
+ "innererror": {
+
+ "trace": ["at Microsoft.Data.OData.MediaTypeUtils.GetContentTypeFromSettings....","callmethod2 etc"],
+
+ "context": {"key1":"for debug deployment only"}
+
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6f1f4d05/fit/src/main/resources/V40/notFound.json
----------------------------------------------------------------------
diff --git a/fit/src/main/resources/V40/notFound.json b/fit/src/main/resources/V40/notFound.json
index fba2ac4..2af4618 100644
--- a/fit/src/main/resources/V40/notFound.json
+++ b/fit/src/main/resources/V40/notFound.json
@@ -1,11 +1,35 @@
{
- "odata.error":
- {
- "code": "",
- "message":
- {
- "lang": "en-US",
- "value": "Resource not found for the segment 'Customer'."
- }
- }
-}
\ No newline at end of file
+
+ "error": {
+
+ "code": "501",
+
+ "message": "Unsupported functionality",
+
+ "target": "query",
+
+ "details": [
+
+ {
+
+ "code": "301",
+
+ "target": "$search",
+
+ "message": "$search query option not supported"
+
+ }
+
+ ],
+
+ "innererror": {
+
+ "trace": ["callmethod1 etc","callmethod2 etc"],
+
+ "context": {"key1":"for debug deployment only"}
+
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6f1f4d05/fit/src/test/java/org/apache/olingo/fit/v4/ErrorResponseTestITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/v4/ErrorResponseTestITCase.java b/fit/src/test/java/org/apache/olingo/fit/v4/ErrorResponseTestITCase.java
new file mode 100644
index 0000000..7e576f0
--- /dev/null
+++ b/fit/src/test/java/org/apache/olingo/fit/v4/ErrorResponseTestITCase.java
@@ -0,0 +1,76 @@
+/*
+ * 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.v4;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.net.URI;
+import java.util.Dictionary;
+
+import org.apache.olingo.client.api.communication.ODataClientErrorException;
+import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
+import org.apache.olingo.commons.api.domain.ODataError;
+import org.apache.olingo.commons.api.domain.ODataErrorDetail;
+import org.apache.olingo.commons.api.domain.v4.ODataEntity;
+import org.apache.olingo.commons.api.format.ODataPubFormat;
+import org.junit.Test;
+
+public class ErrorResponseTestITCase extends AbstractTestITCase {
+
+ @Test
+ public void jsonError() {
+
+ ODataPubFormat format = ODataPubFormat.JSON;
+ final URI readURI = getClient().getURIBuilder(testStaticServiceRootURL)
+ .appendEntitySetSegment("Customers").appendKeySegment(32)
+ .build();
+
+ final ODataEntityRequest<ODataEntity> req = getClient()
+ .getRetrieveRequestFactory().getEntityRequest(readURI);
+ try {
+ final ODataEntity read = read(format, readURI);
+ } catch (Exception ex) {
+ ODataError err = ((ODataClientErrorException) ex).getODataError();
+
+ // verify details
+ ODataErrorDetail detail = (ODataErrorDetail) 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
+ Dictionary<String, Object> 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"));
+ return;
+ }
+
+ assertNotNull("should have got exception", null);
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6f1f4d05/lib/commons-api/src/main/java/org/apache/olingo/commons/api/Constants.java
----------------------------------------------------------------------
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 17a65eb..cc6907c 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
@@ -243,6 +243,10 @@ public interface Constants {
public static final String ERROR_TARGET = "target";
+ public static final String ERROR_DETAILS = "details";
+
+ public static final String ERROR_INNERERROR= "innererror";
+
// canonical functions to be applied via dynamic annotation <tt>Apply</tt>
public static final String CANONICAL_FUNCTION_CONCAT = "odata.concat";
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6f1f4d05/lib/commons-api/src/main/java/org/apache/olingo/commons/api/domain/ODataError.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/domain/ODataError.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/domain/ODataError.java
index fc309d3..f899d9a 100644
--- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/domain/ODataError.java
+++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/domain/ODataError.java
@@ -18,6 +18,9 @@
*/
package org.apache.olingo.commons.api.domain;
+import java.util.Dictionary;
+import java.util.List;
+
/**
* OData error.
*/
@@ -43,5 +46,19 @@ public interface ODataError {
* @return error message.
*/
String getTarget();
+
+
+ /**
+ * Gets error details.
+ *
+ * @return ODataErrorDetail list.
+ */
+ List<ODataErrorDetail> getDetails();
+ /**
+ * Gets server defined key-value pairs for debug environment only.
+ *
+ * @return a Dictionary representing server defined object.
+ */
+ Dictionary<String, Object> getInnerError();
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6f1f4d05/lib/commons-api/src/main/java/org/apache/olingo/commons/api/domain/ODataErrorDetail.java
----------------------------------------------------------------------
diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/domain/ODataErrorDetail.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/domain/ODataErrorDetail.java
new file mode 100644
index 0000000..462e91e
--- /dev/null
+++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/domain/ODataErrorDetail.java
@@ -0,0 +1,48 @@
+/*
+ * 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.commons.api.domain;
+
+/**
+ * OData details, for example - { "error": {..., "details":[
+ * {"code": "301","target": "$search" ,"message": "$search query option not supported"}
+ * ],...}}
+ */
+public interface ODataErrorDetail {
+
+ /**
+ * Gets error code.
+ *
+ * @return error code.
+ */
+ String getCode();
+
+ /**
+ * Gets error message.
+ *
+ * @return error message.
+ */
+ String getMessage();
+
+ /**
+ * Gets error target.
+ *
+ * @return error message.
+ */
+ String getTarget();
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6f1f4d05/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractODataError.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractODataError.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractODataError.java
index 931a38b..62cbebf 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractODataError.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/AbstractODataError.java
@@ -18,9 +18,12 @@
*/
package org.apache.olingo.commons.core.data;
+import java.util.Dictionary;
+import java.util.List;
+
import org.apache.olingo.commons.api.domain.ODataError;
+import org.apache.olingo.commons.api.domain.ODataErrorDetail;
-// TODO p2 supports V4:
// {
// "error": {
// "code": "501",
@@ -29,10 +32,10 @@ import org.apache.olingo.commons.api.domain.ODataError;
// "details": [
// {
// "code": "301",
-// "target": "$search"
-// "message": "$search query option not supported",
+// "target": "$search",
+// "message": "$search query option not supported"
// }
-// ]
+// ],
// "innererror": {
// "trace": [...],
// "context": {...}
@@ -47,6 +50,10 @@ public abstract class AbstractODataError implements ODataError {
private String target;
+ private List<ODataErrorDetail> details;
+
+ private Dictionary<String,Object> innerError;
+
@Override
public String getCode() {
return code;
@@ -74,4 +81,21 @@ public abstract class AbstractODataError implements ODataError {
this.target = target;
}
+ @Override
+ public List<ODataErrorDetail> getDetails() {
+ return details;
+ }
+
+ public void setDetails(final List<ODataErrorDetail> detail) {
+ this.details = detail;
+ }
+
+ @Override
+ public Dictionary<String,Object> getInnerError() {
+ return innerError;
+ }
+
+ public void setInnerError(final Dictionary<String,Object> innerError) {
+ this.innerError = innerError;
+ }
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6f1f4d05/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONODataErrorDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONODataErrorDeserializer.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONODataErrorDeserializer.java
index 43ee06c..50fa1f9 100644
--- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONODataErrorDeserializer.java
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONODataErrorDeserializer.java
@@ -20,13 +20,23 @@ package org.apache.olingo.commons.core.data;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
+
import java.io.IOException;
import java.net.URI;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+
import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.ResWrap;
+import org.apache.olingo.commons.api.domain.ODataErrorDetail;
public class JSONODataErrorDeserializer extends AbstractJsonDeserializer<JSONODataErrorImpl> {
@@ -54,8 +64,30 @@ public class JSONODataErrorDeserializer extends AbstractJsonDeserializer<JSONODa
if (errorNode.has(Constants.ERROR_TARGET)) {
error.setTarget(errorNode.get(Constants.ERROR_TARGET).textValue());
}
+ if (errorNode.hasNonNull(Constants.ERROR_DETAILS)) {
+ List<ODataErrorDetail> details = new ArrayList<ODataErrorDetail>();
+ for (final Iterator<JsonNode> itor = errorNode.get(Constants.ERROR_DETAILS).iterator(); itor.hasNext();) {
+ details.add(
+ itor.next().traverse(parser.getCodec()).<ResWrap<JSONODataErrorDetailImpl>>readValueAs(
+ new TypeReference<JSONODataErrorDetailImpl>() {
+ }).getPayload());
+ }
+
+ error.setDetails(details);
+ }
+ if (errorNode.hasNonNull(Constants.ERROR_INNERERROR)) {
+ JsonNode innerError = errorNode.get(Constants.ERROR_INNERERROR);
+ Dictionary<String, Object> innerErr = new Hashtable<String, Object>();
+ for (final Iterator<String> itor = innerError.fieldNames(); itor.hasNext();) {
+ String keyTmp = itor.next();
+ String val = innerError.get(keyTmp).toString();
+ innerErr.put(keyTmp,val);
+ }
+
+ error.setInnerError(innerErr);
+ }
}
-
+
return new ResWrap<JSONODataErrorImpl>((URI) null, null, error);
}
}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6f1f4d05/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONODataErrorDetailDeserializer.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONODataErrorDetailDeserializer.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONODataErrorDetailDeserializer.java
new file mode 100644
index 0000000..9c2ce7b
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONODataErrorDetailDeserializer.java
@@ -0,0 +1,66 @@
+/*
+ * 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.commons.core.data;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.olingo.commons.api.Constants;
+import org.apache.olingo.commons.api.data.Entity;
+import org.apache.olingo.commons.api.data.ResWrap;
+import org.apache.olingo.commons.api.domain.ODataErrorDetail;
+
+public class JSONODataErrorDetailDeserializer extends
+ AbstractJsonDeserializer<JSONODataErrorDetailImpl> {
+
+ @Override
+ protected ResWrap<JSONODataErrorDetailImpl> doDeserialize(
+ final JsonParser parser, final DeserializationContext ctxt)
+ throws IOException, JsonProcessingException {
+
+ final JSONODataErrorDetailImpl error = new JSONODataErrorDetailImpl();
+ final JsonNode errorNode = parser.getCodec().readTree(parser);
+ if (errorNode.has(Constants.ERROR_CODE)) {
+ error.setCode(errorNode.get(Constants.ERROR_CODE).textValue());
+ }
+ if (errorNode.has(Constants.ERROR_MESSAGE)) {
+ final JsonNode message = errorNode.get(Constants.ERROR_MESSAGE);
+ if (message.isValueNode()) {
+ error.setMessage(message.textValue());
+ } else if (message.isObject()) {
+ error.setMessage(message.get(Constants.VALUE).asText());
+ }
+ }
+ if (errorNode.has(Constants.ERROR_TARGET)) {
+ error.setTarget(errorNode.get(Constants.ERROR_TARGET).textValue());
+ }
+
+ return new ResWrap<JSONODataErrorDetailImpl>((URI) null, null, error);
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6f1f4d05/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONODataErrorDetailImpl.java
----------------------------------------------------------------------
diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONODataErrorDetailImpl.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONODataErrorDetailImpl.java
new file mode 100644
index 0000000..2f4585a
--- /dev/null
+++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/data/JSONODataErrorDetailImpl.java
@@ -0,0 +1,62 @@
+/*
+ * 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.commons.core.data;
+
+import org.apache.olingo.commons.api.domain.ODataErrorDetail;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+/*
+ * JSONODataErrorDetailImpl, using the JSONODataErrorDetailDeserializer similar to JSONODataErrorImpl's.
+ */
+@JsonDeserialize(using = JSONODataErrorDetailDeserializer.class)
+public class JSONODataErrorDetailImpl implements ODataErrorDetail {
+
+ private String code;
+
+ private String message;
+
+ private String target;
+
+ @Override
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(final String code) {
+ this.code = code;
+ }
+
+ @Override
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(final String message) {
+ this.message = message;
+ }
+
+ @Override
+ public String getTarget() {
+ return target;
+ }
+
+ public void setTarget(final String target) {
+ this.target = target;
+ }
+}
\ No newline at end of file