I'm building a set of microservices in Spring Boot. I've got one service which interfaces with the database and has a series of RESTful endpoints which other apps can hit. Many of these table entities are complex objects and are served up as a JSON object but some are simple parameters and so are served as strings. When I hit the main DB service endpoints, all data is returned fine without issue.
I have a series of other applications which consume this data in various ways. Because many objects are reused across applications (the DB service response shape, the person entity POJO, etc), I've got a package made with some common classes. Each app imports these common classes and then makes calls to the main DB service via RestTemplate
. Because the response is always wrapped in a standard way, I am getting the values by performing an exchange which expects a ParameterizedTypeReference
of the response wrapper with the appropriate POJO or Java variable (String, int, etc).
As of 5 months ago, all was good. The app was deployed to a server and is still operating normally. However, I recently went back in to the code in order to make some modifications and now I find that when I run the app locally some of the endpoints fail with the following error:
java.lang.NoSuchMethodError: com.fasterxml.jackson.annotation.JsonFormat$Value.hasLenient()Z
I thought at first that perhaps the two POMs were out of sync and one was pulling a newer version of Jackson but after hard coding the version in the POM to be 100% certain they were the same (version 2.10.1), it still has the same issue. It should also be noted that the method in the error message appears to have been added in version 2.9 and has not been deprecated as of this moment in time. This error only happens when trying to retrieve data from endpoints returning POJOs and not when the data type is a String. It may also be relevant that the call appears to never actually leave the app before throwing an error as the DB service endpoint never gets hit.
Any ideas why I'm getting this error and how I could resolve it?
Response Object:
public class DatabaseServiceResponse<T> {
@JsonInclude(Include.NON_NULL)
private List<T> entities;
@JsonInclude(Include.NON_NULL)
private String error;
[getters and setters ommitted]
}
Person Service:
public List<Person> getPeople() {
List<Person> people = new ArrayList<>();
HttpHeaders headers = getHeaders();
HttpEntity<Object> requestEntity = new HttpEntity<>(null, headers);
ResponseEntity<DatabaseServiceResponse<Person>> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, new ParamaterizedTypeReference<DatabaseServiceResponse<Person>>() {}); // Fails on this line
if (response.getStatusCode() == HttpStatus.OK) {
people = response.getBody().getEntities();
} else {
throw new ServiceException("Error retrieving people");
}
return people;
}
public List<String> getPersonTypes() {
List<String> personTypes = new ArrayList<>();
HttpHeaders headers = getHeaders();
HttpEntity<Object> requestEntity = new HttpEntity<>(null, headers);
ResponseEntity<DatabaseServiceResponse<String>> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, new ParamaterizedTypeReference<DatabaseServiceResponse<String>>() {}); // Works fine here
if (response.getStatusCode() == HttpStatus.OK) {
personTypes = response.getBody().getEntities();
} else {
throw new ServiceException("Error retrieving person types");
}
return personTypes;
}
Person App POM:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath />
</parent>
Common Elements POM:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.1</version>
<scope>provided</scope>
</dependency>
UPDATE I believe the external library and the potentially out-of-sync POM files was a red herring. I have copied all of the relevant classes into the main project to remove the dependency on the external package and I have the same issue. I've also tried completely upgrading all versions to the latest and still no luck. Jackson, for whatever reason, will map JSON to a String or a list of Strings but just will not map my JSON to a POJO.