Skip to content

CCD-6087: Investigate mid event callback request contains unexpected data #2527

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

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 5 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ tasks.withType(Test) {

dependencies {

// Enables serialisation of java.util.Optional and java.time.LocalDateTime
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.2'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2'

implementation('org.springframework.cloud:spring-cloud-starter-bootstrap') {
version {
strictly '4.0.5'
Expand Down Expand Up @@ -662,7 +666,7 @@ sonarqube {
properties {
property "sonar.exclusions", "build/generated-sources/**/*.java," +
"**/AppInsightsConfiguration.java," +
"**/TestingSupportController.java"
"**/TestingSupportController.java,**/JcLogger.java,**/CaseDataContent.java,**/CaseDetails.java,**/MidEventCallback.java"
property "sonar.projectName", "ccd-data-store-api"
property "sonar.projectKey", "ccd-data-store-api"
property "sonar.coverage.jacoco.xmlReportPaths", "${jacocoTestReport.reports.xml.outputLocation}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.springframework.http.ResponseEntity;
import uk.gov.hmcts.ccd.data.casedetails.SecurityClassification;
import uk.gov.hmcts.ccd.domain.model.callbacks.AfterSubmitCallbackResponse;
import uk.gov.hmcts.ccd.domain.service.common.JcLogger;

import java.time.LocalDate;
import java.time.LocalDateTime;
Expand Down Expand Up @@ -42,6 +43,8 @@ public class CaseDetails implements Cloneable {
private static final Logger LOG = LoggerFactory.getLogger(CaseDetails.class);
public static final String DRAFT_ID = "DRAFT%s";

final JcLogger jcLogger = new JcLogger("CCD-6087", "CaseDetails", true);

private String id;

@JsonIgnore
Expand Down Expand Up @@ -202,7 +205,16 @@ public Map<String, JsonNode> getData() {
return data;
}

private void logData(final Map<String, JsonNode> data, final String methodName) {
final String json = jcLogger.getObjectAsString(data);
if (json.contains("dummy.pdf") || json.contains("JSON ERROR")) {
jcLogger.jclog(methodName + " json = " + json);
jcLogger.jclog(methodName + " CALL STACK = " + JcLogger.getStackTraceAsString(new Exception()));
}
}

public void setData(Map<String, JsonNode> data) {
logData(data, "CaseDetails.setData()");
this.data = data;
}

Expand Down Expand Up @@ -235,6 +247,7 @@ public Map<String, JsonNode> getSupplementaryData() {
}

public void setSupplementaryData(Map<String, JsonNode> supplementaryData) {
logData(data, "CaseDetails.setSupplementaryData()");
this.supplementaryData = supplementaryData;
}

Expand Down Expand Up @@ -363,6 +376,7 @@ public boolean hasCaseReference() {
public Map<String, JsonNode> getCaseEventData(Set<String> caseFieldIds) {
Map<String, JsonNode> caseEventData = new HashMap<>();
if (this.data != null) {
logData(data, "CaseDetails.getCaseEventData()");
for (String caseFieldId : caseFieldIds) {
JsonNode value = this.data.get(caseFieldId);
if (value != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.ToString;
import uk.gov.hmcts.ccd.domain.service.common.JcLogger;

@ToString
public class CaseDataContent {
final JcLogger jcLogger = new JcLogger("CCD-6087", "CaseDataContent", true);

private Event event;
private Map<String, JsonNode> data;

Expand Down Expand Up @@ -60,7 +63,16 @@ public Map<String, JsonNode> getData() {
return data;
}

private void logData(final Map<String, JsonNode> data, final String methodName) {
final String json = jcLogger.getObjectAsString(data);
if (json.contains("dummy.pdf") || json.contains("JSON ERROR")) {
jcLogger.jclog(methodName + " json = " + json);
jcLogger.jclog(methodName + " CALL STACK = " + JcLogger.getStackTraceAsString(new Exception()));
}
}

public void setData(Map<String, JsonNode> data) {
logData(data, "CaseDataContent.setData()");
this.data = data;
}

Expand All @@ -69,6 +81,7 @@ public Map<String, JsonNode> getEventData() {
}

public void setEventData(Map<String, JsonNode> eventData) {
logData(eventData, "CaseDataContent.setEventData()");
this.eventData = eventData;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import uk.gov.hmcts.ccd.domain.model.callbacks.CallbackResponse;
import uk.gov.hmcts.ccd.domain.model.definition.CaseDetails;
import uk.gov.hmcts.ccd.domain.model.definition.CaseEventDefinition;
import uk.gov.hmcts.ccd.domain.service.common.JcLogger;
import uk.gov.hmcts.ccd.endpoint.exceptions.ApiException;
import uk.gov.hmcts.ccd.endpoint.exceptions.CallbackException;
import uk.gov.hmcts.ccd.util.ClientContextUtil;
Expand All @@ -47,6 +48,8 @@ public class CallbackService {
private static final String WILDCARD = "*";
public static final String CLIENT_CONTEXT = "Client-Context";

final JcLogger jcLogger = new JcLogger("CCD-6087", "CallbackService", false);

private final SecurityUtils securityUtils;
private final RestTemplate restTemplate;
private final ApplicationParams applicationParams;
Expand Down Expand Up @@ -130,6 +133,11 @@ public <T> ResponseEntity<T> sendSingleRequest(final String url,
});
}

/*
* JC note:
* CallbackRequest DOES contain "dummy.pdf" , for both "Continue 1" (with attachment) and "Continue 2" (without).
* Called from CaseDataValidatorController.
*/
private <T> Optional<ResponseEntity<T>> sendRequest(final String url,
final CallbackType callbackType,
final Class<T> clazz,
Expand All @@ -150,6 +158,9 @@ private <T> Optional<ResponseEntity<T>> sendRequest(final String url,
}
final HttpEntity requestEntity = new HttpEntity(callbackRequest, httpHeaders);
if (logCallbackDetails(url)) {
jcLogger.jclog("sendRequest() url = " + url + " , callbackType = " + callbackType);
jcLogger.jclog("sendRequest() callbackRequest", callbackRequest);
jcLogger.jclog("sendRequest() CALL STACK = " + JcLogger.getStackTraceAsString(new Exception()));
LOG.info("Invoking callback {} of type {} with request: {}", url, callbackType,
printCallbackDetails(requestEntity));
}
Expand Down Expand Up @@ -182,7 +193,6 @@ private String printCallbackDetails(HttpEntity<?> callbackHttpEntity) {
} catch (Exception ex) {
LOG.warn("Unexpected error while logging callback: {}", ex.getMessage());
}

return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
// partal javadoc attributes added prior to checkstyle implementation in module
public class CaseService {

final JcLogger jcLogger = new JcLogger("CCD-6087", "CaseService", true);

private final CaseDataService caseDataService;
private final CaseDetailsRepository caseDetailsRepository;
private final UIDService uidService;
Expand Down Expand Up @@ -74,7 +76,22 @@ public CaseDetails createNewCaseDetails(String caseTypeId, String jurisdictionId
* @return <code>Optional&lt;CaseDetails&gt;</code> - CaseDetails wrapped in Optional
*/
public CaseDetails populateCurrentCaseDetailsWithEventFields(CaseDataContent content, CaseDetails caseDetails) {
content.getEventData().forEach((key, value) -> caseDetails.getData().put(key, value));
final Map<String, JsonNode> eventData = content.getEventData();
Map<String, JsonNode> caseData = caseDetails.getData();

// LOG eventData
eventData.forEach((key, value) -> jcLogger.jclog("eventData: " + key + " = " + value));

// LOG caseDataBefore
caseData.forEach((key, value) -> jcLogger.jclog("caseDataBefore: " + key + " = " + value));

// Process eventData -> caseData
eventData.forEach((key, value) -> caseData.put(key, value));
caseDetails.setData(caseData);

// LOG caseDataAfter
caseData.forEach((key, value) -> jcLogger.jclog("caseDataAfter: " + key + " = " + value));

return caseDetails;
}

Expand Down
134 changes: 134 additions & 0 deletions src/main/java/uk/gov/hmcts/ccd/domain/service/common/JcLogger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package uk.gov.hmcts.ccd.domain.service.common;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import uk.gov.hmcts.ccd.data.casedetails.SecurityClassification;
import uk.gov.hmcts.ccd.domain.model.callbacks.CallbackRequest;
import uk.gov.hmcts.ccd.domain.model.callbacks.StartEventResult;
import uk.gov.hmcts.ccd.domain.model.definition.CaseDetails;
import uk.gov.hmcts.ccd.domain.model.std.CaseDataContent;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;
import java.util.Optional;

public class JcLogger {

private static final Logger LOG = LoggerFactory.getLogger(JcLogger.class);

private final String jiraRef;

private final String classname;

private final boolean enabled;

private final ObjectMapper objectMapper = new ObjectMapper();

public JcLogger(final String jiraRef, final String classname, final boolean enabled) {
this.jiraRef = jiraRef;
this.classname = classname;
this.enabled = enabled;
// Enables serialisation of java.util.Optional and java.time.LocalDateTime
objectMapper.registerModule(new Jdk8Module());
objectMapper.registerModule(new JavaTimeModule());
}

public void jclog(String message) {
if (enabled) {
LOG.info("| JCDEBUG {}: {}: {}", jiraRef, classname, message);
}
}

public void jclog(String message, int i) {
jclog(message + ": " + i);
}

public void jclog(String message, CaseDataContent caseDataContent) {
try {
jclog(message + ": " + objectMapper.writeValueAsString(caseDataContent));
} catch (JsonProcessingException e) {
jclog(message + ": JSON ERROR: " + e.getMessage());
}
}

public void jclog(String message, CallbackRequest callbackRequest) {
try {
jclog(message + ": " + objectMapper.writeValueAsString(callbackRequest));
} catch (JsonProcessingException e) {
jclog(message + ": JSON ERROR: " + e.getMessage());
}
}

public void jclog(String message, Optional optional) {
try {
jclog(message + ": " + objectMapper.writeValueAsString(optional));
} catch (JsonProcessingException e) {
jclog(message + ": JSON ERROR: " + e.getMessage());
}
}

public void jclog(String message, CaseDetails caseDetails) {
try {
jclog(message + ": " + objectMapper.writeValueAsString(caseDetails));
} catch (JsonProcessingException e) {
jclog(message + ": JSON ERROR: " + e.getMessage());
}
}

public void jclog(String message, SecurityClassification securityClassification) {
try {
jclog(message + ": " + objectMapper.writeValueAsString(securityClassification));
} catch (JsonProcessingException e) {
jclog(message + ": JSON ERROR: " + e.getMessage());
}
}

public void jclog(String message, StartEventResult startEventResult) {
try {
jclog(message + ": " + objectMapper.writeValueAsString(startEventResult));
} catch (JsonProcessingException e) {
jclog(message + ": JSON ERROR: " + e.getMessage());
}
}

public String getObjectAsString(final Map<String, JsonNode> value) {
try {
return objectMapper.writeValueAsString(value);
} catch (JsonProcessingException e) {
jclog("JSON ERROR: " + e.getMessage());
return "JSON ERROR: " + e.getMessage();
}
}

public String getObjectAsString(final CaseDataContent caseDataContent) {
try {
return objectMapper.writeValueAsString(caseDataContent);
} catch (JsonProcessingException e) {
jclog("JSON ERROR: " + e.getMessage());
return "JSON ERROR: " + e.getMessage();
}
}

public String getObjectAsString(final CaseDetails caseDetails) {
try {
return objectMapper.writeValueAsString(caseDetails);
} catch (JsonProcessingException e) {
jclog("JSON ERROR: " + e.getMessage());
return "JSON ERROR: " + e.getMessage();
}
}

public static String getStackTraceAsString(Throwable throwable) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
throwable.printStackTrace(pw);
String stackTrace = sw.toString().replaceAll("\r\n", " ").replaceAll("\n", " ");
return stackTrace.hashCode() + " " + stackTrace;
}
}
Loading