elide icon indicating copy to clipboard operation
elide copied to clipboard

InvalidValueException doesn't help resolving issues

Open eedijs opened this issue 3 years ago • 4 comments

Expected Behaviour

When a field receives an invalid value, return the error for it:

Java 8 date/time type `java.time.Instant` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling
 at [Source: UNKNOWN; byte offset: #UNKNOWN] (through reference chain: com.example.package.AttributeClass["thisWillFail"])

Current Behavior

Currently, the error message is very "cryptic" - it's impossible to tell what went wrong, which field was sent an invalid value. I will give you an example in Steps to Reproduce, but here's is the response I receive when a single or multiple values are invalid:

InvalidValueException: Invalid value: {field1=value1, field2=value2, field3=value3, ...} // and so on

Possible Solution

An improvement, in my opinion, would be to either show an error for the first field that fails and has an error, or even better - gather all fields with errors and list them in the response.

Steps to Reproduce (for bugs)

Here is a simple example class:

@Include
@Entity
@Table(name = "main_class")
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@SequenceGenerator(name = "seq", sequenceName = "main_class_entity")
public class MainClass {
	
	private String field1;

	private String field2;

	@Embedded
	private AttributeClass attributes;

	@Getter
	@Setter
	@Builder
	@NoArgsConstructor
	@AllArgsConstructor
	@Embeddable
	public static class AttributeClass {

		private String field1;
		private String field2;
		private String field3;
		private Instant thisWillFail;
		private String field4;
		private String field5;
		private String field6;
	}
}

So if I send a request like this:

{
	"data": {
		"type": "mainclass",
		"attributes": {
			"field1": "string1",
			"field2": "string2",
			"attributes": {
				"field1": "string1",
				"field2": "string2",
				"field3": "string3",
				"thisWillFail": "invalid_instant_value",
				"field4": "string4",
				"field5": "string5",
				"field6": "string6"
			}
		}
	}
}

The error response for the invalid field will be:

InvalidValueException: Invalid value: {field1=string1, field2=string2, field3=string3, thisWillFail=invalid_instant_value, field4=string4, field5=string5, field6=string6}

Your Environment

  • Elide version used: 6.1.9

eedijs avatar Dec 01 '22 12:12 eedijs

Related to this issue - the FromMapConverter creates a new instance of ObjectMapper which has no registered modules, therefore I cannot convert an Instant value from incoming json:

public class FromMapConverter implements Converter {
    private static final ObjectMapper MAPPER = new ObjectMapper();

Do you have any plans for either using Spring Boot ObjectMapper beans or making your instances of ObjectMapper as configurable beans?

eedijs avatar Dec 02 '22 07:12 eedijs

Can you add the Elide annotations to the example model or provide a working example based on Elide-spring-boot of the issue?

aklish avatar Dec 04 '22 21:12 aklish

Apologies for the late reply, but I've updated my main comment's example with the same annotations that I use.

eedijs avatar Dec 12 '22 14:12 eedijs

Hi @aklish, have you had the time to look at this issue? For now, I've implemented my custom ErrorMapper, which changes the InvalidValueException a bit and returns the same exception with a changed message (the verbose message contains the actual error):

    private InvalidValueException getchangedInvalidValueException(Exception exception) {
        InvalidValueException invalidValueException = (InvalidValueException) exception;

        if (StringUtils.isEmpty(invalidValueException.getVerboseMessage())) {
            return invalidValueException;
        }

        return new InvalidValueException(invalidValueException.getVerboseMessage().replace("Invalid value: ", ""), invalidValueException.getVerboseMessage());
    }

eedijs avatar Jan 24 '23 15:01 eedijs