Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MethodArgumentConversionNotSupportedException when I try to map json string onto java domain class in Spring controller's method

From the frontend I receive GET-request which contains encoded json string as one of its parameters:

http://localhost:8080/engine/template/get-templates?context=%7B%22entityType%22%3A%22DOCUMENT%22%2C%22entityId%22%3A%22c7a2a0c6-fd34-4f33-9cb8-14c2090565ea%22%7D&page=1&start=0&limit=25  

Json-parameter 'context' without encoding (UUID is random):

{"entityType":"DOCUMENT","entityId":"c7a2a0c6-fd34-4f33-9cb8-14c2090565ea"}

On backend my controller's method which handle that request looks like this:

@RequestMapping(value = "/get-templates", method = RequestMethod.GET)
public List<Template> getTemplates(@RequestParam(required = false, name = "context") Context context) {
   //...
}

'Context' domain class:

public class Context {
    private String entityType;
    private UUID entityId;

    public String getEntityType() {
        return entityType;
    }
    public void setEntityType(String entityType) {
        this.entityType = entityType;
    }
    public UUID getEntityId() {
        return entityId;
    }
    public void setEntityId(UUID entityId) {
        this.entityId = entityId;
    }
}

I believed Spring's Jackson module would automatically convert that kind of json to java object of Context class, but when I run this code it gives me exception:

org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type 'com.company.domain.Context'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'com.company.domain.Context': no matching editors or conversion strategy found

On StackOverflow I've seen similar questions, but those were about POST-requests handling (with @RequestBody annotation), which doesn't fit with GET-request.

Could you help me to solve this problem? Thanks in advance.

like image 935
amseager Avatar asked Nov 10 '17 09:11

amseager


2 Answers

I think you need to specify that your GET mapping is looking to consume JSON:

@RequestMapping(value = "/get-templates", method = RequestMethod.GET, consumes = "application/json")
public List<Template> getTemplates(@RequestParam(required = false, name = "context") Context context) {
   //...
}

If this doesn't work then you can call the Jackson ObjectMapper yourself:

@RequestMapping(value = "/get-templates", method = RequestMethod.GET)
public List<Template> getTemplates(@RequestParam(required = false, name = "context") String context) {
   ObjectMapper mapper = new ObjectMapper();
   Context myContext = mapper.readValue(context, Context.class); 
   //...
}
like image 175
Plog Avatar answered Oct 18 '22 00:10

Plog


As far as I know Spring does not have the mechanism to convert from a String to a UUID in older releases. In such case you should declare you entityId as a String and then use a converter in order to convert it to UUID.
So your Context class should be like below:

public class Context {
    private String entityType;
    private String entityId;

    public String getEntityType() {
        return entityType;
    }
    public void setEntityType(String entityType) {
        this.entityType = entityType;
    }
    public String getEntityId() {
        return entityId;
    }
    public void setEntityId(String entityId) {
        this.entityId = entityId;
    }
    public UUID getEntityIdAsUUID() {
        return convertToUUID(this.entityId);
    }

    // Helper Conversion String to UUID method
    private UUID convertToUUID(String entityId){
        return UUID.fromString(entityId);
    }

}
like image 22
Anastasios Vlasopoulos Avatar answered Oct 17 '22 23:10

Anastasios Vlasopoulos