Home > Enterprise >  Ambiguous mapping, same URLs which I don't want to change
Ambiguous mapping, same URLs which I don't want to change

Time:07-06

I have next situation, i have controller interface:

package com.example.poster_final_project.controllers.api;


import com.example.poster_final_project.service.dto.api.IPage;
import org.springframework.web.bind.annotation.*;

@RequestMapping("/poster/event")
public interface IController<C,R,P extends IPage<?>> {

    @PostMapping(value = "/{type}")
    C create(@RequestBody C eventDto, @PathVariable String type);

    @GetMapping(value = "/{type}/{uuid}")
    R readEventInfo(@PathVariable String type,@PathVariable String uuid);


    @GetMapping(value = "/{type}")
    P readPageOfEvent(@PathVariable String type,
                      @RequestParam(required = false) Integer size,
                      @RequestParam(required = false) Integer page);

    @PutMapping(value = "/{type}/{uuid}/dt_update/{dt_update}")
    C updateEvent(@PathVariable String type,
                  @PathVariable String uuid,
                  @PathVariable(name = "dt_update") String dtUpdate,
                  @RequestBody C eventBody);

}

which is extended by another 2 controller, but already with concrete types:

first

package com.example.poster_final_project.controllers.api;
    
import com.example.poster_final_project.service.dto.concerts.EventConcertToCreate;
import com.example.poster_final_project.service.dto.concerts.EventConcertToRead;
import com.example.poster_final_project.service.dto.concerts.PageOfConcertToRead;
    
    public interface IEventConcertController extends IController<EventConcertToCreate, EventConcertToRead, PageOfConcertToRead> {}

second

package com.example.poster_final_project.controllers.api;

import com.example.poster_final_project.service.dto.films.EventFilmToCreate;
import com.example.poster_final_project.service.dto.films.EventFilmsToRead;
import com.example.poster_final_project.service.dto.films.PageEventFilmsToShow;

public interface IEventFilmsController extends IController<EventFilmToCreate, EventFilmsToRead, PageEventFilmsToShow>{}

But i have a problem, i can't change URLs, to exclude Ambiguous mapping. I thought about one input controller that will redirect already to specific, but it's differrnt types in @RequestBody. So what can i do (other than renaiming URLs), to exclude Ambiguous mapping?

CodePudding user response:

I think I would use a fixed path per type, and abstract over the service layer.

interface EventService<E extends Event> {
 E create(E data);
 E get(String uuid);
 E update(E data);
}
interface DtoMapper<E extends Event, D extends Dto<E>> {
 E toDomainObject(D data);
 D toDto(E domainObject);
}
@RequestMapping("/poster/event")
class EventController {
  EventService<Film> filmService;
  EventService<Concert> concertService;
  DtoMapper<Film> filmMapper;
  DtoMapper<Concert> concertMapper;

  @PostMapping(value = "/concert")
  Concert create(@RequestBody ConcertDto eventDto) {
    return concertService.create(concertMapper.toDomainObject(eventDto));
  }
  @PostMapping(value = "/film")
  Film create(@RequestBody FilmDto eventDto) {
    return filmService.create(filmMapper.toDomainObject(eventDto));
  }

  @GetMapping(value = "/concert/{uuid}")
  Concert getConcert(@PathVariable String uuid) {
    return concertMapper.toDto(concertService.get(uuid));
  }
  @GetMapping(value = "/film/{uuid}")
  Film getFilm(@PathVariable String uuid) {
    return filmMapper.toDto(filmService.get(uuid));
  }

  ...
}

That makes the controller responsible for the translation between incoming data and service layer, and you have a clean service with the same functionality for each type.

There are a lot of methods in the controller, but I don't think you'll have a hard time having a type determined by a String along with a type Dto object in the method signature. You can return Object and the objectmapper will create valid JSON outbound, and incoming you can declare a Map<String, String> as a body that can construct the object you need, but I would bet you'll have worse code down the road if you do that.

  • Related