jackson-databind "object is not an instance of declaring class" - java

I have been upgrading to a later version of jackson (i.e. from org.codehaus... to com.fasterxml...) and suddenly I am facing many weird errors. After hours of trying and adjusting I still cant get it to work so I am asking you guys if you can help me.
I have the following method:
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("getTerminalsByIdAndLocation")
List<SearchResultDto> getTerminalsByIdAndLocation(#QueryParam("location") String location, #QueryParam("id") Integer id) throws BusinessException;
and that functions implementation just does a lookup in a repository.
The SearchResultDto looks like this:
#JsonIgnoreProperties(ignoreUnknown = true)
public class SearchResultDto implements Serializable {
private static final long serialVersionUID = 1L;
private TerminalId terminalId;
private Integer location;
private String streetNumber;
private String postalcoldeCity;
private Status status;
// getters and setters with no annotation or so
}
When I am now calling my method I am getting the following error:
Caused by: com.fasterxml.jackson.databind.JsonMappingException: object is not an instance of declaring class (through reference chain: java.util.ArrayList[0]-><long package>.SearchResultDto["terminalId"])
After a lot of trying I thought I will just remove the terminalId and then it changes to:
Caused by: com.fasterxml.jackson.databind.JsonMappingException: object is not an instance of declaring class (through reference chain: java.util.ArrayList[0]-><long package>AtmSearchResultDto["location"])
I am clueless, what is wrong here?
EDIT
I also tried using #JsonIgnore on everything except String streetNumber but then the same exception happens just for streetNumber

Long story short: I messed up my class path and there were two class loaders, the implementation of the REST method called a repository from the database module from where it got the instance from a different class loader. After adjusting my maven scopes and import types it is now working!

I had a similar issue for me the problem was that one of my POJOs was final. Removing the final keyword did the trick.
public final class AccessControlMap extends HashMap<Permission, Set<AccessType>>
//Before
public final class AccessType {
//After
public class AccessType {

Related

Object not being able to map to POJO class

I am getting a response, which I converted to Pojo class with one field of type Object. Now when I am trying to cast the Object type to another Pojo class its throwing the error :
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to SecondClass
Code :
FirstClassResponse firstClassResponse = (FirstClassResponse) convertJSONToObject(firstClassResponseJson, FirstClassResponse.class);
//jsonToObject method
public static Object convertJSONToObject(String jsonRequest, Class objectClassType) throws Exception {
Object object = gson.fromJson(jsonRequest, objectClassType);
return object;
}
Here, firsClass object when printed gives following result :
FirstClassResponse [modifiedResponse=null, response={id=123, username=abc, balance=0.0, currencycode=EUR, created=2021-03-30 16:31:54, agent_balance=0.0, sessionid=123}]
Now, the error happens in the following line :
SecondClassResponse modifiedResponse = (SecondClassResponse) firstClassResponse.getResponse();
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to SecondClassResponse
I am sharing the POJO for FirstClassResponse and SecondClassResponse :
public class FirstClassResponse{
private SecondClassResponse modifiedResponse;
private Object response;
//getter, setter
}
public class SecondClassResponse{
private String id;
private String username;
private double balance;
private String currencycode;
private String created;
private double agent_balance;
private String sessionid;
//getter, setter
}
private Object response;
Make this a SecondClassResponse, not an Object. With it being an Object, GSON doesn't know that this should be a SecondClassResponse, so it just shoves the map in there as a Map, which obviously can't be cast.
The entire point of using GSON is to turn everything into specific objects so you can use it in a more Java like way. If you store something as an Object when converting from GSON, you're almost always doing it wrong.
That FirstClassResponse is completely superfluous; use SecondClassResponse instead.
Just look at the JSON ...and then explain to me how to map as FirstClassResponse?
And you've not even object-relational mapping (as the GSON converter does), but you're parsing.
Perhaps gson.fromJson cannot convert the attribute class of the class before. You can try to take out firtClassResponse.getResponse() and do the conversion separately

How to avoid 'Private field is never assigned' which is caused by using MyBatis and Immutable POJO?

my goal is to avoid problem 'Private field is never assigned' without using #SupressWarnings or creating a defined constructor.
I am aware using annotation will lead to technical debt for the long run. However, I can't not justify the Java verbosity (although I love it at times when debugging a bug), this code is easier to read.
Method that I do not wish to use:
SupressWarnings("unused") written above the class statement.
Creating a defined constructor which is not necessary since MyBatis can modify the object attribute regardless there is a setters or not for example when you use #SelectKey.
Creating a setter which will never be used.
This is the sample code for the model I am going to standardize for MyBatis.
model/NameModel.java
package com.example.mssqlserver.model;
import com.fasterxml.jackson.annotation.JsonInclude;
#SuppressWarnings("unused") // MyBatis does not need a defined constructor nor a setters.
#JsonInclude(JsonInclude.Include.NON_NULL) // filter: only non_null, alternative: spring.jackson.default-property-inclusion=NON_NULL in application.properties
public class NameModel {
private Integer id;
private String name;
private String newid;
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public String getNewid() {
return newid;
}
public boolean requestIsValid() {
return !this.name.isEmpty();
}
}
the first is like this
public class MainActivity extends AppCompatActivity {
private PDFView pdfView;
public MainActivity(PDFView pdfView) {
this.pdfView = pdfView; }
and i edit like this
public class MainActivity extends AppCompatActivity {
private final PDFView pdfView;
public MainActivity(PDFView pdfView) {
this.pdfView = pdfView;
}
and the problem solved. thanks
javac will not complain on this.
javac -cp *.jar com/example/mssqlserver/model/NameModel.java
So it is likely be the IDE being used.
It may have a configuration Errors/Warnings option for this specific case.
Unfortunately couldn't find such an option in my Eclipse IDE - though I remember there was one - so cannot point the exact option.
A related question: Why no "field is never assigned" warning with #Mock

Spring Boot Rest API Enumerate some Java types

I am building Spring Boot webflux REST API functionality that needs to work with data containing few Java type's (let's consider String, Integer, Double for example) information as part of JSON request/responses. Attribute representing Java type must be persistable inside mongodb as well (should not be problem once JSON can work with such attribute). I have following model class and type enumeration which is used by REST API to serialize/deserialize JSON message's.
#Getter
#ToString
#EqualsAndHashCode(exclude = "id")
#Document(collection = "core_scheme")
#JsonDeserialize(builder = SchemeModel.Builder.class)
#Builder(builderClassName = "Builder", toBuilder = true, setterPrefix = "with")
public class SchemeModel {
#Id
private final String id;
#Field(name = "userId") private final String userId;
#Field(name = "date") private final String creationDate;
#Field(name = "properties") private final Map<String, SchemeTypes> properties;
}
public enum SchemeTypes {
INTEGER, STRING, DOUBLE
}
Serialization and deserialization work's well. Now the problem is that when i want to resolve real Java type's stored inside Map<String, SchemeTypes> properties map i need to do mapping similar to this (just abstraction not real code):
SchemeTypes.INTEGER => Java Integer class
SchemeTypes.STRING => Java String class
SchemeTypes.DOUBLE => Java Double class
Is there any more simple way to represent Java type's stored inside model class and used within serialized/deserialized JSON file's so i can directly use it to deduce Java type without additional validation that it's valid Java type. For example if type's enumarated inside mentioned enum would have exactly same naming as real Java type's i could do following without any mapping:
public void deduceClass(SchemeTypes type) {
Class myClass = Class.forName(type.toString());
}
Note that i am looking for a solution which would work out of the box (i don't have to validate type's provided by user). If such solution would be harder to implement as mentioned mapping i will stick with mapping.
If you weren't saving this entity I could say you can actually directly map the SchemeTypes into corresponding class like following
public enum SchemeTypes {
INTEGER(Integer.class), STRING(String.class), DOUBLE(Double.class);
private final Class clazz;
private SchemeTypes(Class clazz){
this.clazz = clazz;
}
public Class getClazz(){
return clazz;
}
}
But as you are saving this it could cause some issue to deserialize.
Maybe you can save not the SchemaType instance directly but just the name of enum to overcome this like following
private final Map<String, String> properties;
and find the corresponding clazz value with a static method on this class like following
public static Class findClazzFor(String schemeTypeName){
return SchemeTypes.valueOf(schemeTypeName).getClazz();
}
Nevertheless I think cleanest solution would be keeping the SchemeType class instance mapping somewhere as a one-to-one map. And retrieve the corresponding class for provided schemeType as in the getClazz method above.

Serialize own class

i'm experiencing some problems with the serialization of Java and haven't found my Error.
I want to serialize my class, save it and read it again. This is the class i want to serialize:
public class MusicItem implements Serializable {
private static final long serialVersionUID = 6429052113846297403L;
public String title;
public String album;
public String artist;
public String art;
public String musiclocation;
}
And when i want to write it i get the following error:
08-07 14:21:37.723: W/System.err(9557): java.io.NotSerializableException: de.godev.gomusic.MainActivity
I hope you can help me.
Thanks in Advance,
The class which is not getting serialized is de.godev.gomusic.MainActivity
Please post the source of MainActivity class as well
If MusicItem is an inner class, you should make it static. An inner class maintains a reference to the object that it's contained in, and if you try to serialize it, the containing object has to be serialized as well.
To make a nested class static declare it with the static keyword:
public static class MusicItem implements ...

Jersey UnmarshalException JAXB, XML with multiple getEntity()

ive got this exception.
My Object looks like this:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class ObjectDTO implements Serializable {
/**
*
*/
private static final long serialVersionUID = -8545841080597549468L;
#XmlElement(name="objectId")
private String objectId;
#XmlElement(name="owner")
private String owner;
#XmlElement(name="objectName")
private String objectName;
Constructor, getter/setter, toString, Hash...
Now I invoke my service method with:
ClientResponse postRes = service.path("rest").path("object").accept(MediaType.APPLICATION_XML).post(ClientResponse.class, object);
When I do
System.out.println(postRes.getEntity(ObjectDTO.class));
it works fine. But when I try to do a get operation on my object like:
String string = postRes.getEntity(ObjectDTO.class).getObjectId();
I get the exception.
javax.ws.rs.WebApplicationException: javax.xml.bind.UnmarshalException - with linked exception: [org.xml.sax.SAXParseException: Premature end of life.]
Whats wrong?
Looks like you are trying to read the entity twice (the second time the entity stream is already consumed). Instead of calling postRes.getEntity() twice, call it just once, store the result in a variable and then operate on that variable.

Categories