springrestswaggerswagger-ui

Spring REST API Swagger UI @ModelAttribute request URL and parameter type


I have some problems trying to make my swagger UI return what I want. The problem is that I want to display the areaName as a path parameter type NOT a query in the Swagger UI. I can do that by using @PathVariable String "areaName".

BUT I want to validate the areaname in a separate requestclass and now I'm trying to use @Valid @ModelAttribute instead. The problem with this is that Swagger gives me a boring request URL like:

/v1/areas/{areaName}/series?areaName=testarea&from=20151201

I want it to show the same way as when I'm using @PathVariable:

/v1/areas/testarea/series?from=20151201

I have tried playing around with the @ApiParam in the requestclass and even tried to hidden=true to keep a @PathVariable in the controller and just hide the @ApiParam in the requestclass to not get a duplicate of areaName in the Swagger UI but the hidden doesn't seem to work. I'm using Swagger/SwaggerUI version 2.3.0.. Any ideas?

Requestclass:

public class AreaSeriesRequest {

@ApiParam(value = "Area selector, which area to get series from.", required = true)
@EnergyAreas
private String areaName;

public String getAreaName() {
    return AreaName;
}

public void setAreaName(String areaName) {
    this.areaName = areaName;
}

Controller:

@RequestMapping(value = "/{areaName}/series", method = GET, produces = json)
@ResponseStatus(HttpStatus.OK)
    public Page<GroupSeriesDto> getAreaSeriesPaginated(
            //@PathVariable String areaName,
            @Valid @ModelAttribute AreaSeriesRequest seriesRequest, BindingResult seriesResult,
            @ModelAttribute PagingRequest pagingRequest,
            Principal currentUser) {

Solution

  • So the way i worked around this was to still use the @PathVariable but instead of @Valid @ModelAttribute on the areaName i did a seperate validator for this parameter.

    public class AreaValidator implements Validator {
    
    private static final List<String> types = Arrays.asList(
            "ALL",
            "XX1",
            "XX2",
            "XX3",
            "XX4"
    );
    
    @Override
    public boolean supports(Class<?> clazz) {
        return String.class.equals(clazz);
    }
    
    @Override
    public void validate(Object target, Errors e) {
        String value = (String) target;
    
        if (value == null || !types.contains(value.toUpperCase())) {
            e.reject(String.format("Area '%s' does not exist", value));
        }
    }
    

    And then used it in the controller like:

    new AreaValidator().validate(areaName, seriesResult);
    
    if (seriesResult.hasErrors())
    throw new AreaNotFoundException(areaName);