Skip to content
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

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
6eb83b3
Modified generate's endpoint generate to accept array of events
shudhansu-shekhar Jun 19, 2024
d33c54c
Modified generate's endpoint generate to accept array of events
shudhansu-shekhar Jul 2, 2024
1476f2d
Modified generate's endpoint generate to accept array of events
shudhansu-shekhar Jul 9, 2024
e58d75b
Modified generate's endpoint generate to accept array of events
shudhansu-shekhar Jul 12, 2024
55d720d
Modified generate's endpoint generate to accept array of events
shudhansu-shekhar Jul 17, 2024
037c273
Modified generate's endpoint generate to accept array of events
shudhansu-shekhar Jul 22, 2024
89b52ef
Modified generate's endpoint generate to accept array of events
shudhansu-shekhar Jul 25, 2024
145f2b8
Modified generate's endpoint generate to accept array of events
shudhansu-shekhar Jul 26, 2024
dfa1799
Modified generate's endpoint generate to accept array of events
shudhansu-shekhar Jul 30, 2024
7ea6195
Modified generate's endpoint generate to accept array of events
shudhansu-shekhar Jul 30, 2024
3a3fd1c
Modified generate's endpoint generate to accept array of events
shudhansu-shekhar Aug 1, 2024
962cabb
Modified generate's endpoint generate to accept array of events
shudhansu-shekhar Aug 2, 2024
dbb2ed3
Modified generate's endpoint generate to accept array of events
shudhansu-shekhar Aug 5, 2024
ddca4e6
Modified generate's endpoint generate to accept array of events
shudhansu-shekhar Aug 8, 2024
b5ed6b4
Modified generate's endpoint generate to accept array of events
shudhansu-shekhar Aug 9, 2024
cd2a736
Modified generate's endpoint generate to accept array of events
shudhansu-shekhar Aug 12, 2024
6456f81
Modified generate's endpoint generate to accept array of events
shudhansu-shekhar Aug 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ public final class RemremGenerateServiceConstants {
public static final String NO_TEMPLATE_ERROR = "{\"status_code\": 404, \"result\": \"FAIL\", "
+ "\"message\":\"Requested template is not available\"}";

public static final String TEMPLATE_ERROR = "{\"status_code\": 400, \"result\": \"FAIL\", "
+ "\"message\":\"Template is not correct format or something is missing in the template, please check\"}";

public static final String INTERNAL_SERVER_ERROR = "{\"status_code\": 500, \"result\": \"FAIL\", "
+ "\"message\":\"Internal server error\"}";

Expand Down Expand Up @@ -54,4 +57,10 @@ public final class RemremGenerateServiceConstants {
public static final String LenientValidation = "okToLeaveOutInvalidOptionalFields true will remove the optional "
+ "event fields from the input event data that does not validate successfully, "
+ "and add those removed field information into customData/remremGenerateFailures";

public static final String JSON_STATUS_CODE = "status code";

public static final String JSON_STATUS_RESULT = "result";

public static final String META = "meta";
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.*;
Expand All @@ -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")
Expand Down Expand Up @@ -99,64 +98,158 @@ public void setRestTemplate(RestTemplate restTemplate) {
* <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"),
@ApiResponse(code = 400, message = "Malformed JSON"),
@ApiResponse(code = 500, message = "Internal server error"),
@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) {
JsonObject errorResponse = null;
try {
errorResponse = new JsonObject();
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 e) {
String exceptionMessage = e.getMessage();
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

log.error("Invalid JSON parse data format due to:", e.getMessage());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove ':'.

return createResponseEntity(HttpStatus.BAD_REQUEST,"Invalid JSON parse data format due to: " + exceptionMessage, "fatal",
errorResponse);
} catch (JsonProcessingException e) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think JsonSyntaxException and JsonProcessingException can be handled together. No need to distinguish between them.

String exceptionMessage = e.getMessage();
log.info("Incorrect Json data", exceptionMessage);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be log.error

return createResponseEntity(HttpStatus.BAD_REQUEST,"Incorrect Json data: " + exceptionMessage, "fatal",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Json -> JSON

errorResponse);
}
}

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();
JsonObject errorResponse = new JsonObject();
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<>("LookupLimit must be greater than or equals to 1", HttpStatus.BAD_REQUEST);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should createResponseEntity be used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't think here we need, here we just need to return one response not as many like in other scenerio

}
if (inputData == null) {
log.error("Json event must not be null");
errorResponse.addProperty(JSON_ERROR_MESSAGE_FIELD, "inputData must not be null");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should createResponseEntity be used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here as well

return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why to continue when inputData is null?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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);
}
if (!parsedResponse.getAsJsonObject().has(RemremGenerateServiceConstants.JSON_ERROR_MESSAGE_FIELD)) {
return new ResponseEntity<>(parsedResponse, HttpStatus.OK);
boolean success = true;
for (JsonElement result : generatedEventResults) {
JsonObject jsonObject = result.getAsJsonObject();
success &= jsonObject.has(META);
}
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);

if (processedJson.has(META)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle result as inside loop at line 162.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not getting clearly here,

return new ResponseEntity<>(processedJson, HttpStatus.OK);
}
if (processedJson.has(JSON_STATUS_CODE) && "400".equals(processedJson.get(JSON_STATUS_CODE).toString())) {
return new ResponseEntity<>(processedJson, HttpStatus.BAD_REQUEST);
} else {
return new ResponseEntity<>(parsedResponse, HttpStatus.BAD_REQUEST);
return new ResponseEntity<>(processedJson, HttpStatus.SERVICE_UNAVAILABLE);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This strange state should be logged.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah we can logged like this?

log.error("Unexpected error caught, due to service property is missing or wrong");

}

} else {
return new ResponseEntity<>(parser.parse(RemremGenerateServiceConstants.NO_SERVICE_ERROR),
HttpStatus.SERVICE_UNAVAILABLE);
return createResponseEntity(HttpStatus.BAD_REQUEST, "Invalid JSON format,expected either single template or array of templates",
"fail", errorResponse);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be a constant for "fail".

}
} 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);
} catch (REMGenerateException | JsonSyntaxException e) {
return handleException(e);
}
}

public ResponseEntity<JsonObject> createResponseEntity(HttpStatus status, String errorMessage, String resultMessage,
JsonObject errorResponse) {
initializeResponse(status, errorMessage, resultMessage, errorResponse);
return new ResponseEntity<>(errorResponse, status);
}

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);
}

private ResponseEntity<JsonObject> handleException(Exception e) {
JsonObject errorResponse = new JsonObject();
String exceptionMessage = e.getMessage();
if (e instanceof REMGenerateException) {
List<HttpStatus> statuses = List.of(
HttpStatus.NOT_ACCEPTABLE, HttpStatus.EXPECTATION_FAILED, HttpStatus.SERVICE_UNAVAILABLE, HttpStatus.UNPROCESSABLE_ENTITY
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Split the line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

);
for (HttpStatus status : statuses) {
if (exceptionMessage.contains(Integer.toString(status.value()))) {
Copy link
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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, e.getMessage(), "fail", errorResponse);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use constant for "fail". The same for lines 216 and 219.

}
}
else {
return new ResponseEntity<>(parser.parse(e1.getMessage()), HttpStatus.UNPROCESSABLE_ENTITY);
return createResponseEntity(HttpStatus.BAD_REQUEST, e.getMessage(), "fail", errorResponse);
} else if (e instanceof JsonSyntaxException) {
log.error("Failed to parse JSON: ", exceptionMessage);
return createResponseEntity(HttpStatus.BAD_REQUEST, e.getMessage(), "fail", errorResponse);
} else {
log.error("Unexpected exception caught", exceptionMessage);
return createResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR, exceptionMessage, "fail", errorResponse);
}
}

/**
* This helper method basically generate or process one event
* @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 {
JsonObject eventResponse = new JsonObject();
JsonElement parsedResponse;

JsonObject event = erLookup(jsonObject, failIfMultipleFound, failIfNoneFound, lookupInExternalERs, lookupLimit);
MsgService msgService = getMessageService(msgProtocol);

if (msgService != null) {
String response = msgService.generateMsg(msgType, event, isLenientEnabled(okToLeaveOutInvalidOptionalFields));
parsedResponse = JsonParser.parseString(response);
JsonObject parsedJson = parsedResponse.getAsJsonObject();

if (parsedJson.has(JSON_ERROR_MESSAGE_FIELD)) {
createResponseEntity(HttpStatus.BAD_REQUEST, "fail", TEMPLATE_ERROR, eventResponse);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use constants for "fail".

return eventResponse;
} else {
return parsedJson;
}
} catch (Exception e) {
log.error("Unexpected exception caught", e);
return new ResponseEntity<>(parser.parse(RemremGenerateServiceConstants.INTERNAL_SERVER_ERROR),
HttpStatus.INTERNAL_SERVER_ERROR);
}
return eventResponse;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot return an empty JSON object. Situation when msgService == null must be handled.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah right we can handle this in same as original one means the how it handle earlier right?

else {
return new ResponseEntity<>(parser.parse(RemremGenerateServiceConstants.NO_SERVICE_ERROR),
HttpStatus.SERVICE_UNAVAILABLE);
}

}

private JsonObject erLookup(final JsonObject bodyJson, Boolean failIfMultipleFound, Boolean failIfNoneFound,
Expand Down
Loading