Skip to content

Modified endpoint generateAndPublish to accept array of events #294

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

Merged
merged 13 commits into from
Aug 16, 2024

Conversation

shudhansu-shekhar
Copy link
Contributor

@shudhansu-shekhar shudhansu-shekhar commented Jun 10, 2024

Applicable Issues

Description of the Change

In this after these changes, publish service generateAndPublish endpoint accept array of events

Alternate Designs

Possible Drawbacks

Sign-off

Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or

(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or

(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.

(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.

Signed-off-by: shudhansu.shekhar.ext@ericsson.com

}
}
} else {
return new ResponseEntity<>("Invalid event content", 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.

Can user understand what is wrong?

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
HttpEntity<String> entity = new HttpEntity<>(bodyJsonOut, headers);
EnumSet<HttpStatus> getStatus = EnumSet.of(HttpStatus.SERVICE_UNAVAILABLE, HttpStatus.UNAUTHORIZED, HttpStatus.NOT_ACCEPTABLE, HttpStatus.EXPECTATION_FAILED, HttpStatus.INTERNAL_SERVER_ERROR, 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.

Why you create a const object over and over?

String generateUrl = generateURLTemplate.getUrl() + "&failIfMultipleFound=" + failIfMultipleFound
+ "&failIfNoneFound=" + failIfNoneFound + "&lookupInExternalERs=" + lookupInExternalERs
+ "&lookupLimit=" + lookupLimit + "&okToLeaveOutInvalidOptionalFields=" + okToLeaveOutInvalidOptionalFields;
ResponseEntity<String> response = restTemplate.postForEntity(generateUrl,
Copy link
Contributor

Choose a reason for hiding this comment

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

Why send just one vent to generate service? There's generate endpoint accepting array of events. This restores the former behaviour: a network connection per event.

} catch (JsonSyntaxException e) {
JsonObject errorResponse = new JsonObject();
log.error("Unexpected exception caught due to parse json data", e.getMessage());
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 above.

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("Unexpected exception caught due to parse json data", e.getMessage());
String exceptionMessage = e.getMessage();
errorResponse.addProperty("Status code", HttpStatus.BAD_REQUEST.value());
errorResponse.addProperty("result", "Fatal");
Copy link
Contributor

Choose a reason for hiding this comment

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

Upper-case vs. lower-case property names. Remember, JSON is case-sensitive. If the case is mismatched, user's handlers may not work properly. Define constants for property names.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes

if (element.isJsonObject()) {
events.add(element.getAsJsonObject());
} else {
return new ResponseEntity<>("Invalid events content or format", 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 not to say directly: "Array item must be a JSON object"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes we can do like that

}
}
} else {
return new ResponseEntity<>("Invalid, event is not in the correct format", 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.

Again, very confusing message. Inform directly what went wrong.

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

headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
HttpEntity<String> entity = new HttpEntity<>(bodyJsonOut, headers);
EnumSet<HttpStatus> getStatus = EnumSet.of(HttpStatus.SERVICE_UNAVAILABLE, HttpStatus.UNAUTHORIZED, HttpStatus.NOT_ACCEPTABLE, HttpStatus.EXPECTATION_FAILED, HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.UNPROCESSABLE_ENTITY);
// -- parse params in incoming request -> body -------------
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the comment still valid?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes

// publishing requires an array if you want status code
String responseBody = "[" + response.getBody() + "]";
MsgService msgService = PublishUtils.getMessageService(msgProtocol, msgServices);
JsonArray responseArray = JsonParser.parseString(response.getBody()).getAsJsonArray();
Copy link
Contributor

Choose a reason for hiding this comment

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

What if getJsonArray() fails?

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 from his documentation, it seems it will throw exception with message like Not a JSON Array

}

synchronized (this) {
JsonObject jsonObject = jsonResponse.getAsJsonObject();
Copy link
Contributor

Choose a reason for hiding this comment

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

What if getJsonObject() fails?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

By his method documentation, it seems it will throw exception with message like not a jsonObject

}
} else {
return response;
return new ResponseEntity<>("Invalid Json event content", 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 not to forward the message obtained from generate service?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes we can do but in the else part not sure ,for some reason event processing failed so we should notify user with detailed or more failed info right?

try {
return jsonObject.has("meta") && jsonObject.has("data") &&
jsonObject.has("links") && !jsonObject.has("Status code");
} catch (Exception e) {
Copy link
Contributor

Choose a reason for hiding this comment

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

When this exception can be thrown?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This exception throw for various reason like if there is any incorrect json structure, unexpected data types etc

Comment on lines +203 to +204
return generateAndPublish(msgProtocol, msgType, userDomain, tag, routingKey, parseData, failIfMultipleFound,
failIfNoneFound, lookupInExternalERs, lookupLimit, okToLeaveOutInvalidOptionalFields, bodyJson);

Check warning

Code scanning / CodeQL

Cross-site scripting Medium

Cross-site scripting vulnerability due to a
user-provided value
.
eventResponse = new HashMap<>();
JsonElement jsonResponseEvent = element.getAsJsonArray().get(i);
if (isValid(jsonResponseEvent)) {
synchronized (this) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why the same code starts at line 314?

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 put it one helper method


private Boolean isValid(JsonElement jsonObject) {
try {
return jsonObject.getAsJsonObject().has("meta") && jsonObject.getAsJsonObject().has("data") &&
Copy link
Contributor

Choose a reason for hiding this comment

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

getAsJsonObject() used over and over.

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 make one simple method for this


private Boolean isValid(JsonElement jsonObject) {
try {
return jsonObject.getAsJsonObject().has("meta") && jsonObject.getAsJsonObject().has("data") &&
Copy link
Contributor

Choose a reason for hiding this comment

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

Replace "meta", ... by constants.

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

try {
return jsonObject.getAsJsonObject().has("meta") && jsonObject.getAsJsonObject().has("data") &&
jsonObject.getAsJsonObject().has("links") && !jsonObject.getAsJsonObject().has("Status code");
} catch (Exception e) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't handle general exception.

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

@ApiParam(value = "JSON message", required = true) @RequestBody final String body){

try {
JsonElement bodyJson = JsonParser.parseString(body);
Copy link
Contributor

Choose a reason for hiding this comment

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

Should JSON parser be configured as in case of Generate service, i.e. not allowing duplicate keys, etc.?

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 can do this but why we need this here? Is it necessary if already there is check for correct event publishing means like incorrect event is not published on mb basically

Copy link
Contributor

Choose a reason for hiding this comment

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

OK, so we have the check in generator, right?

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, so we have the check in generator, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes that duplicate key check we implement basically in generate

Copy link
Contributor

@z-sztrom z-sztrom left a comment

Choose a reason for hiding this comment

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

  • When generate service is down, the following error message is displayed
    {
    "timestamp": "Jul 29, 2024, 1:05:51 PM",
    "status": 500,
    "error": "Internal Server Error",
    "path": "/generateAndPublish"
    }
    It should say clearly what's wrong

  • When an error is reported
    {
    "status message": {
    "status code": 400,
    "result": "{"status_code": 400, "result": "FAIL", "message":"Template is not correct format or something is missing in the template, please check"}",
    "message": "fail"
    }
    Value of result shouldn't be escaped. Value of a property can be JSON object.

  • The error message above: failure is should be unified, i.e. "FAIL" vs. "fail".

Copy link
Contributor

@z-sztrom z-sztrom left a comment

Choose a reason for hiding this comment

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

Please, add comment like "Done" or "Resolved" to resolved comments.

@@ -88,7 +88,9 @@ public class ProducerController {

public final String JSON_EVENT_MESSAGE_FIELD = "status message";

public final String JSON_EVENT_STATUS_VALUE = "status";
public final String STATUS_CODE = "Status code";
Copy link
Contributor

Choose a reason for hiding this comment

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

Why upper-case 'S'? Other properties are lower-case.

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 need this Uppercase 'S' here

} else if (bodyJson.isJsonArray()) {
for (JsonElement element : bodyJson.getAsJsonArray()) {
if (element.isJsonObject()) {
events.add(element.getAsJsonObject());
events.add(getAsJsonObject(element));
} else {
return new ResponseEntity<>("Invalid, array events must be a JSON object", 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.

I think there should be createResponesEntity method available.

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

@@ -223,11 +225,11 @@ public ResponseEntity generateAndPublish(final String msgProtocol, final String
MsgService msgService = PublishUtils.getMessageService(msgProtocol, msgServices);
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we continue if msgService == 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.

no we can do it here just like we do in generate ok?

if (msgService == null) {
return createResponseEntity(HttpStatus.SERVICE_UNAVAILABLE,
"No protocol service has been found registered", JSON_ERROR_STATUS).getBody();
}

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 how it should work.

@@ -284,25 +286,8 @@ public ResponseEntity generateAndPublish(final String msgProtocol, final String
if (msgService != null && msgProtocol != null) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is msgServcie set to rmqHelper repeatedly?

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 it seems set only once not repeatedly, please clear if i am wrong here

List<Map<String, Object>> responseEvent = new ArrayList<>();
Map<String, Object> eventResponse;
JsonElement element = JsonParser.parseString(eventMsg);
for (int i = 0; i < element.getAsJsonArray().size(); i++) {
Copy link
Contributor

Choose a reason for hiding this comment

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

What is element isn't an array?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Basically here eventMsg is a response body of string type

JsonElement element = JsonParser.parseString(eventMsg);
for (int i = 0; i < element.getAsJsonArray().size(); i++) {
eventResponse = new HashMap<>();
JsonElement jsonResponseEvent = element.getAsJsonArray().get(i);
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 call getAsJsonArray() in each iteration?

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 i put in one variable, use that one in each iteration right?

JsonElement jsonResponseEvent = element.getAsJsonArray().get(i);
if (isValid(jsonResponseEvent)) {
synchronized (this) {
JsonObject validResponse = jsonResponseEvent.getAsJsonObject();
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it guaranteed that validResponse is non-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.

Yeah we can add check before doing this process like that ?

if (eventResponseMessage == null){
eventResponse.put("Parameter 'eventResponseMessage' must not be null", 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.

I don't mean eventResponseMessage, I mean validResponse.

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 here 'validResponse' is extracting from 'eventResponseMessage' So if this 'eventResponseMessage' is not null then validResponse will also not null because there is not much changes between that

return jsonObject.getAsJsonObject().has("meta") && jsonObject.getAsJsonObject().has("data") &&
jsonObject.getAsJsonObject().has("links") && !jsonObject.getAsJsonObject().has("Status code");
} catch (Exception e) {
return getAsJsonObject(jsonElement).has(META) && getAsJsonObject(jsonElement).has("data") &&
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 instead of hard-coded values, i.e. "data" and "links". There're constants defined in Event class or somewhere...

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 i do that but i need defined that with in this class...There is no separate class for constant as in generate

private Boolean isValid(JsonElement jsonElement) {
try {
return getAsJsonObject(jsonElement).has(META) && getAsJsonObject(jsonElement).has("data") &&
getAsJsonObject(jsonElement).has("links") && !getAsJsonObject(jsonElement).has(STATUS_CODE);
return getAsJsonObject(jsonElement).has(META) && getAsJsonObject(jsonElement).has(DATA) &&
Copy link
Contributor

Choose a reason for hiding this comment

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

As I wrote, use existing constants defined for event properties instead of defining new ones.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

no there is not any existing constant, i have to define new one

Map<String, Object> eventResponse = null;

if (eventResponseMessage == null) {
eventResponse.put("Parameter 'eventResponseMessage' must not be null", 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.

This is response to end user. How the user knows what 'eventResponseMessage' is?

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 so we can put it like that?

eventResponse.put("Parameter 'eventResponseMessage' that is response generated by generate must not be null",
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.

I'd write something like 'Missing response from 'generate' service.'

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

return responseEvent;
}
JsonElement eventElement = JsonParser.parseString(eventResponseMessage);
JsonArray eventArray = eventElement.getAsJsonArray();
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it guaranteed that eventElement is an array?

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 i check it and it seems eventElement is an array, if you want i can show

Copy link
Contributor

Choose a reason for hiding this comment

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

I can't see that...

try {
return getAsJsonObject(jsonElement).has(META) && getAsJsonObject(jsonElement).has(DATA) &&
getAsJsonObject(jsonElement).has(LINKS) && !getAsJsonObject(jsonElement).has(STATUS_CODE);
getAsJsonObject(jsonElement).has(LINKS) && !getAsJsonObject(jsonElement).has(JSON_STATUS_CODE);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why the same code 'getAsJsonObject(jsonElement)' repeats 4 times?

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

try {
return getAsJsonObject(jsonElement).has(META) && getAsJsonObject(jsonElement).has(DATA) &&
getAsJsonObject(jsonElement).has(LINKS) && !getAsJsonObject(jsonElement).has(STATUS_CODE);
getAsJsonObject(jsonElement).has(LINKS) && !getAsJsonObject(jsonElement).has(JSON_STATUS_CODE);
} catch (IllegalStateException e) {
log.error("Error while validating event: ", 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.

Event ID should be published whenever a message related to event is produced.

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 but i am not getting any scope or need might be here, might be i am wrong?

Copy link
Contributor

Choose a reason for hiding this comment

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

Something like ...get(META).get(ID), but I haven't checked...

Copy link
Contributor Author

@shudhansu-shekhar shudhansu-shekhar Aug 2, 2024

Choose a reason for hiding this comment

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

Yeah it can do like this but not sure about the place you suggest to put not sure it will benefit anyway or not but yeah we can discuss once

Copy link
Contributor Author

@shudhansu-shekhar shudhansu-shekhar left a comment

Choose a reason for hiding this comment

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

please check my comment

if (element.isJsonObject()) {
events.add(element.getAsJsonObject());
} else {
return new ResponseEntity<>("Invalid events content or format", HttpStatus.BAD_REQUEST);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes we can do like that

}
}
} else {
return new ResponseEntity<>("Invalid, event is not in the correct format", HttpStatus.BAD_REQUEST);
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

// publishing requires an array if you want status code
String responseBody = "[" + response.getBody() + "]";
MsgService msgService = PublishUtils.getMessageService(msgProtocol, msgServices);
JsonArray responseArray = JsonParser.parseString(response.getBody()).getAsJsonArray();
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 from his documentation, it seems it will throw exception with message like Not a JSON Array

}
} else {
return response;
return new ResponseEntity<>("Invalid Json event content", HttpStatus.BAD_REQUEST);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes we can do but in the else part not sure ,for some reason event processing failed so we should notify user with detailed or more failed info right?

try {
return jsonObject.has("meta") && jsonObject.has("data") &&
jsonObject.has("links") && !jsonObject.has("Status code");
} catch (Exception e) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This exception throw for various reason like if there is any incorrect json structure, unexpected data types etc

return responseEvent;
}
JsonElement eventElement = JsonParser.parseString(eventResponseMessage);
JsonArray eventArray = eventElement.getAsJsonArray();
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 i check it and it seems eventElement is an array, if you want i can show

try {
return getAsJsonObject(jsonElement).has(META) && getAsJsonObject(jsonElement).has(DATA) &&
getAsJsonObject(jsonElement).has(LINKS) && !getAsJsonObject(jsonElement).has(STATUS_CODE);
getAsJsonObject(jsonElement).has(LINKS) && !getAsJsonObject(jsonElement).has(JSON_STATUS_CODE);
} catch (IllegalStateException e) {
log.error("Error while validating event: ", e.getMessage());
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 but i am not getting any scope or need might be here, might be i am wrong?

try {
return getAsJsonObject(jsonElement).has(META) && getAsJsonObject(jsonElement).has(DATA) &&
getAsJsonObject(jsonElement).has(LINKS) && !getAsJsonObject(jsonElement).has(STATUS_CODE);
getAsJsonObject(jsonElement).has(LINKS) && !getAsJsonObject(jsonElement).has(JSON_STATUS_CODE);
} catch (IllegalStateException e) {
log.error("Error while validating event: ", e.getMessage());
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 but i am not getting any scope or need might be here, might be i am wrong?

eventResponse = new HashMap<>();
JsonElement jsonResponseEvent = eventElement.getAsJsonArray().get(i);
JsonElement jsonResponseEvent = eventArray.get(i);
if (isValid(jsonResponseEvent)) {
synchronized (this) {
JsonObject validResponse = jsonResponseEvent.getAsJsonObject();
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 add check before doing this process like that ?

if (eventResponseMessage == null){
eventResponse.put("Parameter 'eventResponseMessage' must not be null", HttpStatus.BAD_REQUEST);
}

return responseEvent;
}
JsonElement eventElement = JsonParser.parseString(eventResponseMessage);
JsonArray eventArray = eventElement.getAsJsonArray();
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 i check it and it seems eventElement is an array, if you want i can show

@@ -223,11 +225,11 @@ public ResponseEntity generateAndPublish(final String msgProtocol, final String
MsgService msgService = PublishUtils.getMessageService(msgProtocol, msgServices);
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 how it should work.

Map<String, Object> eventResponse = null;

if (eventResponseMessage == null) {
eventResponse.put("Parameter 'eventResponseMessage' must not be null", 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.

I'd write something like 'Missing response from 'generate' service.'

return responseEvent;
}
JsonElement eventElement = JsonParser.parseString(eventResponseMessage);
JsonArray eventArray = eventElement.getAsJsonArray();
Copy link
Contributor

Choose a reason for hiding this comment

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

I can't see that...

JsonElement jsonResponseEvent = element.getAsJsonArray().get(i);
if (isValid(jsonResponseEvent)) {
synchronized (this) {
JsonObject validResponse = jsonResponseEvent.getAsJsonObject();
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't mean eventResponseMessage, I mean validResponse.

try {
return getAsJsonObject(jsonElement).has(META) && getAsJsonObject(jsonElement).has(DATA) &&
getAsJsonObject(jsonElement).has(LINKS) && !getAsJsonObject(jsonElement).has(STATUS_CODE);
getAsJsonObject(jsonElement).has(LINKS) && !getAsJsonObject(jsonElement).has(JSON_STATUS_CODE);
} catch (IllegalStateException e) {
log.error("Error while validating event: ", 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.

Something like ...get(META).get(ID), but I haven't checked...

Copy link
Contributor Author

@shudhansu-shekhar shudhansu-shekhar left a comment

Choose a reason for hiding this comment

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

Please check my comment and if need we can discuss

Map<String, Object> eventResponse = null;

if (eventResponseMessage == null) {
eventResponse.put("Parameter 'eventResponseMessage' must not be null", HttpStatus.BAD_REQUEST);
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

JsonElement jsonResponseEvent = element.getAsJsonArray().get(i);
if (isValid(jsonResponseEvent)) {
synchronized (this) {
JsonObject validResponse = jsonResponseEvent.getAsJsonObject();
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 here 'validResponse' is extracting from 'eventResponseMessage' So if this 'eventResponseMessage' is not null then validResponse will also not null because there is not much changes between that

try {
return getAsJsonObject(jsonElement).has(META) && getAsJsonObject(jsonElement).has(DATA) &&
getAsJsonObject(jsonElement).has(LINKS) && !getAsJsonObject(jsonElement).has(STATUS_CODE);
getAsJsonObject(jsonElement).has(LINKS) && !getAsJsonObject(jsonElement).has(JSON_STATUS_CODE);
} catch (IllegalStateException e) {
log.error("Error while validating event: ", e.getMessage());
Copy link
Contributor Author

@shudhansu-shekhar shudhansu-shekhar Aug 2, 2024

Choose a reason for hiding this comment

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

Yeah it can do like this but not sure about the place you suggest to put not sure it will benefit anyway or not but yeah we can discuss once

@ApiParam(value = "JSON message", required = true) @RequestBody final String body){

try {
JsonElement bodyJson = JsonParser.parseString(body);
Copy link
Contributor

Choose a reason for hiding this comment

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

OK, so we have the check in generator, right?

for (int i = 0; i < eventArray.size(); i++) {
eventResponse = new HashMap<>();
JsonElement jsonResponseEvent = eventArray.get(i);
if (isValid(jsonResponseEvent)) {
synchronized (this) {
JsonObject validResponse = jsonResponseEvent.getAsJsonObject();
if (validResponse == null) {
String errorMessage = "Invalid, response json event is not in the form of JSON object";
Copy link
Contributor

Choose a reason for hiding this comment

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

Misleading error message, use something like "Invalid, array item expected to be in the form of JSON object".

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

} catch (IllegalStateException e) {
log.error("Error while validating event: ", e.getMessage());
log.error("Error while validating json event: ", 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.

json -> JSON

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

@z-sztrom
Copy link
Contributor

z-sztrom commented Aug 5, 2024

When submitting a bad request, something like that is reported

{
"status message": {
"status code": 400,
"result": "{"status_code": 400, "result": "FAIL", "message":"Template is not correct format or something is missing in the template, please check"}",
"message": "FAIL"
}
}

while result of parsing (viewing in debugger) is

{"message":"Cannot validate given JSON string","cause":"com.ericsson.eiffel.remrem.semantics.validator.EiffelValidationException: Multiple trace links are not allowed for link type COMPOSITION"}

Where this error message disappears? Why is it replaced by a "Template is not correct format or something is missing in the template, please check"?

@shudhansu-shekhar
Copy link
Contributor Author

When submitting a bad request, something like that is reported

{ "status message": { "status code": 400, "result": "{"status_code": 400, "result": "FAIL", "message":"Template is not correct format or something is missing in the template, please check"}", "message": "FAIL" } }

while result of parsing (viewing in debugger) is

{"message":"Cannot validate given JSON string","cause":"com.ericsson.eiffel.remrem.semantics.validator.EiffelValidationException: Multiple trace links are not allowed for link type COMPOSITION"}

Where this error message disappears? Why is it replaced by a "Template is not correct format or something is missing in the template, please check"?

Done, now the responses look as same in debugger

Copy link
Contributor Author

@shudhansu-shekhar shudhansu-shekhar left a comment

Choose a reason for hiding this comment

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

please check my comment

@ApiParam(value = "JSON message", required = true) @RequestBody final String body){

try {
JsonElement bodyJson = JsonParser.parseString(body);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes that duplicate key check we implement basically in generate

for (int i = 0; i < eventArray.size(); i++) {
eventResponse = new HashMap<>();
JsonElement jsonResponseEvent = eventArray.get(i);
if (isValid(jsonResponseEvent)) {
synchronized (this) {
JsonObject validResponse = jsonResponseEvent.getAsJsonObject();
if (validResponse == null) {
String errorMessage = "Invalid, response json event is not in the form of JSON object";
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

} catch (IllegalStateException e) {
log.error("Error while validating event: ", e.getMessage());
log.error("Error while validating json event: ", e.getMessage());
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

Copy link
Contributor

@z-sztrom z-sztrom left a comment

Choose a reason for hiding this comment

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

Please, add documentation, as in case of generate service.

@shudhansu-shekhar
Copy link
Contributor Author

Please, add documentation, as in case of generate service.

No need there is already in publish

Copy link
Contributor

@z-sztrom z-sztrom left a comment

Choose a reason for hiding this comment

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

Works, fine. Just change the error messages.

return send(msgProtocol, userDomain, tag, routingKey, inputBody);
} catch (JsonSyntaxException e) {
String exceptionMessage = e.getMessage();
log.error("Unexpected exception caught due to parsed 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.

Use log.error("Cannot parse the following JSON data:\n" + inputBody, exceptionMessage);

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we use inputBodyhere in the catch section we need initiailize this and it seems null in the catch, so it is not better to use body instead of inputBody?

String exceptionMessage = e.getMessage();
log.error("Unexpected exception caught due to parsed json data", exceptionMessage);
return createResponseEntity(HttpStatus.BAD_REQUEST, JSON_FATAL_STATUS,
"Invalid JSON parse data format due to: " + exceptionMessage);
Copy link
Contributor

Choose a reason for hiding this comment

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

"Invalid JSON data: " + exceptionMessage

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

Copy link
Contributor Author

@shudhansu-shekhar shudhansu-shekhar left a comment

Choose a reason for hiding this comment

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

Fix the error messages, please check the comment

Copy link
Contributor Author

@shudhansu-shekhar shudhansu-shekhar left a comment

Choose a reason for hiding this comment

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

please check my comment, just need to check one thing

@ApiParam(value = "eiffel event", required = true) @RequestBody final String body) {
try {
JsonElement inputBody = JsonParser.parseString(body);
return send(msgProtocol, userDomain, tag, routingKey, inputBody);

Check warning

Code scanning / CodeQL

Information exposure through an error message Medium

Error information
can be exposed to an external user.
return createResponseEntity(HttpStatus.BAD_REQUEST, JSON_FATAL_STATUS,
"Invalid JSON parse data format due to: " + exceptionMessage);
"Invalid 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.

A space missing after ':'.

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

@@ -195,9 +195,9 @@ public ResponseEntity send(
return send(msgProtocol, userDomain, tag, routingKey, inputBody);
} catch (JsonSyntaxException e) {
String exceptionMessage = e.getMessage();
log.error("Unexpected exception caught due to parsed json data", exceptionMessage);
log.error("Cannot parse the following JSON data: " + body, exceptionMessage);
Copy link
Contributor

Choose a reason for hiding this comment

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

Separate the JSON data from the rest of logs:

... data:\n" + body + '\n'

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

Copy link
Contributor Author

@shudhansu-shekhar shudhansu-shekhar left a comment

Choose a reason for hiding this comment

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

Fixed now, please check

@@ -195,9 +195,9 @@ public ResponseEntity send(
return send(msgProtocol, userDomain, tag, routingKey, inputBody);
} catch (JsonSyntaxException e) {
String exceptionMessage = e.getMessage();
log.error("Cannot parse the following JSON data: " + body, exceptionMessage);
log.error("Cannot parse the following JSON data:\n" + body + '\n', exceptionMessage);
Copy link
Contributor

Choose a reason for hiding this comment

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

I can't see the error message in log file.

@shudhansu-shekhar shudhansu-shekhar merged commit 4aa72b9 into eiffel-community:master Aug 16, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants