简体   繁体   中英

Spring: handle ambiguous mapping with BadRequest

I'm developing a Spring application, and at the moment I'm implementing a search on our customers registry.

A key-pointy of our users request is that the search can be done for at most ONE of the following parameters : name OR id (can be partial) OR shop id (the shop where the customer is registered) Searches with more parameters ("more filters" if you prefer) in combination, are not allowed.

Here i ran into the problem: I developed a RestController with 1 endpoint handled by 3 different functions like this:

@RestController()
    @RequestMapping("v1/customers")
    public class ExampleController {

        /**
        * Search for customer's name (can be partial)
        * @param name
        * @return
        */
        @GetMapping(value="search", params="name")
        public String searchByName(String name) {
            return "search for name";
        }


        /**
        * Search for the customer by id (can be partial)
        * @param name
        * @return
        */
        @GetMapping(value="search", params="id")
        public String searchById(String id) {
            return "search for id";
        }

        /**
        * search for the customer from the shop id where he is registered
        * @param name
        * @return
        */
        @GetMapping(value="search", params="shopId")
        public String searchByShopID(String shopId) {
            return "search for shop";
        }

    }

All works fine except for a problem:

The problem is that if the application recive a request with multiple query params like this:

http://localhost:8080/v1/customers/search?name=bob&shopId=897a

Spring throw an exception of "Ambiguous Mapping" and return an HTTP 500 status code

How can i handle it? It's possible to handle the case returning an HTTP 400 (and a custom message)? Maybe with something like a "Default mapping".

You can use https://docs.spring.io/spring/docs/5.0.8.RELEASE/javadoc-api/org/springframework/web/bind/annotation/RequestMapping.html#params-- parameter to filter by HTTP parameters. In your case it would be something like:

 @GetMapping(value="search",params = "name")
        public String searchByName(@RequestParam("name") String name) {
            return "search for name";
        }

 @GetMapping(value="search",params = "shopId")
    public String searchByShopID(@RequestParam("shopId") String shopId) {
        return "search for shop";
    }

Thank to @GauravRai1512 i read another time the Spring's documentation, and i noticed that with "params" i can filter for "absent" paramenters too! (i didn't notice at first time) this way params="!myParam"

So i tried to do it this way an it works:

(Let me know your opionion :) )

@RestController()
@RequestMapping("v1/customers")
public class ExampleController {

    /**
    * Search for customer's name (can be partial)
    * @param name
    * @return
    */
    @GetMapping(value="search", params={"name", "!id", "!shopId"})
    public String searchByName(String name) {
        return "search for name";
    }


    /**
    * Search for the customer by id (can be partial)
    * @param name
    * @return
    */
    @GetMapping(value="search",  params={"!name", "id", "!shopId"})
    public String searchById(String id) {
        return "search for id";
    }

    /**
    * search for the customer from the shop id where he is registered
    * @param name
    * @return
    */
    @GetMapping(value="search", params={"!name", "!id", "shopId"})
    public String searchByShopID(String shopId) {
        return "search for shop";
    }

    /**
    * Handle invalid reqest
    * @param name
    * @return
    */
    @GetMapping(value="search")
    public String searchByShopID() {
        return "Invalid!";
    }

} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM