valik
valik

Reputation: 2094

How can I have two return types in one controller returning Collection of Class A or Object of Class B

I am trying to follow Rest Principles, so I have two rest controllers with a base URL localhost:8088/trucks.

First, I have to get all trucks:

@GetMapping(value = "/trucks")
public final Collection<TruckDto> getAllTrucks() {
    LOGGER.debug("test: getAllTrucks()");
    Collection<Truck> trucks = truckService.getAllTrucks();
    return mappingService.map(trucks, TruckDto.class);
}

Note, my issue also has to do with the fact that I have different classes I am returning for truckById and truckByTruckCode.

And I have 'get truck by ID' service:

@GetMapping(value = "/trucks/{truckId:[0-9]+}")
@ResponseStatus(HttpStatus.FOUND)
@ResponseBody
public final TruckDto getTruckId(@PathVariable(value = "truckId") final Integer truckId) {
    LOGGER.debug("test: truckId({})", truckId);
    Truck truck = truckService.getTruckById(truckId);
    return mappingService.map(truck, TruckDto.class);
}

Now I have a get by truckCode that works but it doesnt follow the rest principle , which is something like , there should be only one base url and all others build from it , here it is

  @ResponseStatus(HttpStatus.OK)
  @ResponseBody
  @GetMapping(value = "/trucks/{truckCode:[0-9]*[a-zA-Z][a-zA-Z0-9]*}")
  public final TruckWithAvgPetrolDto getTruckByTruckCode (@PathVariable(value = "truckCode")
            final String truckCode) {
      LOGGER.debug("getTruckByTruckCode()");

      TruckWithAvgDto truck = truckService.getTruckByTruckCode(truckCode);
      return  mappingService.map(truck, TruckWithAvgPetrolDto.class);
  }

Now it works but I think it should be an optional param there for it should be in one method. So maybe I can have some sort of optional return type because I have two different services, methods to return in both situations.

Because get by id just gets truck detail, but get by trukCode performs a left join and gets truck average consumption of petrol from an order table so I have two different DTOs for get by id and get by truckCode.

My questions are how can I get something like one method say getBY(param) if I put a number it should get by id and return TruckDto but if I put a code like BY788 it should get by code and return a TruckWithAvgPetrolDto. Is that's possible?

Upvotes: 1

Views: 81

Answers (1)

valik
valik

Reputation: 2094

This is a solution that works but i will need verification that it is ok to do such in rest or it is bad practice

  @GetMapping("/trucks/{value}")
    public ResponseEntity<?> getTruckByIdOrCode(@PathVariable(value = "value" )String value) {

        if (value.matches("[0-9]*[a-zA-Z][a-zA-Z0-9]*")) {
            TruckWithAvgDto list = truckService.getTruckByTruckCode(value);
            return new ResponseEntity<TruckWithAvgDto>(list, HttpStatus.FOUND);
        }else {
            Truck truck = truckService.getTruckById(Integer.parseInt(value));
            return new ResponseEntity<Truck>(truck,HttpStatus.FOUND);
        }

    }

Upvotes: 1

Related Questions