Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson POJOPropertyBuilder finds multiple setters in POJO

We're working on a rather large JSON REST API using Spring Web MVC 3.2.2 and Jackson Databind 2.4.4 (among many other libs...).

I'm trying to use swagger-springmvc, but I'm having troubles with some our DTOs.

No matter if I use a simple @EnableSwagger or a more complex swagger config, I always get the following exception when starting Tomcat 7:

java.lang.IllegalArgumentException: Conflicting setter definitions for property "year": javax.xml.datatype.XMLGregorianCalendar#setYear(1 params) vs javax.xml.datatype.XMLGregorianCalendar#setYear(1 params)
at com.fasterxml.jackson.databind.introspect.POJOPropertyBuilder.getSetter(POJOPropertyBuilder.java:303)
at com.mangofactory.swagger.models.Annotations.findPropertyAnnotation(Annotations.java:33)
at com.mangofactory.swagger.models.property.bean.BeanModelProperty.<init>(BeanModelProperty.java:26)
at com.mangofactory.swagger.models.property.bean.BeanModelPropertyProvider.beanModelProperty(BeanModelPropertyProvider.java:166) (...rest of stacktrace )

The above mentioned property "year" is just one example, tried the same without the class containing the property year.

The weird thing is that Jackson seams to find the same exact methods / setter twice: javax.xml.datatype.XMLGregorianCalendar#setYear(1 params) vs javax.xml.datatype.XMLGregorianCalendar#setYear(1 params

I spent some time with the debugger and noticed that some DTOs seem to pass the check for conflicting setters just fine.

I have now spent many hours on this and couldn't come up with a solution. Most pages for this exception I found with Google talk about overloaded methods / setters, which is not the case with my DTOs - they're simple objects with nothing more than properties, setters and getters.

Any help would be greatly appreciated!

like image 769
zeisi Avatar asked Jan 22 '15 16:01

zeisi


1 Answers

The problem is that XMLGregorianCalendar has two setYear methods: setYear(int year) and setYear(BigDecimal year). You need to tell swagger to ignore one of them, you can configure a mixin for the XMLGregorianCalendar to only use getters (something like this). This will work if XMLGregorianCalendar is only used in the context of return values.

If that is not the case, you could set up a substitution type, using the directModelSubstitute option. When you configure you're SwaggerSpringMvcPlugin you might try something like one of the options below

@Bean
public SwaggerSpringMvcPlugin yourPlugin() {
    ...
    plugin.directModelSubstitute(XMLGregorianCalendar.class, String.class)
    //OR this, depending on how you intend to use it and how you want
    // the serialized/deserialized types to appear on the swagger UI
    plugin.directModelSubstitute(XMLGregorianCalendar.class, Date.class)   
    ...
    return plugin
}

Or if you dont care about the type being represented in your API documentation, you could ignore the type as well.

like image 57
Predrag Maric Avatar answered Sep 27 '22 22:09

Predrag Maric