diff options
author | PawelSzalapski <pawel.szalapski@nokia.com> | 2018-06-05 10:54:27 +0200 |
---|---|---|
committer | PawelSzalapski <pawel.szalapski@nokia.com> | 2018-06-11 10:11:41 +0200 |
commit | b48ea0e307f5977b5d2b9dcc4ebb22a7bc3f1710 (patch) | |
tree | c7a64db3efb07f41fde28e232e47a12c4e620c75 /src | |
parent | 071fb8779fd4c8c4abfcb72c1ed266280461bed2 (diff) |
Fix bug about custom exceptions not being used
The bug was that custom exception config was never actually queried
because of the mismatch between the production code usages and .json config file.
Change-Id: I416ef5f45770f9bb55d5dff143277b6c62fa25ba
Issue-ID: DCAEGEN2-518
Signed-off-by: PawelSzalapski <pawel.szalapski@nokia.com>
Diffstat (limited to 'src')
6 files changed, 157 insertions, 242 deletions
diff --git a/src/main/java/org/onap/dcae/commonFunction/CommonStartup.java b/src/main/java/org/onap/dcae/commonFunction/CommonStartup.java index f16cdbbc..0ca25e2b 100644 --- a/src/main/java/org/onap/dcae/commonFunction/CommonStartup.java +++ b/src/main/java/org/onap/dcae/commonFunction/CommonStartup.java @@ -92,7 +92,6 @@ public class CommonStartup extends NsaBaseEndpoint implements Runnable { public static final String KSETTING_SCHEMAFILE = "collector.schema.file";
public static final String KDEFAULT_SCHEMAFILE = "{\"v5\":\"./etc/CommonEventFormat_28.3.json\"}";
- public static final String KSETTING_EXCEPTIONCONFIG = "exceptionConfig";
public static final String KSETTING_DMAAPSTREAMID = "collector.dmaap.streamid";
@@ -114,7 +113,6 @@ public class CommonStartup extends NsaBaseEndpoint implements Runnable { public static int eventTransformFlag = 1;
public static String schemaFile;
public static JSONObject schemaFileJson;
- public static String exceptionConfig;
public static String cambriaConfigFile;
private boolean listnerstatus;
public static String streamid;
@@ -155,7 +153,6 @@ public class CommonStartup extends NsaBaseEndpoint implements Runnable { schemaFileJson = new JSONObject(schemaFile);
}
- exceptionConfig = settings.getString(KSETTING_EXCEPTIONCONFIG, null);
authflag = settings.getInt(CommonStartup.KSETTING_AUTHFLAG, CommonStartup.KDEFAULT_AUTHFLAG);
String[] currentconffile = settings.getStrings(CommonStartup.KSETTING_DMAAPCONFIGS,
CommonStartup.KDEFAULT_DMAAPCONFIGS);
@@ -166,8 +163,6 @@ public class CommonStartup extends NsaBaseEndpoint implements Runnable { fTomcatServer = new ApiServer.Builder(connectors, new RestfulCollectorServlet(settings)).encodeSlashes(true)
.name("collector").build();
- // Load override exception map
- CustomExceptionLoader.LoadMap();
setListnerstatus(true);
}
diff --git a/src/main/java/org/onap/dcae/commonFunction/CustomExceptionLoader.java b/src/main/java/org/onap/dcae/commonFunction/CustomExceptionLoader.java deleted file mode 100644 index 2aec512f..00000000 --- a/src/main/java/org/onap/dcae/commonFunction/CustomExceptionLoader.java +++ /dev/null @@ -1,128 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.commonFunction; - -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.util.HashMap; - -import java.util.Map.Entry; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonIOException; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.JsonSyntaxException; - -public class CustomExceptionLoader { - - protected static HashMap<String, JsonArray> map = null; - private static final Logger log = LoggerFactory.getLogger(CustomExceptionLoader.class); - - // For standalone test - // LoadMap Invoked from servletSetup - /* - * public static void main(String[] args) { - * - * System.out. - * println("CustomExceptionLoader.main --> Arguments -- ExceptionConfig file: " - * + args[0] + "StatusCode:" + args[1]+ " Error Msg:" + args[2]); - * CommonStartup.exceptionConfig = args[0]; - * - * //Read the Custom exception JSON file into map LoadMap(); System.out. - * println("CustomExceptionLoader.main --> Map info post LoadMap:" + map); - * - * String[] str= LookupMap(args[1],args[2]); if (! (str==null)) { - * System.out. - * println("CustomExceptionLoader.main --> Return from lookup function" + - * str[0] + "value:" + str[1]); } - * - * } - */ - - public static void LoadMap() { - - map = new HashMap<String, JsonArray>(); - FileReader fr = null; - try { - JsonElement root = null; - fr = new FileReader(CommonStartup.exceptionConfig); - root = new JsonParser().parse(fr); - JsonObject jsonObject = root.getAsJsonObject().get("code").getAsJsonObject(); - - for (Entry<String, JsonElement> entry : jsonObject.entrySet()) { - map.put(entry.getKey(), (JsonArray) entry.getValue()); - } - - log.debug("CustomExceptionLoader.LoadMap --> Map loaded - " + map); - } catch (JsonIOException | JsonSyntaxException | FileNotFoundException e) { - log.error("Exception in LoadMap:" + e.getMessage()); - map = null; - } finally { - if (fr != null) { - try { - fr.close(); - } catch (IOException e) { - log.error("Error closing file reader stream : " + e.toString()); - map = null; - } - } - } - } - - public static String[] LookupMap(String error, String errormsg) { - - String[] retarray = null; - - log.debug("CustomExceptionLoader.LookupMap -->" + " HTTP StatusCode:" + error + " Msg:" + errormsg); - try { - - JsonArray jarray = map.get(error); - for (int i = 0; i < jarray.size(); i++) { - - JsonElement val = jarray.get(i).getAsJsonObject().get("Reason"); - JsonArray ec = (JsonArray) jarray.get(i).getAsJsonObject().get("ErrorCode"); - log.trace("CustomExceptionLoader.LookupMap Parameter -> Error msg : " + errormsg - + " Reason text being matched:" + val); - if (errormsg.contains(val.toString().replace("\"", ""))) { - log.trace( - "CustomExceptionLoader.LookupMap Successful! Exception matched to error message StatusCode:" - + ec.get(0).toString() + "ErrorMessage:" + ec.get(1).toString()); - retarray = new String[2]; - retarray[0] = ec.get(0).toString(); - retarray[1] = ec.get(1).toString(); - return retarray; - } - } - - } catch (Exception e) { - System.out.println(e.getMessage()); - } - - return retarray; - } - -} diff --git a/src/main/java/org/onap/dcae/restapi/ApiException.java b/src/main/java/org/onap/dcae/restapi/ApiException.java new file mode 100644 index 00000000..3feeacfc --- /dev/null +++ b/src/main/java/org/onap/dcae/restapi/ApiException.java @@ -0,0 +1,70 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.ves + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.restapi; + +import com.google.common.base.CaseFormat; +import org.json.JSONObject; + +/** + * @author Pawel Szalapski (pawel.szalapski@nokia.com) + */ +public enum ApiException { + + INVALID_JSON_INPUT(ExceptionType.SERVICE_EXCEPTION, "SVC0002", "Incorrect JSON payload", 400), + SCHEMA_VALIDATION_FAILED(ExceptionType.SERVICE_EXCEPTION, "SVC0002", "Bad Parameter (JSON does not conform to schema)", 400), + INVALID_CONTENT_TYPE(ExceptionType.SERVICE_EXCEPTION, "SVC0002", "Bad Parameter (Incorrect request Content-Type)", 400), + UNAUTHORIZED_USER(ExceptionType.POLICY_EXCEPTION, "POL2000", "Unauthorized user", 401), + NO_SERVER_RESOURCES(ExceptionType.SERVICE_EXCEPTION, "SVC1000", "No server resources (internal processing queue full)", 503); + + public final ExceptionType type; + public final String code; + public final String details; + public final int httpStatusCode; + + ApiException(ExceptionType type, String code, String details, int httpStatusCode) { + this.type = type; + this.code = code; + this.details = details; + this.httpStatusCode = httpStatusCode; + } + + public enum ExceptionType { + SERVICE_EXCEPTION, POLICY_EXCEPTION; + + @Override + public String toString() { + return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, this.name()); + } + } + + public JSONObject toJSON() { + JSONObject exceptionTypeNode = new JSONObject(); + exceptionTypeNode.put("messageId", code ); + exceptionTypeNode.put("text", details); + + JSONObject requestErrorNode = new JSONObject(); + requestErrorNode.put(type.toString(), exceptionTypeNode); + + JSONObject rootNode = new JSONObject(); + rootNode.put("requestError", requestErrorNode); + return rootNode; + } + +} diff --git a/src/main/java/org/onap/dcae/restapi/endpoints/EventReceipt.java b/src/main/java/org/onap/dcae/restapi/endpoints/EventReceipt.java index f5a5e6d8..24bd96ea 100644 --- a/src/main/java/org/onap/dcae/restapi/endpoints/EventReceipt.java +++ b/src/main/java/org/onap/dcae/restapi/endpoints/EventReceipt.java @@ -29,27 +29,25 @@ import com.att.nsa.logging.LoggingContext; import com.att.nsa.logging.log4j.EcompFields;
import com.att.nsa.security.db.simple.NsaSimpleApiKey;
import com.google.gson.JsonParser;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.Base64;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.onap.dcae.commonFunction.CommonStartup;
import org.onap.dcae.commonFunction.CommonStartup.QueueFullException;
-import org.onap.dcae.commonFunction.CustomExceptionLoader;
import org.onap.dcae.commonFunction.VESLogger;
+import org.onap.dcae.restapi.ApiException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.Charset;
-import java.util.Base64;
-import java.util.UUID;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
public class EventReceipt extends NsaBaseEndpoint {
private static final Logger log = LoggerFactory.getLogger(EventReceipt.class);
@@ -116,7 +114,7 @@ public class EventReceipt extends NsaBaseEndpoint { //log.info("Invalid user request :" + userId + " FROM " + ctx.request().getRemoteAddress() + " " + ctx.request().getContentType() + MESSAGE + jsonObject);
log.info(String.format("Unauthorized request %s FROM %s %s %s %s", getUser(ctx), ctx.request().getRemoteAddress(), ctx.request().getContentType(), MESSAGE, jsonObject));
CommonStartup.eplog.info("EVENT_RECEIPT_FAILURE: Unauthorized user" + userId + x);
- respondWithCustomMsginJson(ctx, HttpStatusCodes.k401_unauthorized, "Invalid user");
+ respondWithCustomMsginJson(ctx, ApiException.UNAUTHORIZED_USER);
return;
}
@@ -131,12 +129,12 @@ public class EventReceipt extends NsaBaseEndpoint { log.error(String.format("Couldn't parse JSON Array - HttpStatusCodes.k400_badRequest%d%s%s",
HttpStatusCodes.k400_badRequest, MESSAGE, x.getMessage()));
CommonStartup.eplog.info("EVENT_RECEIPT_FAILURE: Invalid user request " + x);
- respondWithCustomMsginJson(ctx, HttpStatusCodes.k400_badRequest, "Couldn't parse JSON object");
+ respondWithCustomMsginJson(ctx, ApiException.INVALID_JSON_INPUT);
return;
} catch (QueueFullException e) {
log.error("Collector internal queue full :" + e.getMessage(), e);
CommonStartup.eplog.info("EVENT_RECEIPT_FAILURE: QueueFull" + e);
- respondWithCustomMsginJson(ctx, HttpStatusCodes.k503_serviceUnavailable, "Queue full");
+ respondWithCustomMsginJson(ctx, ApiException.NO_SERVER_RESOURCES);
return;
} finally {
if (fr != null) {
@@ -187,20 +185,18 @@ public class EventReceipt extends NsaBaseEndpoint { log.info("Validation successful");
} else if (valresult.equals("false")) {
log.info("Validation failed");
- respondWithCustomMsginJson(ctx, HttpStatusCodes.k400_badRequest,
- "Schema validation failed");
+ respondWithCustomMsginJson(ctx, ApiException.SCHEMA_VALIDATION_FAILED);
ErrorStatus=true;
return ErrorStatus;
} else {
log.error("Validation errored" + valresult);
- respondWithCustomMsginJson(ctx, HttpStatusCodes.k400_badRequest,
- "Couldn't parse JSON object");
+ respondWithCustomMsginJson(ctx, ApiException.INVALID_JSON_INPUT);
ErrorStatus=true;
return ErrorStatus;
}
} else {
log.info("Validation failed");
- respondWithCustomMsginJson(ctx, HttpStatusCodes.k400_badRequest, "Schema validation failed");
+ respondWithCustomMsginJson(ctx, ApiException.SCHEMA_VALIDATION_FAILED);
ErrorStatus=true;
return ErrorStatus;
}
@@ -225,8 +221,7 @@ public class EventReceipt extends NsaBaseEndpoint { if (!ctx.request().getContentType().equalsIgnoreCase("application/json")) {
log.info(String.format("Rejecting request with content type %s Message:%s",
ctx.request().getContentType(), jsonObject));
- respondWithCustomMsginJson(ctx, HttpStatusCodes.k400_badRequest,
- "Incorrect message content-type; only accepts application/json messages");
+ respondWithCustomMsginJson(ctx, ApiException.INVALID_CONTENT_TYPE);
ErrorStatus=true;
return ErrorStatus;
}
@@ -235,39 +230,17 @@ public class EventReceipt extends NsaBaseEndpoint { } else {
log.info(String.format("Unauthorized request %s FROM %s %s %s %s", getUser(ctx), ctx.request().getRemoteAddress(), ctx.request().getContentType(), MESSAGE,
jsonObject));
- respondWithCustomMsginJson(ctx, HttpStatusCodes.k401_unauthorized, "Unauthorized user");
+ respondWithCustomMsginJson(ctx, ApiException.UNAUTHORIZED_USER);
ErrorStatus=true;
return ErrorStatus;
}
return ErrorStatus;
}
- public static void respondWithCustomMsginJson(DrumlinRequestContext ctx, int sc, String msg) {
- String[] str;
- String exceptionType = "GeneralException";
-
- str = CustomExceptionLoader.LookupMap(String.valueOf(sc), msg);
- log.info("Post CustomExceptionLoader.LookupMap" + str);
-
- if (str != null) {
-
- if (str[0].matches("SVC")) {
- exceptionType = "ServiceException";
- } else if (str[1].matches("POL")) {
- exceptionType = "PolicyException";
- }
-
- JSONObject jb = new JSONObject().put("requestError",
- new JSONObject().put(exceptionType, new JSONObject().put("MessagID", str[0]).put("text", str[1])));
-
- log.debug("Constructed json error : " + jb);
- ctx.response().sendErrorAndBody(sc, jb.toString(), MimeTypes.kAppJson);
- } else {
- JSONObject jb = new JSONObject().put("requestError",
- new JSONObject().put(exceptionType, new JSONObject().put("Status", sc).put("Error", msg)));
- ctx.response().sendErrorAndBody(sc, jb.toString(), MimeTypes.kAppJson);
- }
-
+ public static void respondWithCustomMsginJson(DrumlinRequestContext ctx, ApiException apiException) {
+ ctx.response()
+ .sendErrorAndBody(apiException.httpStatusCode,
+ apiException.toJSON().toString(), MimeTypes.kAppJson);
}
public static void safeClose(FileReader fr) {
diff --git a/src/test/java/org/onap/dcae/commonFunction/ApiExceptionTest.java b/src/test/java/org/onap/dcae/commonFunction/ApiExceptionTest.java new file mode 100644 index 00000000..0e494030 --- /dev/null +++ b/src/test/java/org/onap/dcae/commonFunction/ApiExceptionTest.java @@ -0,0 +1,66 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcaegen2.collectors.ves + * ================================================================================ + * Copyright (C) 2018 Nokia. All rights reserved. + * ================================================================================ + * Licensed 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. + * ============LICENSE_END========================================================= + */ +package org.onap.dcae.commonFunction; + +import static org.junit.Assert.assertEquals; + +import org.json.JSONObject; +import org.junit.Test; +import org.onap.dcae.restapi.ApiException; +import org.onap.dcae.restapi.ApiException.ExceptionType; + +/** + * @author Pawel Szalapski (pawel.szalapski@nokia.com) + */ +public class ApiExceptionTest { + + @Test + public void shouldStringifyServiceExceptionTypeAccordingToSpecification() { + assertEquals(ExceptionType.SERVICE_EXCEPTION.toString(), "ServiceException"); + } + + @Test + public void shouldStringifyPolicyExceptionTypeAccordingToSpecification() { + assertEquals(ExceptionType.POLICY_EXCEPTION.toString(), "PolicyException"); + } + + @Test + public void shouldConvertExceptionToBackwardCompatibleFormat() { + JSONObject responseBody = ApiException.UNAUTHORIZED_USER.toJSON(); + assertJSONEqual(responseBody, asJSON("" + + "{ " + + " 'requestError': { " + + " 'PolicyException': { " + + " 'messageId': 'POL2000', " + + " 'text': 'Unauthorized user' " + + " } " + + " } " + + "} " + )); + } + + private JSONObject asJSON(String jsonString) { + return new JSONObject(jsonString.replace("'", "\"")); + } + + private void assertJSONEqual(JSONObject o1, JSONObject o2) { + assertEquals(o1.toString(), o2.toString()); + } +} diff --git a/src/test/java/org/onap/dcae/vestest/TestCustomExceptionLoader.java b/src/test/java/org/onap/dcae/vestest/TestCustomExceptionLoader.java deleted file mode 100644 index 60d791cc..00000000 --- a/src/test/java/org/onap/dcae/vestest/TestCustomExceptionLoader.java +++ /dev/null @@ -1,61 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * PROJECT - * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed 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. - * ============LICENSE_END========================================================= - */ - -package org.onap.dcae.vestest; - -import static java.lang.String.format; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; -import static org.onap.dcae.commonFunction.CustomExceptionLoader.LookupMap; - -import com.att.nsa.drumlin.service.standards.HttpStatusCodes; -import org.junit.Test; -import org.onap.dcae.commonFunction.CommonStartup; -import org.onap.dcae.commonFunction.CustomExceptionLoader; - -public class TestCustomExceptionLoader { - - @Test - public void shouldLoadMapWithoutExceptions() { - CommonStartup.exceptionConfig = "./etc/ExceptionConfig.json"; - CustomExceptionLoader.LoadMap(); - } - - @Test - public void shouldLookupErrorMessageOutOfStatusCodeAndReason() { - // given - CommonStartup.exceptionConfig = "./etc/ExceptionConfig.json"; - CustomExceptionLoader.LoadMap(); - int statusCode = HttpStatusCodes.k401_unauthorized; - String message = "Unauthorized user"; - - // when - String[] retarray = LookupMap(String.valueOf(statusCode), message); - - // then - if (retarray == null) { - fail(format( - "Lookup failed, did not find value for a valid status code %s and message %s", statusCode, message)); - } else { - assertEquals("\"POL2000\"", retarray[0]); - } - } -} - |