0

I recently stumbled upon a problem that I could not find any references to although it's very unlikely nobody ever had this problem before.

Maybe someone can give me a heads-up on where to look.

Using JAX-RS to build a REST service running on JakartaEE 8 I created a method that's supposed to handle PUT requests from the client. This method is given a DTO object which, amongst other things, contains a HashMap that uses Long variables as keys.

This works just fine so far and the method accepts the input given by the clients PUT request. However when I check for the type of the variables that the keyset() method return for the HashMap it is not of type Long but instead of type String which obviously leads to problems later on.

Here is a shortened version of the code in question:

@PUT
@Path("edituser")
@Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Optional<DTOobject> editUser(@QueryParam("user_id") Long user_id, DTOobject dto_object) {
  for (Object i : dto_object.getOtherDTO_map().keySet()) {
    LOGGER.log(Level.INFO, "HashMap key of type: {0}", i.getClass().getName());
    // This will return java.lang.String as the type for the individual keys.
  }
  // do something and return something
}
public class DTOobject {
  // some other vars
  private HashMap<Long, OtherDTO> otherDTO_map;

  // getters and setters
}
Daki
  • 97
  • 9
  • Well if in the JSON, the keys are strings, the provider is not going to know to convert it to a number. Look at the JSON and see if it is in fact a string. – Paul Samsotha Nov 25 '20 at 22:47
  • Thanks for the pointer! That actually seems to be the problem here. What I still don't get is why... It should transfer a key of type Long but in the JSON it is instead shown as a String: "otherDTO_map":{"1":{OtherDTO-Contents}} – Daki Nov 30 '20 at 08:48
  • It's because of [type erasure](https://docs.oracle.com/javase/tutorial/java/generics/erasure.html), the type parameter is erased at runtime. The type ultimately becomes Oject because it is unbounded. So that's why a String is allowed to be put in at _runtime_. At compile-tme, it would be an error though if you tried to pass a String. – Paul Samsotha Nov 30 '20 at 15:56
  • Thanks for the explanation. That explains why jax-rs is able to save a String inside a Long variable but I was still wondering why it actually does that in the end. Found [this thread](https://stackoverflow.com/questions/6371092/can-not-find-a-map-key-deserializer-for-type-simple-type-class-com-comcast-i) where it is said that Map Keys will always be serialized as Strings and often won't be deserialized properly again. Only solution sadly seems to be to implement custom deserializers. To me this seems really odd, considering how common Maps are and that Long is a standard-object. – Daki Dec 04 '20 at 07:07

0 Answers0