diff --git a/src/main/java/com/yetanalytics/xapi/model/Extensions.java b/src/main/java/com/yetanalytics/xapi/model/Extensions.java index 852d8a2..c3b2ac3 100644 --- a/src/main/java/com/yetanalytics/xapi/model/Extensions.java +++ b/src/main/java/com/yetanalytics/xapi/model/Extensions.java @@ -5,13 +5,12 @@ import java.util.Map; import java.util.Set; +import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.PathNotFoundException; import com.yetanalytics.xapi.model.deserializers.ExtensionDeserializer; -import com.yetanalytics.xapi.model.serializers.ExtensionSerializer; import com.yetanalytics.xapi.util.Mapper; /** @@ -22,7 +21,7 @@ * or through a JSONPath API. */ @JsonDeserialize(using = ExtensionDeserializer.class) -@JsonSerialize(using = ExtensionSerializer.class) +// @JsonSerialize(using = ExtensionSerializer.class) public class Extensions { private Map extMap = new HashMap<>(); @@ -92,6 +91,7 @@ public Set getKeys() { * Returns the full raw Extension Map as a HashMap<URI, Object> * @return The raw Extensions Map */ + @JsonValue public Map getMap() { return extMap; } diff --git a/src/main/java/com/yetanalytics/xapi/model/InteractionType.java b/src/main/java/com/yetanalytics/xapi/model/InteractionType.java index 0e4bd59..18a903c 100644 --- a/src/main/java/com/yetanalytics/xapi/model/InteractionType.java +++ b/src/main/java/com/yetanalytics/xapi/model/InteractionType.java @@ -45,7 +45,7 @@ public static InteractionType getByDisplayName(String name) { return t; } } - throw new IllegalArgumentException("Bad InteractionType Value"); + throw new IllegalArgumentException("Invalid InteractionType value: " + name); } /** diff --git a/src/main/java/com/yetanalytics/xapi/model/LangMap.java b/src/main/java/com/yetanalytics/xapi/model/LangMap.java index b0a48b2..e71c35f 100644 --- a/src/main/java/com/yetanalytics/xapi/model/LangMap.java +++ b/src/main/java/com/yetanalytics/xapi/model/LangMap.java @@ -4,10 +4,9 @@ import java.util.Map; import java.util.Set; +import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.yetanalytics.xapi.model.deserializers.LangMapDeserializer; -import com.yetanalytics.xapi.model.serializers.LangMapSerializer; /** * Java wrapper object for the @@ -17,7 +16,7 @@ * the value is a String in the language specified by the tag. */ @JsonDeserialize(using = LangMapDeserializer.class) -@JsonSerialize(using = LangMapSerializer.class) +// @JsonSerialize(using = LangMapSerializer.class) public class LangMap { private HashMap languageHashMap = new HashMap<>(); @@ -68,6 +67,7 @@ public Set getLanguageCodes() { * Retrieves the full Language Map in the form of a HashMap<String, String> * @return The full Language Map */ + @JsonValue public Map getMap() { return languageHashMap; } diff --git a/src/main/java/com/yetanalytics/xapi/model/ObjectType.java b/src/main/java/com/yetanalytics/xapi/model/ObjectType.java index 4f91938..32577b1 100644 --- a/src/main/java/com/yetanalytics/xapi/model/ObjectType.java +++ b/src/main/java/com/yetanalytics/xapi/model/ObjectType.java @@ -41,7 +41,7 @@ public static ObjectType getByDisplayName(String name) { return t; } } - throw new IllegalArgumentException("Bad ObjectType Value"); + throw new IllegalArgumentException("Invalid ObjectType value: " + name); } /** diff --git a/src/main/java/com/yetanalytics/xapi/model/deserializers/AbstractActorDeserializer.java b/src/main/java/com/yetanalytics/xapi/model/deserializers/AbstractActorDeserializer.java index c638151..a111856 100644 --- a/src/main/java/com/yetanalytics/xapi/model/deserializers/AbstractActorDeserializer.java +++ b/src/main/java/com/yetanalytics/xapi/model/deserializers/AbstractActorDeserializer.java @@ -1,15 +1,15 @@ package com.yetanalytics.xapi.model.deserializers; -import com.fasterxml.jackson.databind.deser.std.StdDeserializer; - -import com.yetanalytics.xapi.model.Group; +import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.yetanalytics.xapi.model.AbstractActor; import com.yetanalytics.xapi.model.Agent; +import com.yetanalytics.xapi.model.Group; import com.yetanalytics.xapi.model.ObjectType; import com.yetanalytics.xapi.util.Mapper; @@ -27,17 +27,15 @@ public AbstractActorDeserializer(final Class vc) { } @Override - public AbstractActor deserialize(final JsonParser jp, final DeserializationContext context) { - try { - ObjectMapper mapper = Mapper.getMapper(); - JsonNode node = mapper.readTree(jp); - String objType = node.has("objectType") ? node.get("objectType").asText() : null; - Class instanceClass = - ObjectType.GROUP.matches(objType) ? Group.class : Agent.class; - return mapper.convertValue(node, instanceClass); - } catch (Exception e) { - e.printStackTrace(); - return null; - } + public AbstractActor deserialize(final JsonParser jp, final DeserializationContext context) throws IOException { + ObjectMapper mapper = Mapper.getMapper(); + JsonNode node = mapper.readTree(jp); + String objType = node.has("objectType") + ? node.get("objectType").asText() + : null; + Class instClass = ObjectType.GROUP.matches(objType) + ? Group.class + : Agent.class; + return mapper.convertValue(node, instClass); } } diff --git a/src/main/java/com/yetanalytics/xapi/model/deserializers/AbstractObjectDeserializer.java b/src/main/java/com/yetanalytics/xapi/model/deserializers/AbstractObjectDeserializer.java index e2f20b6..5403020 100644 --- a/src/main/java/com/yetanalytics/xapi/model/deserializers/AbstractObjectDeserializer.java +++ b/src/main/java/com/yetanalytics/xapi/model/deserializers/AbstractObjectDeserializer.java @@ -1,15 +1,15 @@ package com.yetanalytics.xapi.model.deserializers; -import com.fasterxml.jackson.databind.deser.std.StdDeserializer; - -import com.yetanalytics.xapi.model.Group; +import java.io.IOException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.yetanalytics.xapi.model.AbstractObject; import com.yetanalytics.xapi.model.Activity; import com.yetanalytics.xapi.model.Agent; +import com.yetanalytics.xapi.model.Group; import com.yetanalytics.xapi.model.ObjectType; import com.yetanalytics.xapi.model.Statement; import com.yetanalytics.xapi.model.StatementRef; @@ -30,15 +30,17 @@ public AbstractObjectDeserializer(final Class vc) { } private Class getObjectType(JsonNode n) { - String objType = n.has("objectType") ? n.get("objectType").asText() : null; + String objType = n.has("objectType") + ? n.get("objectType").asText() + : null; boolean hasActor = n.has("actor"); boolean hasId = n.has("id"); - if (ObjectType.GROUP.toString().equals(objType)){ + if (ObjectType.GROUP.toString().equals(objType)) { return Group.class; } else if (ObjectType.STATEMENT_REF.matches(objType)) { return StatementRef.class; - } else if (ObjectType.AGENT.matches(objType) || (objType == null && !hasId)){ + } else if (ObjectType.AGENT.matches(objType) || (objType == null && !hasId)) { return Agent.class; } else if (ObjectType.SUB_STATEMENT.matches(objType) || (objType == null && hasActor)) { @@ -49,13 +51,8 @@ private Class getObjectType(JsonNode n) { } @Override - public AbstractObject deserialize(final JsonParser jp, final DeserializationContext context) { - try { - JsonNode node = jp.readValueAsTree(); - return Mapper.getMapper().convertValue(node, getObjectType(node)); - } catch (Exception e) { - e.printStackTrace(); - return null; - } + public AbstractObject deserialize(final JsonParser jp, final DeserializationContext context) throws IOException { + JsonNode node = jp.readValueAsTree(); + return Mapper.getMapper().convertValue(node, getObjectType(node)); } } diff --git a/src/main/java/com/yetanalytics/xapi/model/deserializers/ContextActivityListDeserializer.java b/src/main/java/com/yetanalytics/xapi/model/deserializers/ContextActivityListDeserializer.java index 7747d39..daea7de 100644 --- a/src/main/java/com/yetanalytics/xapi/model/deserializers/ContextActivityListDeserializer.java +++ b/src/main/java/com/yetanalytics/xapi/model/deserializers/ContextActivityListDeserializer.java @@ -1,5 +1,6 @@ package com.yetanalytics.xapi.model.deserializers; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -26,23 +27,18 @@ public ContextActivityListDeserializer(final Class vc) { } @Override - public List deserialize(final JsonParser jp, final DeserializationContext context) { - try { - ObjectMapper mapper = Mapper.getMapper(); - JsonNode node = mapper.readTree(jp); - //Sometimes a contextactivity list is actually a single entry, but - //should be converted to a list - if (node instanceof ArrayNode){ - TypeReference> typeRef = new TypeReference>() {}; - return mapper.convertValue(node, typeRef); - } else { - ArrayList ctxActList = new ArrayList(); - ctxActList.add(mapper.convertValue(node, Activity.class)); - return ctxActList; - } - } catch (Exception e) { - e.printStackTrace(); - return null; + public List deserialize(final JsonParser jp, final DeserializationContext context) throws IOException { + ObjectMapper mapper = Mapper.getMapper(); + JsonNode node = mapper.readTree(jp); + // Sometimes a contextactivity list is actually a single entry, but + // should be converted to a list + if (node instanceof ArrayNode){ + TypeReference> typeRef = new TypeReference>() {}; + return mapper.convertValue(node, typeRef); + } else { + ArrayList ctxActList = new ArrayList<>(); + ctxActList.add(mapper.convertValue(node, Activity.class)); + return ctxActList; } } } diff --git a/src/main/java/com/yetanalytics/xapi/model/deserializers/ExtensionDeserializer.java b/src/main/java/com/yetanalytics/xapi/model/deserializers/ExtensionDeserializer.java index 9150781..5f2b0f8 100644 --- a/src/main/java/com/yetanalytics/xapi/model/deserializers/ExtensionDeserializer.java +++ b/src/main/java/com/yetanalytics/xapi/model/deserializers/ExtensionDeserializer.java @@ -1,5 +1,6 @@ package com.yetanalytics.xapi.model.deserializers; +import java.io.IOException; import java.net.URI; import java.util.HashMap; @@ -25,17 +26,11 @@ public ExtensionDeserializer(final Class vc) { } @Override - public Extensions deserialize(final JsonParser jp, final DeserializationContext context) { - try { - TypeReference> typeRef - = new TypeReference>() {}; - - JsonNode node = Mapper.getMapper().readTree(jp); - - return new Extensions(Mapper.getMapper().convertValue(node, typeRef)); - } catch (Exception e) { - e.printStackTrace(); - return null; - } + public Extensions deserialize(final JsonParser jp, final DeserializationContext context) throws IOException { + TypeReference> typeRef + = new TypeReference>() {}; + JsonNode node = Mapper.getMapper().readTree(jp); + HashMap m = Mapper.getMapper().convertValue(node, typeRef); + return new Extensions(m); } } diff --git a/src/main/java/com/yetanalytics/xapi/model/deserializers/InteractionTypeDeserializer.java b/src/main/java/com/yetanalytics/xapi/model/deserializers/InteractionTypeDeserializer.java index 6c60499..5e315ce 100644 --- a/src/main/java/com/yetanalytics/xapi/model/deserializers/InteractionTypeDeserializer.java +++ b/src/main/java/com/yetanalytics/xapi/model/deserializers/InteractionTypeDeserializer.java @@ -1,9 +1,11 @@ package com.yetanalytics.xapi.model.deserializers; -import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import java.io.IOException; + import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.yetanalytics.xapi.model.InteractionType; import com.yetanalytics.xapi.util.Mapper; @@ -21,13 +23,9 @@ public InteractionTypeDeserializer(final Class vc) { } @Override - public InteractionType deserialize(final JsonParser jp, final DeserializationContext context) { - try { - ObjectMapper mapper = Mapper.getMapper(); - return InteractionType.getByDisplayName(mapper.readValue(jp, String.class)); - } catch (Exception e) { - e.printStackTrace(); - return null; - } + public InteractionType deserialize(final JsonParser jp, final DeserializationContext context) throws IOException { + ObjectMapper mapper = Mapper.getMapper(); + String intType = mapper.readValue(jp, String.class); + return InteractionType.getByDisplayName(intType); } } diff --git a/src/main/java/com/yetanalytics/xapi/model/deserializers/LangMapDeserializer.java b/src/main/java/com/yetanalytics/xapi/model/deserializers/LangMapDeserializer.java index 0564704..3a50ff6 100644 --- a/src/main/java/com/yetanalytics/xapi/model/deserializers/LangMapDeserializer.java +++ b/src/main/java/com/yetanalytics/xapi/model/deserializers/LangMapDeserializer.java @@ -1,5 +1,6 @@ package com.yetanalytics.xapi.model.deserializers; +import java.io.IOException; import java.util.HashMap; import com.fasterxml.jackson.core.JsonParser; @@ -25,16 +26,11 @@ public LangMapDeserializer(final Class vc) { } @Override - public LangMap deserialize(final JsonParser jp, final DeserializationContext context) { - try { - ObjectMapper mapper = Mapper.getMapper(); - TypeReference> typeRef - = new TypeReference>() {}; - - return new LangMap(mapper.readValue(jp, typeRef)); - } catch (Exception e) { - e.printStackTrace(); - return null; - } + public LangMap deserialize(final JsonParser jp, final DeserializationContext context) throws IOException { + ObjectMapper mapper = Mapper.getMapper(); + TypeReference> typeRef + = new TypeReference>() {}; + HashMap map = mapper.readValue(jp, typeRef); + return new LangMap(map); } } diff --git a/src/main/java/com/yetanalytics/xapi/model/deserializers/MimeTypeDeserializer.java b/src/main/java/com/yetanalytics/xapi/model/deserializers/MimeTypeDeserializer.java index f5186e2..ebc8c30 100644 --- a/src/main/java/com/yetanalytics/xapi/model/deserializers/MimeTypeDeserializer.java +++ b/src/main/java/com/yetanalytics/xapi/model/deserializers/MimeTypeDeserializer.java @@ -1,5 +1,7 @@ package com.yetanalytics.xapi.model.deserializers; +import java.io.IOException; + import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.ObjectMapper; @@ -23,7 +25,7 @@ public MimeTypeDeserializer(final Class vc) { } @Override - public MimeType deserialize(final JsonParser jp, final DeserializationContext context) { + public MimeType deserialize(final JsonParser jp, final DeserializationContext context) throws IOException { try { ObjectMapper mapper = Mapper.getMapper(); return new MimeType(mapper.readValue(jp, String.class)); @@ -31,9 +33,6 @@ public MimeType deserialize(final JsonParser jp, final DeserializationContext co // Need special case since MimeTypeParseException does not // extend RuntimeException, so it angers the compiler. throw new IllegalArgumentException(e); - } catch (Exception e) { - e.printStackTrace(); - return null; } } } diff --git a/src/main/java/com/yetanalytics/xapi/model/deserializers/ObjectTypeDeserializer.java b/src/main/java/com/yetanalytics/xapi/model/deserializers/ObjectTypeDeserializer.java index 892c4a7..08b7ebe 100644 --- a/src/main/java/com/yetanalytics/xapi/model/deserializers/ObjectTypeDeserializer.java +++ b/src/main/java/com/yetanalytics/xapi/model/deserializers/ObjectTypeDeserializer.java @@ -1,9 +1,11 @@ package com.yetanalytics.xapi.model.deserializers; -import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import java.io.IOException; + import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.yetanalytics.xapi.model.ObjectType; import com.yetanalytics.xapi.util.Mapper; @@ -21,13 +23,9 @@ public ObjectTypeDeserializer(final Class vc) { } @Override - public ObjectType deserialize(final JsonParser jp, final DeserializationContext context) { - try { - ObjectMapper mapper = Mapper.getMapper(); - return ObjectType.getByDisplayName(mapper.readValue(jp, String.class)); - } catch (Exception e) { - e.printStackTrace(); - return null; - } + public ObjectType deserialize(final JsonParser jp, final DeserializationContext context) throws IOException { + ObjectMapper mapper = Mapper.getMapper(); + String objType = mapper.readValue(jp, String.class); + return ObjectType.getByDisplayName(objType); } } diff --git a/src/test/java/com/yetanalytics/ValueExceptionTest.java b/src/test/java/com/yetanalytics/ValueExceptionTest.java new file mode 100644 index 0000000..83190db --- /dev/null +++ b/src/test/java/com/yetanalytics/ValueExceptionTest.java @@ -0,0 +1,123 @@ +package com.yetanalytics; + +import static org.junit.Assert.assertThrows; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.yetanalytics.xapi.model.ActivityDefinition; +import com.yetanalytics.xapi.model.Agent; +import com.yetanalytics.xapi.model.Attachment; +import com.yetanalytics.xapi.model.Result; +import com.yetanalytics.xapi.model.Statement; +import com.yetanalytics.xapi.model.Verb; +import com.yetanalytics.xapi.util.Mapper; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +public class ValueExceptionTest extends TestCase { + public ValueExceptionTest(String testName) { + super(testName); + } + + public static Test suite() { + return new TestSuite(ValueExceptionTest.class); + } + + public void assertJsonProcessingException(String original, Class toConvert) { + ObjectMapper mapper = Mapper.getMapper(); + JsonProcessingException exception = assertThrows(JsonProcessingException.class, + () -> mapper.readValue(original, toConvert)); + + System.out.println(exception.getOriginalMessage()); + } + + public void testInvalidUUID() { + // Extra digit at front + String uuidStr = "{\"id\": \"100000000-4000-8000-0000-000000000000\"}"; + String errMsg = "Cannot deserialize value of type `java.util.UUID` from String \"100000000-4000-8000-0000-000000000000\": UUID has to be represented by standard 36-char representation"; + JsonProcessingException exception = assertThrows(JsonProcessingException.class, + () -> Mapper.getMapper().readValue(uuidStr, Statement.class)); + assertEquals(errMsg, exception.getOriginalMessage()); + } + + public void testInvalidUri() { + // Curly braces are not allowed in URIs + String uriStr = "{\"id\": \"{http://example.com}\"}"; + String errMsg = "Cannot deserialize value of type `java.net.URI` from String \"{http://example.com}\": not a valid textual representation, problem: Illegal character in scheme name at index 0: {http://example.com}"; + JsonProcessingException exception = assertThrows(JsonProcessingException.class, + () -> Mapper.getMapper().readValue(uriStr, Verb.class)); + assertEquals(errMsg, exception.getOriginalMessage()); + } + + public void testInvalidUri2() { + // Same test as above except as Extension key + String uriStr = "{\"extensions\": {\"{http://example.com}\": 2}"; + String errMsg = "Cannot deserialize Map key of type `java.net.URI` from String \"{http://example.com}\": not a valid representation, problem: (com.fasterxml.jackson.databind.exc.InvalidFormatException) Cannot deserialize Map key of type `java.net.URI` from String \"{http://example.com}\": problem: Illegal character in scheme name at index 0: {http://example.com}\n at [Source: UNKNOWN; byte offset: #UNKNOWN]"; + JsonProcessingException exception = assertThrows(JsonProcessingException.class, + () -> Mapper.getMapper().readValue(uriStr, ActivityDefinition.class)); + assertEquals(errMsg, exception.getOriginalMessage()); + } + + public void testInvalidTimestamp() { + // Spaces in timestamp + String timestampStr = "{\"timestamp\": \"2023 10 27T09:03:21.722Z\"}"; + String errMsg = "Cannot deserialize value of type `java.time.ZonedDateTime` from String \"2023 10 27T09:03:21.722Z\": Failed to deserialize java.time.ZonedDateTime: (java.time.format.DateTimeParseException) Text '2023 10 27T09:03:21.722Z' could not be parsed at index 4"; + JsonProcessingException exception = assertThrows(JsonProcessingException.class, + () -> Mapper.getMapper().readValue(timestampStr, Statement.class)); + assertEquals(errMsg, exception.getOriginalMessage()); + } + + public void testInvalidDuration() { + // Mispelled "PT" as "PR" + String durationStr = "{\"duration\": \"PR4H35M59.14S\"}"; + String errMsg = "Cannot construct instance of `com.yetanalytics.xapi.model.XapiDuration`, problem: Text cannot be parsed to a Duration"; + JsonProcessingException exception = assertThrows(JsonProcessingException.class, + () -> Mapper.getMapper().readValue(durationStr, Result.class)); + assertEquals(errMsg, exception.getOriginalMessage()); + } + + public void testInvalidMimeType() { + // No subtype + String mimeTypeStr = "{\"contentType\": \"text\"}"; + String errMsg = "jakarta.activation.MimeTypeParseException: Unable to find a sub type."; + JsonProcessingException exception = assertThrows(JsonProcessingException.class, + () -> Mapper.getMapper().readValue(mimeTypeStr, Attachment.class)); + assertEquals(errMsg, exception.getOriginalMessage()); + } + + public void testInvalidLangTag() { + String langTagStr = "{\"description\": {\"{en-us}\": \"Foo\"}}"; + String errMsg = "Cannot deserialize Map key of type `com.yetanalytics.xapi.model.LangTag` from String \"{en-us}\": not a valid representation, problem: (java.lang.reflect.InvocationTargetException) Invalid subtag: {en [at index 0]"; + JsonProcessingException exception = assertThrows(JsonProcessingException.class, + () -> Mapper.getMapper().readValue(langTagStr, ActivityDefinition.class)); + assertEquals(errMsg, exception.getOriginalMessage()); + } + + public void testInvalidVersion() { + String versionStr = "{\"version\": \"1-0-0\"}"; + String errMsg = "Cannot construct instance of `org.semver4j.Semver`, problem: Version [1-0-0] is not valid semver."; + JsonProcessingException exception = assertThrows(JsonProcessingException.class, + () -> Mapper.getMapper().readValue(versionStr, Statement.class)); + assertEquals(errMsg, exception.getOriginalMessage()); + } + + // Enums + + public void testInvalidObjectType() { + String objTypeStr = "{\"objectType\": \"Person\"}"; + String errMsg = "Invalid ObjectType value: Person"; + JsonProcessingException exception = assertThrows(JsonProcessingException.class, + () -> Mapper.getMapper().readValue(objTypeStr, Agent.class)); + assertEquals(errMsg, exception.getOriginalMessage()); + } + + public void testinvalidInteractiontype() { + String intTypeStr = "{\"interactionType\": \"unknown\"}"; + String errMsg = "Invalid InteractionType value: unknown"; + JsonProcessingException exception = assertThrows(JsonProcessingException.class, + () -> Mapper.getMapper().readValue(intTypeStr, ActivityDefinition.class)); + assertEquals(errMsg, exception.getOriginalMessage()); + } +}