Getting HttpServerErrorException: 500 null when using #PathVariable - spring

I am not getting this. I have a #RestController which is supposed to handle requests like /foo?latitude=15.12345. Of course there should be more parameters, but it's not even working for one.
This is the controller:
#RestController
public class GooglePlaceController {
private final static Logger LOGGER = LogManager.getLogger(GooglePlaceController.class);
#Autowired
private GooglePlaceService googlePlaceService;
#RequestMapping(value = "/foo", method = RequestMethod.GET)
public List<GooglePlaceEntity> doNearbySearch(#PathVariable Float latitude) {
LOGGER.trace("Searching for places nearby.");
return null;
}
}
and this is the request I am building:
public ResponseEntity<List<PlaceDto>> nearbySearch(Float lat, Float lng, Integer radius, Boolean googleSearch) {
String href = UriComponentsBuilder.fromHttpUrl("http://localhost:8081/foo")
.queryParam("latitude", lat)
.build().encode().toString();
ResponseEntity<Object> forEntity = this.oauthRestTemplate.getForEntity(href, null, Object.class);
return null;
}
However, I am getting this exception below, unless I remove #PathVariable Float latitude in which case the request gets handled correctly.
org.springframework.web.client.HttpServerErrorException: 500 null
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:97)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:79)
at org.springframework.security.oauth2.client.http.OAuth2ErrorHandler.handleError(OAuth2ErrorHandler.java:84)
at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:777)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:730)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.doExecute(OAuth2RestTemplate.java:128)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:686)
at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:361)
at mz.api.client.Client.nearbySearch(Client.java:191)
But here is the thing:
In another controller I am having this:
#RequestMapping(value = "/groups/{groupId}/places", method = RequestMethod.GET)
public List<PlaceEntity> getGooglePlaces(#PathVariable Long groupId) {
return this.userGroupService.getPlaces(groupId);
}
#RequestMapping(value = "/groups/{groupId}/google-places", method = RequestMethod.POST)
public void addGooglePlace(#PathVariable Long groupId, #RequestParam String googlePlaceId) {
this.userGroupService.addGooglePlace(groupId, googlePlaceId);
}
and those requests are working without any problems.

#PathVariable is for parameters which are part of the URL like: /groups/{groupId}/google-places.
If parameter is after the ? you should use #RequestParam annotation.
#RequestMapping(value = "/foo", method = RequestMethod.GET)
public List<GooglePlaceEntity> doNearbySearch(#RequestParam Float latitude) {
LOGGER.trace("Searching for places nearby.");
return null;
}

Related

MockMVC #PathVariable not work when using String

Mockmvc test not work when Pathvariable is a String but work on int.
Here is my code:
#Controller
#RequestMapping("/etablissement/{typeEtablissement}")
public class EtablissementController{
#RequestMapping(method = RequestMethod.GET)
public String accueil(#PathVariable("typeEtablissement") String typeEtablissement) {
return "/test";
}
}
// somewhere in my test
mockMvc.perform(get("/etablissement/{typeEtablissement}", "test")).andExpect(status().isOk()); // Error 400
But, if I use int instead of String it works
#RequestMapping(method = RequestMethod.GET)
public String accueil(#PathVariable("typeEtablissement") int typeEtablissement) {
return "/test";
}
// somewhere in my test
mockMvc.perform(get("/etablissement/{typeEtablissement}", 123)).andExpect(status().isOk()); // Works
Using Object also work
public String accueil(#PathVariable("typeEtablissement") Object typeEtablissement) {}
Thanks for your help !
Here is an example of a GetMapping who should help you :
#GetMapping("/{typeEtablissement}/{something2}/{something3}")
public List<Object> extract(
#PathVariable String typeEtablissement,
#PathVariable String something2,
#PathVariable String something3) {
List<Object> object = objectService.extractDatas(typeEtablissement, something2, something3);
return object;
}
Strange cause it means typeEtablissement is an int. You can also create a new variable after with valueOf:
#GetMapping("/{typeEtablissement}/{something2}/{something3}")
public List<Object> extract(
#PathVariable String typeEtablissement,
#PathVariable String something2,
#PathVariable String something3) {
String typeEtablissementConverted = String.valueOf(typeEtablissement );
List<Object> object = objectService.extractDatas(typeEtablissementConverted, something2, something3);
return object;
}

Can spring map POST parameters by a way other than #RequestBody

I am using #RestControllers with an application where all requests are POST requests ... As I learned from this post , you can't map individual post parameters to individual method arguments, rather you need to wrap all the parameters in an object and then use this object as a method parameter annotated with #RequestBody thus
#RequestMapping(value="/requestotp",method = RequestMethod.POST)
public String requestOTP( #RequestParam(value="idNumber") String idNumber , #RequestParam(value="applicationId") String applicationId) {
return customerService.requestOTP(idNumber, applicationId);
will not work with a POST request of body {"idNumber":"345","applicationId":"64536"}
MY issue is that I have A LOT of POST requests , each with only one or two parameters, It will be tedious to create all these objects just to receive the requests inside ... so is there any other way similar to the way where get request parameters (URL parameters) are handled ?
Yes there are two ways -
first - the way you are doing just you need to do is append these parameter with url, no need to give them in body.
url will be like - baseurl+/requestotp?idNumber=123&applicationId=123
#RequestMapping(value="/requestotp",method = RequestMethod.POST)
public String requestOTP( #RequestParam(value="idNumber") String idNumber , #RequestParam(value="applicationId") String applicationId) {
return customerService.requestOTP(idNumber, applicationId);
second- you can use map as follows
#RequestMapping(value="/requestotp",method = RequestMethod.POST)
public String requestOTP( #RequestBody Map<String,Object> body) {
return customerService.requestOTP(body.get("idNumber").toString(), body.get("applicationId").toString());
I have change your code please check it
DTO Class
public class DTO1 {
private String idNumber;
private String applicationId;
public String getIdNumber() {
return idNumber;
}
public void setIdNumber(String idNumber) {
this.idNumber = idNumber;
}
public String getApplicationId() {
return applicationId;
}
public void setApplicationId(String applicationId) {
this.applicationId = applicationId;
}
}
Rest Controller Method
#RequestMapping(value="/requestotp",method = RequestMethod.POST)
public String requestOTP( #RequestBody DTO1 dto){
System.out.println(dto.getApplicationId()+" (------) "+dto.getIdNumber());
return "";
}
Request Type -- application/json
{"idNumber":"345","applicationId":"64536"}
OR
#RequestMapping(value="/requestotp",method = RequestMethod.POST)
public String requestOTP( #RequestBody String dto){
System.out.println(dto);
return "";
}

Spring REST Service Controller not being validate by #PathVariable and #Valid

#Controller
#EnableWebMvc
#Validated
public class ChildController extends ParentController<InterfaceController> implements InterfaceController{
#Override
#RequestMapping(value = "/map/{name}", produces = "application/json; charset=UTF-8", method = RequestMethod.GET)
#ResponseStatus( HttpStatus.OK)
#ResponseBody
public List<Friends> getAllFriendsByName(
#Valid
#Size(max = 2, min = 1, message = "name should have between 1 and 10 characters")
#PathVariable("name") String name,
#RequestParam(value="pageSize", required=false) String pageSize,
#RequestParam(value="pageNumber", required=false) String pageNumber,
HttpServletRequest request) throws BasicException {
//Some logic over here;
return results;
}
#ExceptionHandler(value = { ConstraintViolationException.class })
#ResponseStatus(value = HttpStatus.BAD_REQUEST)
public String handleResourceNotFoundException(ConstraintViolationException e) {
Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
StringBuilder strBuilder = new StringBuilder();
for (ConstraintViolation<?> violation : violations ) {
strBuilder.append(violation.getMessage() + "\n");
}
return strBuilder.toString();
}
Hi, I am trying to do pretty basic validation for a spring request parameter but it just doesn't seem to call the Exception handler, could someone point me into the right direction
P.S. I keep getting NoHandlerFoundException
Spring doesn't support #PathVariable to be validated using #Valid. However, you can do custom validation in your handler method or if you insist on using #Valid then write a custom editor, convert your path variable value to an object, use JSR 303 bean validation and then use #Valid on that object. That might actually work.
Edit:
Here's a third approach. You can actually trick spring to treat your path variable as a model attribute and then validate it.
1. Write a custom validator for your path variable
2. Construct a #ModelAttribute for your path variable and then use #Validator (yes not #Valid as it doesn't let you specify a validator) on that model attribute.
#Component
public class NameValidator implements Validator {
#Override
public boolean supports(Class<?> clazz) {
return String.class.equals(clazz);
}
#Override
public void validate(Object target, Errors errors) {
String name = (String) target;
if(!StringUtils.isValidName(name)) {
errors.reject("name.invalid.format");
}
}
}
#RequestMapping(value = "/path/{name}", method = RequestMethod.GET)
public List<Friend> getAllFriendsByName(#ModelAttribute("name") #Validated(NameValidator.class) String name) {
// your code
return friends;
}
#ModelAttribute("name")
private String nameAsModelAttribute(#PathVariable String name) {
return name;
}

Influence on performance of using 'private static final' strings in Spring 3 REST controller

I'm working on REST API based on Spring 3 MVC. In each call I'm adding to JSON response two variables: 'description' and 'result'.
For example:
#RequestMapping(value = "entity.htm", method = RequestMethod.GET)
public ModelAndView get() {
ModelAndView mav = new ModelAndView(JSON_VIEW);
mav.addObject("description", "entity list");
mav.addObject("result", someService.getAll());
return mav;
}
Does it make sense for performance of the app to create a pool of private static final strings and use them every time I need?
I mean like this:
#Controller
public class MyController {
private static final String JSON_VIEW = "jsonView";
private static final String VAR_DESCRIPTION = "description";
private static final String VAR_RESULT = "result";
private static final String DESC_CREATED = "entity created";
private static final String DESC_ENTITY_LIST = "entity list";
private static final String DESC_ACCESS_DENIED = "forbidden";
#RequestMapping(value = "entity.htm", method = RequestMethod.PUT)
public ModelAndView put(HttpServletResponse response) {
ModelAndView mav = new ModelAndView(JSON_VIEW);
if (!entityService.someChecking()) {
mav.addObject(VAR_DESCRIPTION, DESC_ACCESS_DENIED);
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
} else {
mav.addObject(VAR_DESCRIPTION, DESC_CREATED);
mav.addObject(VAR_RESULT, entityService.save(new Entity()));
response.setStatus(HttpServletResponse.SC_CREATED);
}
return mav;
}
#RequestMapping(value = "entity.htm", method = RequestMethod.GET)
public ModelAndView get(HttpServletResponse response) {
ModelAndView mav = new ModelAndView(JSON_VIEW);
if (!entityService.someChecking()) {
mav.addObject(VAR_DESCRIPTION, DESC_ACCESS_DENIED);
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
} else {
mav.addObject(VAR_DESCRIPTION, DESC_ENTITY_LIST);
mav.addObject(VAR_RESULT, entityService.getAll());
}
return mav;
}
// and so on
}
Someone of these statuses I use only once, but DESC_ACCESS_DENIED I use up to 10 times in one REST controller.
Your get is not returning json, it returns a view.
I prefer using an enum instead of static final ints - easier to add functionality later.
Yes, it does make sense. It's a good pratice. It save's you time and effort if you ever need to change this values. It's quite insignificant in terms of memory use or process time, but it's better.
If you intend to use those strings more than once, then it is a good pratice to turn then into static final. But notice your methods aren't returning JSON responses. A JSON response is something like that:
#RequestMapping(value = "/porUF", method = RequestMethod.GET)
public #ResponseBody List<Municipio> municipios(
#RequestParam(value = "uf", required = true) String uf) {
if ( uf.length() != 2) {
return null;
}
return municipioBO.findByUf(uf);
}
The #ResponseBody annotation will transform the List into a JSON object, and the response of a HTTP GET for that is something like that:
[{"codigo":9701,"uf":{"uf":"DF","nome":"DISTRITO FEDERAL"},"nome":"BRASILIA "}]
This is a JSON response.

Expecting a request param with a "XOR" validation

I have a simple request call in a spring mvc controller
#ResponseBody
#RequestMapping(value = "/url", method = RequestMethod.GET)
public SomeDTO getSth(#RequestParam("paramA") Integer paramA, #RequestParam("paramB") Integer paramB) {
// ...
}
and I want to have either the paramA or the paramB otherwise a normal http response as it currently happens if I do not provide both parameters.
I know there is a required parameter available, but I do not see a way to connect both. Any idea?
I can't think of a very good solution, but the straightforward one seems to be normal, isn't it?
#ResponseBody
#RequestMapping(value = "/url", method = RequestMethod.GET)
public String getSth(#RequestParam(value = "paramA", required = false) Integer paramA,
#RequestParam(value = "paramB", required = false) Integer paramB) {
if (paramA == null ^ paramB == null) {
return "body";
} else {
throw new BadRequestException();
}
}
#ResponseStatus(value = HttpStatus.NOT_FOUND)
public static class BadRequestException extends RuntimeException {
private static final long serialVersionUID = 1L;
}

Resources