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".
java spring rest
|
show 4 more comments
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".
java spring rest
Is this something you could do on the front end? As in prevent more than one parameter from being entered by the user?
– Katie.Sun
Nov 19 '18 at 15:40
If you can't take care of it from the front end, you could use@Nullable
to make an endpoint that accepts up to all 3 params and returns a 400 error if it has more than one
– Katie.Sun
Nov 19 '18 at 15:57
I think this is not possible. You may have to create a single method and apply some logic upon some request made.
– Bunyamin Coskuner
Nov 19 '18 at 15:59
@Katie.Sun, I had already managed it on the frontend, but i was looking for a way on the backend too to prevent frontend changes or other future clients to introduce error on the logic.
– pippo paperino
Nov 19 '18 at 16:31
Ok. I think the@Nullable
idea might work, but I can't try it at the moment
– Katie.Sun
Nov 19 '18 at 16:33
|
show 4 more comments
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".
java spring rest
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".
java spring rest
java spring rest
edited Nov 19 '18 at 15:41
asked Nov 19 '18 at 15:35


pippo paperino
185
185
Is this something you could do on the front end? As in prevent more than one parameter from being entered by the user?
– Katie.Sun
Nov 19 '18 at 15:40
If you can't take care of it from the front end, you could use@Nullable
to make an endpoint that accepts up to all 3 params and returns a 400 error if it has more than one
– Katie.Sun
Nov 19 '18 at 15:57
I think this is not possible. You may have to create a single method and apply some logic upon some request made.
– Bunyamin Coskuner
Nov 19 '18 at 15:59
@Katie.Sun, I had already managed it on the frontend, but i was looking for a way on the backend too to prevent frontend changes or other future clients to introduce error on the logic.
– pippo paperino
Nov 19 '18 at 16:31
Ok. I think the@Nullable
idea might work, but I can't try it at the moment
– Katie.Sun
Nov 19 '18 at 16:33
|
show 4 more comments
Is this something you could do on the front end? As in prevent more than one parameter from being entered by the user?
– Katie.Sun
Nov 19 '18 at 15:40
If you can't take care of it from the front end, you could use@Nullable
to make an endpoint that accepts up to all 3 params and returns a 400 error if it has more than one
– Katie.Sun
Nov 19 '18 at 15:57
I think this is not possible. You may have to create a single method and apply some logic upon some request made.
– Bunyamin Coskuner
Nov 19 '18 at 15:59
@Katie.Sun, I had already managed it on the frontend, but i was looking for a way on the backend too to prevent frontend changes or other future clients to introduce error on the logic.
– pippo paperino
Nov 19 '18 at 16:31
Ok. I think the@Nullable
idea might work, but I can't try it at the moment
– Katie.Sun
Nov 19 '18 at 16:33
Is this something you could do on the front end? As in prevent more than one parameter from being entered by the user?
– Katie.Sun
Nov 19 '18 at 15:40
Is this something you could do on the front end? As in prevent more than one parameter from being entered by the user?
– Katie.Sun
Nov 19 '18 at 15:40
If you can't take care of it from the front end, you could use
@Nullable
to make an endpoint that accepts up to all 3 params and returns a 400 error if it has more than one– Katie.Sun
Nov 19 '18 at 15:57
If you can't take care of it from the front end, you could use
@Nullable
to make an endpoint that accepts up to all 3 params and returns a 400 error if it has more than one– Katie.Sun
Nov 19 '18 at 15:57
I think this is not possible. You may have to create a single method and apply some logic upon some request made.
– Bunyamin Coskuner
Nov 19 '18 at 15:59
I think this is not possible. You may have to create a single method and apply some logic upon some request made.
– Bunyamin Coskuner
Nov 19 '18 at 15:59
@Katie.Sun, I had already managed it on the frontend, but i was looking for a way on the backend too to prevent frontend changes or other future clients to introduce error on the logic.
– pippo paperino
Nov 19 '18 at 16:31
@Katie.Sun, I had already managed it on the frontend, but i was looking for a way on the backend too to prevent frontend changes or other future clients to introduce error on the logic.
– pippo paperino
Nov 19 '18 at 16:31
Ok. I think the
@Nullable
idea might work, but I can't try it at the moment– Katie.Sun
Nov 19 '18 at 16:33
Ok. I think the
@Nullable
idea might work, but I can't try it at the moment– Katie.Sun
Nov 19 '18 at 16:33
|
show 4 more comments
2 Answers
2
active
oldest
votes
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";
}
Hi thank for your suggestion but as i wrote in the question (the code part) I already use the "params" parameter (and it works fine) my problem is to handle requests that do not match with any of allowed cases and return an HTTP status 400 (Bad Request)
– pippo paperino
Nov 19 '18 at 16:53
add a comment |
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!";
}
}
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53377958%2fspring-handle-ambiguous-mapping-with-badrequest%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
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";
}
Hi thank for your suggestion but as i wrote in the question (the code part) I already use the "params" parameter (and it works fine) my problem is to handle requests that do not match with any of allowed cases and return an HTTP status 400 (Bad Request)
– pippo paperino
Nov 19 '18 at 16:53
add a comment |
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";
}
Hi thank for your suggestion but as i wrote in the question (the code part) I already use the "params" parameter (and it works fine) my problem is to handle requests that do not match with any of allowed cases and return an HTTP status 400 (Bad Request)
– pippo paperino
Nov 19 '18 at 16:53
add a comment |
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";
}
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";
}
answered Nov 19 '18 at 16:30
GauravRai1512
58811
58811
Hi thank for your suggestion but as i wrote in the question (the code part) I already use the "params" parameter (and it works fine) my problem is to handle requests that do not match with any of allowed cases and return an HTTP status 400 (Bad Request)
– pippo paperino
Nov 19 '18 at 16:53
add a comment |
Hi thank for your suggestion but as i wrote in the question (the code part) I already use the "params" parameter (and it works fine) my problem is to handle requests that do not match with any of allowed cases and return an HTTP status 400 (Bad Request)
– pippo paperino
Nov 19 '18 at 16:53
Hi thank for your suggestion but as i wrote in the question (the code part) I already use the "params" parameter (and it works fine) my problem is to handle requests that do not match with any of allowed cases and return an HTTP status 400 (Bad Request)
– pippo paperino
Nov 19 '18 at 16:53
Hi thank for your suggestion but as i wrote in the question (the code part) I already use the "params" parameter (and it works fine) my problem is to handle requests that do not match with any of allowed cases and return an HTTP status 400 (Bad Request)
– pippo paperino
Nov 19 '18 at 16:53
add a comment |
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!";
}
}
add a comment |
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!";
}
}
add a comment |
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!";
}
}
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!";
}
}
answered Nov 19 '18 at 17:30


pippo paperino
185
185
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53377958%2fspring-handle-ambiguous-mapping-with-badrequest%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Is this something you could do on the front end? As in prevent more than one parameter from being entered by the user?
– Katie.Sun
Nov 19 '18 at 15:40
If you can't take care of it from the front end, you could use
@Nullable
to make an endpoint that accepts up to all 3 params and returns a 400 error if it has more than one– Katie.Sun
Nov 19 '18 at 15:57
I think this is not possible. You may have to create a single method and apply some logic upon some request made.
– Bunyamin Coskuner
Nov 19 '18 at 15:59
@Katie.Sun, I had already managed it on the frontend, but i was looking for a way on the backend too to prevent frontend changes or other future clients to introduce error on the logic.
– pippo paperino
Nov 19 '18 at 16:31
Ok. I think the
@Nullable
idea might work, but I can't try it at the moment– Katie.Sun
Nov 19 '18 at 16:33