I am using a Spring Boot application (Version 2.4.5) with Jackson. Can I add an fat jar which is using gson without affecting the Jackson deserialisation of the application?
When I add the jar to my application, the application uses gson everywhere to deserialise JSONs. But since I am using some special functions of Jackson this fails.
I can unfortunately not change this in the library.
I use Gradle to add the fat jar like this in the dependencies:
implementation fileTree(dir: 'libs', include: ['*.jar'])
I am building Jacksons object mapper like:
private static ObjectMapper getMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jdk8Module());
mapper.registerModule(new JavaTimeModule());
return mapper;
}
And following lines throws an error:
List<User> users = objectMapper.readValue(getReader("users.json"), new TypeReference<>() {});
java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class User (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; onek.books.backend.model.book.Book is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @445d3853)
And Gson is added to fat jar with following maven dependencies:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson-version}</version>
</dependency>
<dependency>
<groupId>io.gsonfire</groupId>
<artifactId>gson-fire</artifactId>
<version>${gson-fire-version}</version>
</dependency>
Edit
As suggested that is not due to gson I tried to narrow it down and added all dependecies one by one and none caused the error by itself.
But I might have found the cause, but I don't know how to solve this. It is the way Jacksons typeFactory construct it's type. For the line:
List<Book> books = objectMapper.readValue(getReader("books.json"), new TypeReference<>() {});
If the jar ist not existent the constructed Type looks like:
result = {CollectionType@13667} "[collection type; class java.util.List, contains [simple type, class onek.books.backend.model.book.Book]]"
_elementType = {SimpleType@13669} "[simple type, class onek.books.backend.model.book.Book]"
_superClass = null
_superInterfaces = {JavaType[1]@13670}
_bindings = {TypeBindings@13671} "<Lonek/books/backend/model/book/Book;>"
_canonicalName = null
_class = {Class@352} "interface java.util.List"
_hash = -95724352
_valueHandler = null
_typeHandler = null
_asStatic = false
Which is what I would expect because the Book-Class is in the type. But if I add the jar the constructed Type looks like:
result = {SimpleType@11757} "[simple type, class java.lang.Object]"
_superClass = null
_superInterfaces = null
_bindings = {TypeBindings@11759} "<>"
_canonicalName = null
_class = {Class@595} "class java.lang.Object"
_hash = 1063877011
_valueHandler = null
_typeHandler = null
_asStatic = false
And jackson deserialize it as an LinkedHashmap with this type causing the ClassCastException.
But I realy don't know how to continue from here. Can an external jar alter some parts of the Jackson TypeFactory?