0

I have two java endpoints in spring boot like this:

@PostMapping(path="/my-import-1")
@ResponseStatus(HttpStatus.OK)
public String myImport1(@Valid @RequestBody ParameterDto1 params) {
    return this.serviceImpl.import(params);
}

and

@PostMapping(path="/my-import-2")
@ResponseStatus(HttpStatus.OK)
public String myImport2(@Valid @RequestBody ParameterDto2 params) {
    return this.serviceImpl.import(params);
}

Both use the same service for importing, but have some differences in their parameters.

I created the service's import method like this

@Override
public String import(ParameterInterface params) throws Exception {
   ...
}

and the ParameterInterface like this

public interface ImportMetaData {
    public default ArrayList<FileInterface> getFiles() {
        return null;
    }
    public void setFiles(ArrayList<FileInterface> files);
}

Implementing this interface I created two ParameterDto classes (ParameterDto1 and ParameterDto2). The IDE shows everything is correct, also the start of my service works, but as soon as I send a request to one of the endpoints, I get the following error:

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.beo.services.myImportService.rest.domain.dto.metadata.interfaces.ParameterInerface]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of com.beo.services.myImportService.rest.domain.dto.metadata.interfaces.ParameterInerface (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information at [Source: (PushbackInputStream); line: 3, column: 5] (through reference chain: com.beo.services.myImportService.rest.domain.dto.metadata.ParameterDto["files"]->java.util.ArrayList[0])] with root cause

Can I any how create such an ArrayList from an interface and get these two endpoints running? Or is there another solution?

2 Answers 2

1

The issue is with the ParameterDto1 and ParameterDto2. Jackson library requires a default, no-args constructor or a constructor with parameters annotated with @JsonProperty("field_name"), otherwise it cannot convert your message.

Solution:

Add a no-args constructor to ParameterDto1 and ParameterDto2 or annotate the constructor parameters with @JsonProperty("field_name")

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your response. No matter if I add a constructor like public ParameterDto1() {} and public ParameterDto2() {} to my classes or I add them the way public ParameterDto1(@JsonProperty("files") ArrayList<FileInterface> files) {} to my classes, I get the same error as mentioned above.
Could you please check whether the method public String myImport1(@Valid @RequestBody ParameterDto1 params) uses ParameterDto1 or the ParameterInterface in the signature? I suspect that the issue lies over there.
0

im guessing here because you didnt share the implementation of ParameterDto1 or ParameterDto2 - and for some reason your interface is called ImportMetaData where according to the exception, your explanation and other files it should be ParameterInterface.

the problem is that getFiles/setFiles is considered as a property by jackson , its type is an interface and you are not sending any type information.

in general assuming ParameterDto1 and ParameterDto2are using a concreate implementation of FileInterface you could just change your interface methods getFiles/setFiles so they are using generics parameter and in each implementation set the concreate type for FileInterface you are using , this will allow jackson to understand the concreate type for FileInterface .

incase ParameterDto1 and ParameterDto2 are not using a concreate implementation of FileInterface you should add @JsonTypeInfo or @JsonSubTypes (see https://www.baeldung.com/jackson-annotations section 5 for more info) - note that the client calling the api should also specify the actual type in the json-type field

Suggested implementation

public interface ParameterInterface {
@JsonIgnore
public List<FileInterface> getParameters() default { return null;}
.....
}

public class ParameterDto1 implements ParameterInterface {
private List<FileImpl1> files;
public List<FileImpl1> getFiles(){return files;}
public void setFiles(List<FileImpl1> files){this.files=files;}
....
}



public class ParameterDto2 implements ParameterInterface {
private List<FileImpl2> files;
public List<FileImpl2> getFiles(){return files;}
public void setFiles(List<FileImpl2> files){this.files=files;}
...
}


public class FileImpl1 implements FileInterface{

...
}

public class FileImpl2 implements FileInterface{

...
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.