javaspring-bootspring-mvcswaggerspring-restcontroller

Java SpringBoot @PathVariable on RestController


I have the following @RestController:

package io.github.paulmarcelinbejan.coandaairlines.reservationsystem.adapters.inbound.controller.rest;

import java.util.List;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import io.github.paulmarcelinbejan.coandaairlines.reservationsystem.adapters.inbound.impl.rest.CurrencyInboundAdapterRestImpl;
import io.github.paulmarcelinbejan.coandaairlines.reservationsystem.ports.currency.domain.CurrencyDTO;
import io.github.paulmarcelinbejan.davinci.adapters.api.DavinciApiResponse;

import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/currency")
public class CurrencyRestController {

    private final CurrencyInboundAdapterRestImpl currencyInboundAdapterRestImpl;

    @GetMapping(value = "/id/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
    public DavinciApiResponse<CurrencyDTO> findById(@PathVariable Integer id) {
        return currencyInboundAdapterRestImpl.findById(id);
    }

    @GetMapping(value = "/code/{code}", produces = MediaType.APPLICATION_JSON_VALUE)
    public DavinciApiResponse<CurrencyDTO> findByCode(@PathVariable String code) {
        return currencyInboundAdapterRestImpl.findByCode(code);
    }

    @GetMapping(value = "/", produces = MediaType.APPLICATION_JSON_VALUE)
    public DavinciApiResponse<List<CurrencyDTO>> findAll() {
        return currencyInboundAdapterRestImpl.findAll();
    }

}

but when I access Swagger, it doesn't show me the space to insert the pathVariable:

enter image description here

If I try to execute I have the following exception:

{
  "status": "KO",
  "errors": {
    "timestampUTC": "2024-04-02T11:24:45.416132Z",
    "exceptionType": "IllegalArgumentException",
    "message": "Name for argument of type [java.lang.Integer] not specified, and parameter name information not available via reflection. Ensure that the compiler uses the '-parameters' flag."
  }
}

same issue also from postman:

enter image description here

If I remove the @PathVariable then on swagger I can see it:

enter image description here

but still same error:

{
  "status": "KO",
  "errors": {
    "timestampUTC": "2024-04-02T11:26:56.186060Z",
    "exceptionType": "IllegalArgumentException",
    "message": "Name for argument of type [java.lang.Integer] not specified, and parameter name information not available via reflection. Ensure that the compiler uses the '-parameters' flag."
  }
}

On another project, I have similar @RestController:

package com.hyperbank.types.currency.controller;

import java.util.List;

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.hyperbank.types.currency.dto.CurrencyResponse;
import com.hyperbank.types.currency.dto.CurrencySaveRequest;
import com.hyperbank.types.currency.dto.CurrencyUpdateRequest;
import com.hyperbank.types.currency.mapper.CurrencyMapper;
import com.hyperbank.types.currency.service.CurrencyService;

import io.github.paulmarcelinbejan.toolbox.exception.functional.FunctionalException;
import io.github.paulmarcelinbejan.toolbox.utils.validation.ValidatorUtils;
import io.github.paulmarcelinbejan.toolbox.web.response.OkResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/currency")
public class CurrencyRestController {

    private final CurrencyService currencyService;
    
    private final CurrencyMapper currencyMapper;

    @GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
    public @ResponseBody CurrencyResponse findById(@PathVariable Integer id) throws FunctionalException {
        return currencyMapper.toResponse(currencyService.findById(id));
    }

    @GetMapping(value = "/", produces = MediaType.APPLICATION_JSON_VALUE)
    public @ResponseBody List<CurrencyResponse> findAll() {
        return currencyMapper.toResponses(currencyService.findAll());
    }

}

and on that one, there are no issue:

enter image description here

any idea ?


Solution

  • Reason : This problem arises because Swagger, a tool that helps you document your API, need to know the names of the variable you use in your code. But, sometimes ,the java compiler doesn't save this information by default.So, Swagger get confused and can't show the correct documentation for your API.

    Solution : To fix that, you need to tell the java compiler to save this information. once you do that, Swagger will find the pathvariable name and display the correct documentation for your API.

    Add (Maven pom.xml file)

            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <compilerArgs>
                            <arg>-parameters</arg>
                        </compilerArgs>
                    </configuration>
                </plugin>
            </plugins>