1

I am writing an API using Spring MVC and I am coming up with a problem allowing apps written in different languages to consume my API.

It turns out that the "Ruby users" like to have their params named in snake_case and our "Java users" like to have their param names in camel_case.

Is it possible to create my methods that allow param names to be named multiple ways, but mapped to the same method variable?

For instance... If I have a method that accepts a number of variables, of them there is mapped to a postal code. Could I write my method with a @RequestParam that accepts BOTH "postal_code" and "postalCode" and maps it to the same variable?

1
  • why do you make your code more complicated bacause of "Ruby users". Api should be client independent. Commented Nov 23, 2016 at 12:40

2 Answers 2

1

Neither JAX-RS @QueryParam nor Spring @RequestParam support your requirement i.e., mapping multiple request parameter names to the same variable. I recommend not to do this as it will be very hard to support because of the confusion like which parameter is coming from which client.

But if you really wanted to handle this ((because you can't change the URL coming from 3rd parties, agreed long back), then the alternative is to make use of HandlerMethodArgumentResolver which helps in passing our own request argument (like @MyRequestParam) to the controller method like as shown in the below code:

Controller class:

@Controller
public class MyController { 
    @RequestMapping(value="/xyz")
    public void train1(@MyRequestParam String postcode) {//custom method argument injected
        //Add your code here
    }
}

MyRequestParam :

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface MyRequestParam {
}

HandlerMethodArgumentResolver Impl class:

public class MyRequestParamWebArgumentResolver implements HandlerMethodArgumentResolver  {

    @Override
    public Object resolveArgument(MethodParameter parameter,   
           ModelAndViewContainer mavContainer, 
            NativeWebRequest webRequest, 
             WebDataBinderFactory binderFactory) {

        MyRequestParam myRequestParam = 
                parameter.getParameterAnnotation(MyRequestParam.class);

        if(myRequestParam != null) {

            HttpServletRequest request = 
                (HttpServletRequest) webRequest.getNativeRequest();

            String myParamValueToBeSentToController = "";
            //set the value from request.getParameter("postal_code") 
             //or request.getParameter("postalCode")

            return myParamValueToBeSentToController;
        }         
        return null;
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return (parameter.getParameterAnnotation(MyRequestParam.class) != null);
    }    
}

WebMvcConfigurerAdapter class:

@Configuration
class WebMvcContext extends WebMvcConfigurerAdapter {

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new MyRequestParamWebArgumentResolver());
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

I think what you want to do is not allowed by Spring framework with the annotation RequestParam.

But if you can change the code or say to your third party to modify the calls i would suggest you 2 options

Option 1:

Use the @PathVariable property

@RequestMapping(value = "/postalcode/{postalCode}", method = RequestMethod.GET)
public ModelAndView yourMethod(@PathVariable("postalCode") String postalCode) {
//...your code

Here does not matter if the are calling your URL as:

http://domain/app/postalcode/E1-2ES
http://domain/app/postalcode/23580

Option 2:

Create 2 methods in your controller and use the same service

 @RequestMapping(value = "/postalcode", method = RequestMethod.GET, params={"postalCode"})
public ModelAndView yourMethod(@RequestParam("postalCode") String postalCode) {
    //...call the service


 @RequestMapping(value = "/postalcode", method = RequestMethod.GET, params={"postal_code"})
public ModelAndView yourMethodClient2(@RequestParam("postal_code") String postalCode) {
    //...call the service

If is possible, I would suggest you option 1 is much more scalable

3 Comments

What makes option 1 more scalable? How does it work with, say, 5 parameters? Why does yourMethodClient2 not simply call yourMethod?
With 5, 10 or more parameters it will work just fine the second option is not very good, mainly becouse of duplicated code.
always depends on the kind of methods, number of parameters, possibility to increase the number of third parties,...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.