-
Notifications
You must be signed in to change notification settings - Fork 70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Modified generate's endpoint generate to accept array of events #226
Changes from 9 commits
6eb83b3
d33c54c
1476f2d
e58d75b
55d720d
037c273
89b52ef
145f2b8
dfa1799
7ea6195
3a3fd1c
962cabb
dbb2ed3
ddca4e6
b5ed6b4
cd2a736
6456f81
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,12 +18,12 @@ | |
import com.ericsson.eiffel.remrem.generate.constants.RemremGenerateServiceConstants; | ||
import com.ericsson.eiffel.remrem.generate.exception.REMGenerateException; | ||
import com.ericsson.eiffel.remrem.protocol.MsgService; | ||
import com.google.gson.Gson; | ||
import com.google.gson.GsonBuilder; | ||
import com.google.gson.JsonArray; | ||
import com.google.gson.JsonElement; | ||
import com.google.gson.JsonObject; | ||
import com.google.gson.JsonParser; | ||
import com.fasterxml.jackson.core.JsonFactory; | ||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.JsonMappingException; | ||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.google.gson.*; | ||
|
||
import ch.qos.logback.classic.Logger; | ||
import io.swagger.annotations.*; | ||
|
@@ -46,14 +46,13 @@ | |
|
||
import springfox.documentation.annotations.ApiIgnore; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.FileInputStream; | ||
import java.io.IOException; | ||
import java.io.InputStreamReader; | ||
import java.io.*; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Map.Entry; | ||
|
||
import static com.ericsson.eiffel.remrem.generate.constants.RemremGenerateServiceConstants.*; | ||
|
||
@RestController | ||
@RequestMapping("/*") | ||
@Api(value = "REMReM Generate Service", description = "REST API for generating Eiffel messages") | ||
|
@@ -78,84 +77,221 @@ public class RemremGenerateController { | |
private boolean lenientValidationEnabledToUsers; | ||
|
||
public void setLenientValidationEnabledToUsers(boolean lenientValidationEnabledToUsers) { | ||
this.lenientValidationEnabledToUsers = lenientValidationEnabledToUsers; | ||
} | ||
this.lenientValidationEnabledToUsers = lenientValidationEnabledToUsers; | ||
} | ||
|
||
private static RestTemplate restTemplate = new RestTemplate(); | ||
private static RestTemplate restTemplate = new RestTemplate(); | ||
|
||
public void setRestTemplate(RestTemplate restTemplate) { | ||
this.restTemplate = restTemplate; | ||
} | ||
|
||
/** | ||
* Returns event information as json element based on the message protocol, | ||
* taking message type and json body as input. | ||
* <p> | ||
* taking message type and json body of string type as input because just to parse | ||
* the string in to JsonElement not using JsonElement directly here. | ||
* | ||
* <p> | ||
* Parameters: msgProtocol - The message protocol, which tells us which | ||
* service to invoke. msgType - The type of message that needs to be | ||
* generated. bodyJson - The content of the message which is used in | ||
* generated. body - The content of the message which is used in | ||
* creating the event details. | ||
* <p> | ||
* Returns: The event information as a json element | ||
*/ | ||
|
||
@ApiOperation(value = "To generate eiffel event based on the message protocol", response = String.class) | ||
@ApiResponses(value = { @ApiResponse(code = 200, message = "Event sent successfully"), | ||
@ApiResponses(value = {@ApiResponse(code = 200, message = "Event sent successfully"), | ||
@ApiResponse(code = 400, message = "Malformed JSON"), | ||
@ApiResponse(code = 500, message = "Internal server error"), | ||
@ApiResponse(code = 503, message = "Message protocol is invalid") }) | ||
@ApiResponse(code = 503, message = "Message protocol is invalid")}) | ||
@RequestMapping(value = "/{mp" + REGEX + "}", method = RequestMethod.POST) | ||
public ResponseEntity<?> generate( | ||
@ApiParam(value = "message protocol", required = true) @PathVariable("mp") final String msgProtocol, | ||
@ApiParam(value = "message type", required = true) @RequestParam("msgType") final String msgType, | ||
@ApiParam(value = "ER lookup result multiple found, Generate will fail") @RequestParam(value = "failIfMultipleFound", required = false, defaultValue = "false") final Boolean failIfMultipleFound, | ||
@ApiParam(value = "ER lookup result none found, Generate will fail") @RequestParam(value = "failIfNoneFound", required = false, defaultValue = "false") final Boolean failIfNoneFound, | ||
@ApiParam(value = RemremGenerateServiceConstants.LOOKUP_IN_EXTERNAL_ERS) @RequestParam(value = "lookupInExternalERs", required = false, defaultValue = "false") final Boolean lookupInExternalERs, | ||
@ApiParam(value = RemremGenerateServiceConstants.LOOKUP_LIMIT) @RequestParam(value = "lookupLimit", required = false, defaultValue = "1") final int lookupLimit, | ||
@ApiParam(value = RemremGenerateServiceConstants.LenientValidation) @RequestParam(value = "okToLeaveOutInvalidOptionalFields", required = false, defaultValue = "false") final Boolean okToLeaveOutInvalidOptionalFields, | ||
@ApiParam(value = "JSON message", required = true) @RequestBody JsonObject bodyJson) { | ||
public ResponseEntity<?> generate(@ApiParam(value = "message protocol", required = true) @PathVariable("mp") final String msgProtocol, | ||
@ApiParam(value = "message type", required = true) @RequestParam("msgType") final String msgType, | ||
@ApiParam(value = "ER lookup result multiple found, Generate will fail") @RequestParam(value = "failIfMultipleFound", required = false, defaultValue = "false") final Boolean failIfMultipleFound, | ||
@ApiParam(value = "ER lookup result none found, Generate will fail") @RequestParam(value = "failIfNoneFound", required = false, defaultValue = "false") final Boolean failIfNoneFound, | ||
@ApiParam(value = RemremGenerateServiceConstants.LOOKUP_IN_EXTERNAL_ERS) @RequestParam(value = "lookupInExternalERs", required = false, defaultValue = "false") final Boolean lookupInExternalERs, | ||
@ApiParam(value = RemremGenerateServiceConstants.LOOKUP_LIMIT) @RequestParam(value = "lookupLimit", required = false, defaultValue = "1") final int lookupLimit, | ||
@ApiParam(value = RemremGenerateServiceConstants.LenientValidation) @RequestParam(value = "okToLeaveOutInvalidOptionalFields", required = false, defaultValue = "false") final Boolean okToLeaveOutInvalidOptionalFields, | ||
@ApiParam(value = "JSON message", required = true) @RequestBody String body) { | ||
try { | ||
JsonFactory jsonFactory = JsonFactory.builder().build().enable(com.fasterxml.jackson.core.JsonParser | ||
.Feature.STRICT_DUPLICATE_DETECTION); | ||
ObjectMapper mapper = new ObjectMapper(jsonFactory); | ||
JsonNode node = mapper.readTree(body); | ||
Gson gson = new Gson(); | ||
JsonElement inputJson = gson.fromJson(node.toString(), JsonElement.class); | ||
return generate(msgProtocol, msgType, failIfMultipleFound, failIfNoneFound, lookupInExternalERs, | ||
lookupLimit, okToLeaveOutInvalidOptionalFields, inputJson); | ||
} catch (JsonSyntaxException | JsonProcessingException e) { | ||
String exceptionMessage = e.getMessage(); | ||
log.error("Invalid JSON parse data format due to", e.getMessage()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use exceptionMessage instead of e.getMessage(). |
||
return createResponseEntity(HttpStatus.BAD_REQUEST, "Invalid JSON parse data format due to: " | ||
+ exceptionMessage, JSON_FATAL_STATUS); | ||
} | ||
} | ||
|
||
/** | ||
* Returns event information as json element based on the message protocol, | ||
* taking message type and json body as input | ||
* Here we basically add this to handle if inputData is of jsonArray type as well | ||
* <p> | ||
* Parameters: msgProtocol - The message protocol, which tells us which | ||
* service to invoke. msgType - The type of message that needs to be | ||
* generated. inputData - The content of the message which is used in | ||
* creating the event details. | ||
* <p> | ||
* Returns: The event information as a json element | ||
*/ | ||
public ResponseEntity<?> generate(final String msgProtocol, final String msgType, final Boolean failIfMultipleFound, | ||
final Boolean failIfNoneFound, final Boolean lookupInExternalERs, final int lookupLimit, | ||
final Boolean okToLeaveOutInvalidOptionalFields, JsonElement inputData) { | ||
|
||
JsonArray generatedEventResults = new JsonArray(); | ||
try { | ||
bodyJson = erLookup(bodyJson, failIfMultipleFound, failIfNoneFound, lookupInExternalERs, lookupLimit); | ||
MsgService msgService = getMessageService(msgProtocol); | ||
String response; | ||
if (msgService != null) { | ||
response = msgService.generateMsg(msgType, bodyJson, isLenientEnabled(okToLeaveOutInvalidOptionalFields)); | ||
JsonElement parsedResponse = parser.parse(response); | ||
if(lookupLimit <= 0) { | ||
return new ResponseEntity<>("LookupLimit must be greater than or equals to 1", HttpStatus.BAD_REQUEST); | ||
if (lookupLimit <= 0) { | ||
return new ResponseEntity<>("Parameter 'lookupLimit' must be > 0", HttpStatus.BAD_REQUEST); | ||
} | ||
if (inputData == null) { | ||
return createResponseEntity(HttpStatus.BAD_REQUEST, "Parameter 'inputData' must not be null", | ||
JSON_ERROR_STATUS); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why to continue when inputData is null? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
||
if (inputData.isJsonArray()) { | ||
JsonArray inputEventJsonArray = inputData.getAsJsonArray(); | ||
for (JsonElement element : inputEventJsonArray) { | ||
JsonObject generatedEvent = (processEvent(msgProtocol, msgType, | ||
failIfMultipleFound, failIfNoneFound, lookupInExternalERs, lookupLimit, | ||
okToLeaveOutInvalidOptionalFields, element.getAsJsonObject())); | ||
generatedEventResults.add(generatedEvent); | ||
} | ||
boolean success = true; | ||
for (JsonElement result : generatedEventResults) { | ||
JsonObject jsonObject = result.getAsJsonObject(); | ||
success &= jsonObject.has(META); | ||
} | ||
if (!parsedResponse.getAsJsonObject().has(RemremGenerateServiceConstants.JSON_ERROR_MESSAGE_FIELD)) { | ||
return new ResponseEntity<>(parsedResponse, HttpStatus.OK); | ||
return new ResponseEntity<>(generatedEventResults, success ? HttpStatus.OK : HttpStatus.BAD_REQUEST); | ||
|
||
} else if (inputData.isJsonObject()) { | ||
JsonObject inputJsonObject = inputData.getAsJsonObject(); | ||
JsonObject processedJson = processEvent(msgProtocol, msgType, failIfMultipleFound, failIfNoneFound, | ||
lookupInExternalERs, lookupLimit, okToLeaveOutInvalidOptionalFields, inputJsonObject); | ||
HttpStatus status; | ||
String statusValue = null; | ||
if (processedJson.has(META)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle result as inside loop at line 162. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not getting clearly here, |
||
status = HttpStatus.OK; | ||
return new ResponseEntity<>(processedJson, status); | ||
} else if (processedJson.has(JSON_STATUS_CODE)) { | ||
statusValue = processedJson.get(JSON_STATUS_CODE).toString(); | ||
try { | ||
status = HttpStatus.resolve(Integer.parseInt(statusValue)); | ||
return new ResponseEntity<>(processedJson, status); | ||
} catch (NumberFormatException e) { | ||
log.error("Invalid status value: '" + statusValue + "' of response " + processedJson); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why to compose the same string twice? Store it in a variable and reuse it. The same 195 and 196. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can do like this? else { There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that's perfect solution. |
||
return createResponseEntity(HttpStatus.BAD_REQUEST, "Invalid status value: '" | ||
+ statusValue + "' of response " + processedJson, JSON_ERROR_STATUS); | ||
} | ||
} else { | ||
return new ResponseEntity<>(parsedResponse, HttpStatus.BAD_REQUEST); | ||
log.error("There is no status value: '" + statusValue + "' in the response" + processedJson); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing a space after 'response'. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
OK |
||
return createResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR, "There is no status value: '" | ||
+ statusValue + "' in the response " + processedJson, JSON_ERROR_STATUS); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. statusValue is always null here. You should move its declaration from 180 to 185. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK |
||
} | ||
} else { | ||
return new ResponseEntity<>(parser.parse(RemremGenerateServiceConstants.NO_SERVICE_ERROR), | ||
HttpStatus.SERVICE_UNAVAILABLE); | ||
} | ||
} catch (REMGenerateException e1) { | ||
if (e1.getMessage().contains(Integer.toString(HttpStatus.NOT_ACCEPTABLE.value()))) { | ||
return new ResponseEntity<>(parser.parse(e1.getMessage()), HttpStatus.NOT_ACCEPTABLE); | ||
} | ||
else if (e1.getMessage().contains(Integer.toString(HttpStatus.EXPECTATION_FAILED.value()))) { | ||
return new ResponseEntity<>(parser.parse(e1.getMessage()), HttpStatus.EXPECTATION_FAILED); | ||
} | ||
else if (e1.getMessage().contains(Integer.toString(HttpStatus.EXPECTATION_FAILED.value()))) { | ||
return new ResponseEntity<>(parser.parse(e1.getMessage()), HttpStatus.EXPECTATION_FAILED); | ||
} | ||
else if (e1.getMessage() | ||
.contains(Integer.toString(HttpStatus.SERVICE_UNAVAILABLE.value()))) { | ||
return new ResponseEntity<>(parser.parse(RemremGenerateServiceConstants.NO_ER), | ||
HttpStatus.SERVICE_UNAVAILABLE); | ||
return createResponseEntity(HttpStatus.BAD_REQUEST, | ||
"Invalid JSON format,expected either single template or array of templates", | ||
JSON_ERROR_STATUS); | ||
} | ||
else { | ||
return new ResponseEntity<>(parser.parse(e1.getMessage()), HttpStatus.UNPROCESSABLE_ENTITY); | ||
} catch (REMGenerateException | JsonSyntaxException e) { | ||
return handleException(e); | ||
} | ||
} | ||
|
||
|
||
/** | ||
* To display response in browser or application | ||
* @param status response code for the HTTP request | ||
* @param responseMessage the message according to response | ||
* @param resultMessage whatever the result this message gives you idea about that | ||
* @param errorResponse is to collect all the responses here. | ||
* @return ResponseEntity | ||
*/ | ||
public ResponseEntity<JsonObject> createResponseEntity(HttpStatus status, String responseMessage, String resultMessage, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The method should be also available in form createResponseEntity(HttpStatus, String, String) because errorResponse is usually passed as an empty object. Thus, it can be created internally. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i don't think it is necessary here because we need to store error many responses in one jsonobject , so we need this externally here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please, dont' forget about this one. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
JsonObject errorResponse) { | ||
initializeResponse(status, responseMessage, resultMessage, errorResponse); | ||
return new ResponseEntity<>(errorResponse, status); | ||
} | ||
public ResponseEntity<JsonObject> createResponseEntity(HttpStatus status, String responseMessage, String resultMessage) { | ||
return createResponseEntity(status, responseMessage, resultMessage, new JsonObject()); | ||
} | ||
|
||
public void initializeResponse(HttpStatus status, String errorMessage, String resultMessage, JsonObject errorResponse) { | ||
errorResponse.addProperty(JSON_STATUS_CODE, status.value()); | ||
errorResponse.addProperty(JSON_STATUS_RESULT, resultMessage); | ||
errorResponse.addProperty(JSON_ERROR_MESSAGE_FIELD, errorMessage); | ||
} | ||
|
||
/** | ||
* To handle the exception in one method | ||
* @param e taken general exception here | ||
* @return ResponseEntity | ||
*/ | ||
private ResponseEntity<JsonObject> handleException(Exception e) { | ||
String exceptionMessage = e.getMessage(); | ||
if (e instanceof REMGenerateException) { | ||
List<HttpStatus> statuseList = List.of( | ||
shudhansu-shekhar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
HttpStatus.NOT_ACCEPTABLE, HttpStatus.EXPECTATION_FAILED, HttpStatus.SERVICE_UNAVAILABLE, | ||
HttpStatus.UNPROCESSABLE_ENTITY | ||
); | ||
for (HttpStatus status : statuseList) { | ||
if (exceptionMessage.contains(Integer.toString(status.value()))) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess there should be more strict test, not just test for occurrence in message. The message is a JSON data. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah but whatever the test is handled by these exception error, it is same like as earlier.. |
||
return createResponseEntity(status, exceptionMessage, JSON_ERROR_STATUS); | ||
} | ||
} | ||
} catch (Exception e) { | ||
log.error("Unexpected exception caught", e); | ||
return new ResponseEntity<>(parser.parse(RemremGenerateServiceConstants.INTERNAL_SERVER_ERROR), | ||
HttpStatus.INTERNAL_SERVER_ERROR); | ||
return createResponseEntity(HttpStatus.BAD_REQUEST, exceptionMessage, JSON_ERROR_STATUS); | ||
} else if (e instanceof JsonSyntaxException) { | ||
log.error("Failed to parse JSON", exceptionMessage); | ||
return createResponseEntity(HttpStatus.BAD_REQUEST, exceptionMessage, JSON_ERROR_STATUS); | ||
} else { | ||
log.error("Unexpected exception caught", exceptionMessage); | ||
return createResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR, exceptionMessage, JSON_ERROR_STATUS); | ||
} | ||
} | ||
|
||
/** | ||
* This helper method basically generate or process single event | ||
* @param msgProtocol The message protocol, which tells us which service to invoke | ||
* @param msgType The type of message that needs to be generated. inputData | ||
* @param failIfMultipleFound | ||
* @param failIfNoneFound | ||
* @param lookupInExternalERs | ||
* @param lookupLimit | ||
* @param okToLeaveOutInvalidOptionalFields | ||
* @param jsonObject The content of the message which is used in creating the event details. | ||
* @return JsonObject generated event | ||
*/ | ||
|
||
public JsonObject processEvent(String msgProtocol, String msgType, Boolean failIfMultipleFound, | ||
Boolean failIfNoneFound, Boolean lookupInExternalERs, int lookupLimit, | ||
Boolean okToLeaveOutInvalidOptionalFields, JsonObject jsonObject) throws REMGenerateException, JsonSyntaxException { | ||
JsonElement parsedResponse; | ||
|
||
JsonObject event = erLookup(jsonObject, failIfMultipleFound, failIfNoneFound, lookupInExternalERs, lookupLimit); | ||
MsgService msgService = getMessageService(msgProtocol); | ||
|
||
if (msgService == null) { | ||
return createResponseEntity(HttpStatus.SERVICE_UNAVAILABLE, | ||
"No protocol service has been found registered", JSON_ERROR_STATUS).getBody(); | ||
} | ||
String response = msgService.generateMsg(msgType, event, isLenientEnabled(okToLeaveOutInvalidOptionalFields)); | ||
parsedResponse = JsonParser.parseString(response); | ||
JsonObject parsedJson = parsedResponse.getAsJsonObject(); | ||
|
||
if (parsedJson.has(JSON_ERROR_MESSAGE_FIELD)) { | ||
JsonObject eventResponse = new JsonObject(); | ||
createResponseEntity(HttpStatus.BAD_REQUEST, JSON_ERROR_STATUS, TEMPLATE_ERROR, eventResponse); | ||
return eventResponse; | ||
} else { | ||
return parsedJson; | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use exceptionMessage at line 122, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done