Cannot Deseralise to Concrete Java Type

110 Views Asked by At

I'm building a fitness tracker application which allows a user to track their workouts. A workout is comprised of a list of movements. The abstract Movement class is extended by several subtypes of movement.

Abstract class:

@XmlSeeAlso({BodyweightMovementDTO.class, CalorieMovementDTO.class,
             DistanceMovementDTO.class, WeightedMovementDTO.class})
public abstract class Movement {
  public abstract MovementType getType();
  public abstract void setType(final MovementType type);
}

Extended by:

@XmlRootElement(name = "weightedMovement")
public class WeightedMovementDTO extends Movement {
  private MovementType type;
  private Integer weight;
  private Integer reps;

  public WeightedMovementDTO(final MovementType type, final Integer weight, final Integer reps) {
    this.type = type;
    this.weight = weight;
    this.reps = reps;
  }

  //Getters and Setters

 }

And also extend by:

@XmlRootElement(name = "distanceMovement")
public class DistanceMovementDTO extends Movement {
  private MovementType type;
  private Integer distance;

  public DistanceMovementDTO(final MovementType type, final Integer distance) {
    this.type = type;
    this.distance = distance;
  }

  //Getters and setters
}

And two more similar classes.

The resource method that allows a PUT of a workout or WorkoutResultDTO is as follows:

  @PUT
  @Path("{user}/today")
  @Consumes({ MediaType.APPLICATION_JSON })
  public Response recordResult(@PathParam(value = "user") final String user, 
                               final WorkoutResultDTO result) {
    WorkoutController.recordResult(user, result);
    return Response.ok().build();
  }

The WorkoutResultDTO is the object which I assume is causing the problem as it has an ArrayList of the abstract Movement object.

@XmlRootElement(name = "workout")
public class WorkoutResultDTO implements Result {
  private int id = 0;
  private OcsidDate date = new OcsidDate(LocalDate.now());
  private Scale scale = null;
  private WorkoutType workoutType = null;
  private List<Movement> wod = new ArrayList<>();
  private boolean complete = false;
  private double time = 0.0;
  private int reps = 0;

  public WorkoutResultDTO() {}

  public WorkoutResultDTO(final int id) {
    this.id = id;
  }

  //Getters and Setters

}

The when I do a PUT to my endpoint using postman I get the following error returned:

Can not construct instance of ninja.ocsid.crossfit.dto.movement.abstracts.Movement, 
problem: abstract types either need to be mapped to concrete types, 
have custom deserializer, or be instantiated with 
additional type information  at [Source:org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@41d13e9b; 
line: 16, column: 9] (through reference chain: 
ninja.ocsid.crossfit.dto.result.WorkoutResultDTO["movements"])

I was lead to believe that adding the line:

@XmlSeeAlso({BodyweightMovementDTO.class, CalorieMovementDTO.class,
                 DistanceMovementDTO.class, WeightedMovementDTO.class})

would solve this problem as that annotation would give enough information as to how the abstract class can be deserialised to one of the concrete types, but this does not seem to be the case. Am I missing some other configuration or some custom class that is need to do this? I've been trying to solve this for two days now which much googling, but to no avail. Any input would be welcome. Thanks!

EDIT: Details of the PUT request attached in an image.

Details of PUT request

0

There are 0 best solutions below