0

I have a spring mvc API (config in XML) with multiple services inside. But when I try to add a service with a @RequestMapping containing a path variable /{theCurrencyCode}, the resource created is not what I expected.

What I expected :

http://localhost:8080/api/v3/parameters/currencies/EUR

What works :

http://localhost:8080/api/v3/parameters/currencies/{theCurrencyCode}?theCurrencyCode=EUR

This is my mapping :

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.List;

import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

@RequestMapping(value = "v3/", produces = { APPLICATION_JSON_VALUE })
public interface ParametersApi {

  @RequestMapping(
      value = "/parameters/currencies/{theCurrencyCode}",
      produces = { "application/json" },
      method = RequestMethod.GET)
  ResponseEntity<List<Currency>> GetCurrencies(@PathVariable("theCurrencyCode") String theCurrencyCode);

}

Implementation :

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;

import java.util.ArrayList;
import java.util.List;

@Controller
public class ParametersApiController implements ParametersApi{

  private final CurrenciesService service;

  @Autowired
  public ParametersApiController(CurrenciesService service) {
    this.service = service;
  }

  @Override
  public ResponseEntity<List<Currency>> GetCurrencies(String code) {

    final List<Currency> currencies = service.getCurrencies(code);

    return new ResponseEntity<>(currencies, HttpStatus.OK);
  }
}

Swagger UI confirmed this, seeing theCurrencyCode as a "Parameter Type" query instead of path.

Screenshot from swagger UI

How do I get my @PathVariable to work ?

Mualig
  • 1,444
  • 1
  • 19
  • 42
  • 1
    Seems that such question has already been discussed [here](https://stackoverflow.com/questions/8002514/spring-mvc-annotated-controller-interface) – nikita_pavlenko Jun 08 '17 at 15:39

3 Answers3

1

Pathvariable is missing from your method implementation. So to fix, you need to write something like this:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;

import java.util.ArrayList;
import java.util.List;

@Controller
public class ParametersApiController implements ParametersApi{

    private final CurrenciesService service;

    @Autowired
    public ParametersApiController(CurrenciesService service) {
        this.service = service;
    }

    @Override
    public ResponseEntity<List<Currency>> GetCurrencies(@PathVariable String theCurrencyCode) {
        final List<Currency> currencies = service.getCurrencies(theCurrencyCode);
        return new ResponseEntity<>(currencies, HttpStatus.OK);
    }
}
Jack
  • 86
  • 1
  • 6
1

Annotated method parameters are not being passed to all implementations. So that is why you need to redeclare it.

nikita_pavlenko
  • 658
  • 3
  • 11
  • Adding the `@PathVariable` in the implementation worked. The only stange thing is that I have an other API with the same logic for Interface / implementation and it's working without the `@PathVariable` in the implementation. – Mualig Jun 09 '17 at 07:01
0

Change your interface as:

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.List;

import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

@RequestMapping(value = "v3/", produces = { APPLICATION_JSON_VALUE })
public interface ParametersApi {

  @RequestMapping(
      value = "/parameters/currencies/{theCurrencyCode}",
      produces = { "application/json" },
      method = RequestMethod.GET)
  ResponseEntity<List<Currency>> GetCurrencies(@PathVariable String theCurrencyCode);

}

Your path variable name and URL path name should match. No need to specify parameter name in the bracket.

kk.
  • 3,747
  • 12
  • 36
  • 67