Skip to content

Commit c071449

Browse files
authored
Merge pull request #400 from bcgov/fix/event-exception
Added event exception hardening
2 parents a7c5427 + ad4c77d commit c071449

File tree

6 files changed

+130
-3
lines changed

6 files changed

+130
-3
lines changed

api/src/main/java/ca/bc/gov/educ/api/dataconversion/constant/EventOutcome.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,18 @@ public enum EventOutcome {
77
/**
88
* Student updated event outcome.
99
*/
10-
TRAX_STUDENT_MASTER_UPDATED,
10+
TRAX_STUDENT_MASTER_UPDATED;
11+
12+
public static boolean isValid(String value) {
13+
if (value == null) {
14+
return false;
15+
}
16+
try {
17+
EventOutcome.valueOf(value);
18+
return true;
19+
} catch (IllegalArgumentException e) {
20+
return false;
21+
}
22+
}
23+
1124
}

api/src/main/java/ca/bc/gov/educ/api/dataconversion/constant/EventType.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,17 @@ public enum EventType {
1616
XPROGRAM,
1717
ASSESSMENT,
1818
COURSE,
19-
FI10ADD
19+
FI10ADD;
20+
21+
public static boolean isValid(String value) {
22+
if (value == null) {
23+
return false;
24+
}
25+
try {
26+
EventType.valueOf(value);
27+
return true;
28+
} catch (IllegalArgumentException e) {
29+
return false;
30+
}
31+
}
2032
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package ca.bc.gov.educ.api.dataconversion.exception;
2+
3+
import lombok.Data;
4+
import lombok.EqualsAndHashCode;
5+
6+
import java.io.Serial;
7+
8+
@EqualsAndHashCode(callSuper = true)
9+
@Data
10+
public class IgnoreEventException extends Exception {
11+
12+
private final String eventType;
13+
private final String eventOutcome;
14+
/**
15+
* The constant serialVersionUID.
16+
*/
17+
@Serial
18+
private static final long serialVersionUID = 5241655513745148898L;
19+
20+
/**
21+
* Instantiates a new Pen reg api runtime exception.
22+
*
23+
* @param message the message
24+
*/
25+
public IgnoreEventException(final String message, String eventType, String eventOutcome) {
26+
super(message);
27+
this.eventType = eventType;
28+
this.eventOutcome = eventOutcome;
29+
}
30+
}

api/src/main/java/ca/bc/gov/educ/api/dataconversion/messaging/jetstream/Subscriber.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package ca.bc.gov.educ.api.dataconversion.messaging.jetstream;
22

33
import ca.bc.gov.educ.api.dataconversion.constant.Topics;
4+
import ca.bc.gov.educ.api.dataconversion.exception.IgnoreEventException;
45
import ca.bc.gov.educ.api.dataconversion.model.ChoreographedEvent;
56
import ca.bc.gov.educ.api.dataconversion.service.EventHandlerDelegatorService;
67
import ca.bc.gov.educ.api.dataconversion.util.EducGradDataConversionApiConstants;
8+
import ca.bc.gov.educ.api.dataconversion.util.EventUtils;
79
import ca.bc.gov.educ.api.dataconversion.util.JsonUtil;
810
import ca.bc.gov.educ.api.dataconversion.util.LogHelper;
911
import com.google.common.util.concurrent.ThreadFactoryBuilder;
@@ -96,7 +98,7 @@ public void onMessage(final Message message) {
9698
try {
9799
val eventString = new String(message.getData());
98100
LogHelper.logMessagingEventDetails(eventString, constants.isSplunkLogHelperEnabled());
99-
final ChoreographedEvent event = JsonUtil.getJsonObjectFromString(ChoreographedEvent.class, eventString);
101+
final ChoreographedEvent event = EventUtils.getChoreographedEventIfValid(eventString);
100102
if (event.getEventPayload() == null) {
101103
message.ack();
102104
log.warn("payload is null, ignoring event :: {}", event);
@@ -110,6 +112,9 @@ public void onMessage(final Message message) {
110112
}
111113
});
112114
log.debug("received event :: {} ", event);
115+
} catch (final IgnoreEventException ex) {
116+
log.warn("Ignoring event with type :: {} :: and event outcome :: {}", ex.getEventType(), ex.getEventOutcome());
117+
message.ack();
113118
} catch (final Exception ex) {
114119
log.error("Exception ", ex);
115120
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package ca.bc.gov.educ.api.dataconversion.model;
2+
3+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Builder;
6+
import lombok.Data;
7+
import lombok.NoArgsConstructor;
8+
9+
import java.util.UUID;
10+
11+
@Data
12+
@Builder
13+
@AllArgsConstructor
14+
@NoArgsConstructor
15+
@JsonIgnoreProperties(ignoreUnknown = true)
16+
public class ChoreographedEventValidation {
17+
UUID eventID;
18+
/**
19+
* The Event type.
20+
*/
21+
String eventType;
22+
/**
23+
* The Event outcome.
24+
*/
25+
String eventOutcome;
26+
/**
27+
* The Activity code.
28+
*/
29+
String activityCode;
30+
/**
31+
* The Event payload.
32+
*/
33+
String eventPayload; // json string
34+
/**
35+
* The Create user.
36+
*/
37+
String createUser;
38+
/**
39+
* The Update user.
40+
*/
41+
String updateUser;
42+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package ca.bc.gov.educ.api.dataconversion.util;
2+
3+
import ca.bc.gov.educ.api.dataconversion.constant.EventOutcome;
4+
import ca.bc.gov.educ.api.dataconversion.constant.EventType;
5+
import ca.bc.gov.educ.api.dataconversion.exception.IgnoreEventException;
6+
import ca.bc.gov.educ.api.dataconversion.model.ChoreographedEvent;
7+
import ca.bc.gov.educ.api.dataconversion.model.ChoreographedEventValidation;
8+
import com.fasterxml.jackson.core.JsonProcessingException;
9+
import org.apache.commons.lang3.StringUtils;
10+
11+
12+
public final class EventUtils {
13+
private EventUtils() {
14+
}
15+
16+
public static ChoreographedEvent getChoreographedEventIfValid(String eventString) throws JsonProcessingException, IgnoreEventException {
17+
final ChoreographedEventValidation event = JsonUtil.getJsonObjectFromString(ChoreographedEventValidation.class, eventString);
18+
if(StringUtils.isNotBlank(event.getEventOutcome()) && !EventOutcome.isValid(event.getEventOutcome())) {
19+
throw new IgnoreEventException("Invalid event outcome", event.getEventType(), event.getEventOutcome());
20+
}else if(StringUtils.isNotBlank(event.getEventType()) && !EventType.isValid(event.getEventType())) {
21+
throw new IgnoreEventException("Invalid event type", event.getEventType(), event.getEventOutcome());
22+
}
23+
return JsonUtil.getJsonObjectFromString(ChoreographedEvent.class, eventString);
24+
}
25+
}

0 commit comments

Comments
 (0)