Jersey UnmarshalException JAXB, XML with multiple getEntity() - java

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.

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

ModelMapper propertyMap with List of objects to a responseDTO

I'm new to modelMapper and I've encountered a problem when I tried to List of entity objects to a responseDTO.
User - Entity
UserResponseDTO - response DTO
I did the following configurating for propertyMap.
modelMapper.addMappings(new PropertyMap<List<User>, UserResponseDTO>() {
#Override
protected void configure() {
map().setName(source.get(0).getName());
map().setEmail(source.get(0).getEmail());
map().setUserRole(source.get(0).getUserRole());
map().setLanguage(source.get(0).getLanguage());
map().setTimeZone(source.get(0).getTimeZone());
// ....have more mapping ahead
}
});
But it gives following errors:
org.modelmapper.ConfigurationException: ModelMapper configuration errors:
1) Invalid source method java.util.List.get(). Ensure that method has zero parameters and does not return void.
2) Invalid source method java.util.List.get(). Ensure that method has zero parameters and does not return void.
3) Invalid source method java.util.List.get(). Ensure that method has zero parameters and does not return void.
4) Invalid source method java.util.List.get(). Ensure that method has zero parameters and does not return void.
5) Invalid source method java.util.List.get(). Ensure that method has zero parameters and does not return void.
Can anyone tell me how can I fix this issue?
It is exactly as the error message says:
Ensure that method has zero parameters
This is because (below excerpt from here)
You receive these errors because PropertyMap restricts what you can do inside configure().
I find it hard to understand what you actually are trying to map because it seems that you just want to flatten some list of Users to a DTO containing data from a just a single user, namely the first in the list (if not empty!). Maybe you are not doing what you should or maybe you do it on a wrong manner. At least it seems that you do not need any special mappings.
Assuming your User and UserResponseDTO would be like (simplified!) :
#Getter #Setter
#NoArgsConstructor
#AllArgsConstructor
public class User {
private Long id;
private String name;
private String email;
}
and
#Getter
#Setter
public class UserResponseDTO {
private String name;
private String email;
}
then mapping single user would be like:
new ModelMapper().map(users.get(0), UserResponseDTO.class);
and if you would like to map the who list, like:
new ModelMapper().map(users, UserListResponseDTO.class)
then your UserListResponseDTO would simply be something like:
#SuppressWarnings("serial")
public class UserListResponseDTO extends ArrayList<UserResponseDTO> {}
or if it happens that you need to return a list with just the first user:
new ModelMapper()..map(Arrays.asList(users.get(0)), UserListResponseDTO.class)

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

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 {

Cast an Array in to an Array of specific objects in Java

I have a response class - MyResponse as below to call the server using Retrofit2. resource is an array of objects.
public class MyResponse {
#SerializedName("success")
#Expose
private Boolean success;
#SerializedName("resource")
#Expose
private Array[] resource;
public ApiResponse(Boolean done, Array[] resource) {
this.done = done;
this.resource = resource;
}
//getters and setters
}
In the Activity, I created an Array as below:
MyResponse decodedResponse = response.body();
Array[] catsList = decodedResponse.getResource();
And I have a Model class Category as below:
public class Category {
#SerializedName("id")
#Expose
private Integer id;
#SerializedName("category")
#Expose
private String category;
//getters, setter and constructor
}
Each object of above catsList array follows above category model(with id and category keys). Now how I make an array of Category (Category[]) from above catsList array?
I can't do it as Category[] catsList = decodedResponse.getObject(); because I want to create more arrays for other models too. Therefore I am planning to create a common MyResponse class as above and cast it's generated array to specific model when needed.
Also following method(after changed Array[] =to=> Object[] in MyResponse) is not supported. It gives java.lang.ClassCastException: java.lang.Object[] cannot be cast to my.package.Category[] exception.
Object[] catsList = decodedResponse.getObject();
Category[] catsListCooked = (Category[]) catsList;
EDIT:
My JSON response from server has same style for every request types and uses one model for one request type. Because Retrofit wants to know which model class will use for the call in order to make a call as below.
#GET()
Call<MyResponse> getCategories(#Url String url);
Note: Please correct me if I can do this in another way. Because I call as mentioned above, I need to have a class in order to make a call.
So what I want to do is create a main response(MyResponse as above) which will receive the response and then use each model to fetch received data according to the request type. It is not possible to use the model directly when making a call because I have a custom JSON response from server.
i.e. If used model directly, then it gives errors such as expected BEGIN_ARRAY but provide BEGIN_OBJECT or expected BEGIN_OBJECT but provide BEGIN_ARRAY.
As commented below, from suggested duplicates, this suggestion by ytg looks like ok to achieve the solution. But using Arrays.copyOf() as suggested there, it seems it is not creating Category[] array to be useful since it gives "...cannot be stored in destination array of type..." error. Also other solutions from that question are not doable in my case.

JSON Parsing errors with RESTeasy/JAXB

I'm trying to make a call to the iTunes REST service that returns information about the genres defined in iTunes via a RESTeasy client. The JSON object returned by this call looks something like this:
{
"35":{
"name":"iPod Games",
"id":"35",
"url":"https://itunes.apple.com/us/genre/ipod-games/id35"
},
"36":{
"name":"App Store",
"id":"36",
"url":"https://itunes.apple.com/us/genre/ios/id36?mt=8"
}
}
I've defined my response object model like this:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
#JsonIgnoreProperties(ignoreUnknown = true)
public class ITunesGenre implements Serializable {
private static final long serialVersionUID = 4330727214147295490L;
#XmlElement
private String name = null;
#XmlElement
private String id = null;
...
}
However, when I make the call via my RESTeasy client, however, I get serialization errors. I believe it is due to the fact that this is not a true List or array of objects. Instead, it seems like each entry has an "identifier" on it (in the example above, the "35" or "36").
Given a JSON object like this, how do I map this so that the RESTeasy client can deserialize it? I've not encountered objects of this format before. I obviously can't hard-code each identifier, since there will be several and they could potentially change.
You can see the full JSON object returned by this call (it's sizable) by clicking here. You'll see that this object structure is found throughout this object, rather than using simple Lists or Arrays of objects.
Any ideas? I'd really appreciate any help you can give.
The response is a Map so root element is not your ITunesGenre class but the Map.I suppose that it is clear how to modify response object.
I suppose it could look something like this (though i haven't tested it)
#XmlRootElement
public class Response implements Serializable
{
public Response(){
}
private java.util.Map<String, Genre> genres = new java.util.HashMap<String, Genre> ();
}
public class Genre implements Serializable {
private static final long serialVersionUID = 4330727214147295490L;
public Genre(){
}
#XmlElement
private String name = null;
#XmlElement
private String id = null;
...
}

Categories