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 9 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,14 @@ 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";

public static final String JSON_ERROR_STATUS = "fail";

public static final String JSON_FATAL_STATUS = "fatal";
}
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 All @@ -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();
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.

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

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);
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 compose the same string twice? Store it in a variable and reuse it. The same 195 and 196.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can do like this?

else {
String errorMessage = "There is no status value in the response " + processedJson;
log.error(errorMessage);
return createResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR, errorMessage, JSON_ERROR_STATUS);
}

Copy link
Contributor

Choose a reason for hiding this comment

The 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);
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing a space after 'response'.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Missing a space after 'response'.

OK

return createResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR, "There is no status value: '"
+ statusValue + "' in the response " + processedJson, JSON_ERROR_STATUS);
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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,
Copy link
Contributor

Choose a reason for hiding this comment

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

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 it is necessary here because we need to store error many responses in one jsonobject , so we need this externally here

Copy link
Contributor

Choose a reason for hiding this comment

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

Please, dont' forget about this one.

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

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()))) {
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, 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;
}
}

Expand Down
Loading