ResponseEntity doesn't retrieve Integer - spring

Want to return simple Integer in ResponseEntity:
#PreAuthorize("hasAnyAuthority('WORKER')")
#RequestMapping(value = "/countFiles", method = RequestMethod.GET)
#ResponseBody
public ResponseEntity<Integer> countFiles(HttpServletRequest request){
Integer count = fileService.countFiles(request);
if(count == null){
return new ResponseEntity<Integer>(HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<Integer>(count, HttpStatus.OK);
}
When I do it, at front end site I got without filed named 'count':
Before you answer:
At front end site everything works fine
The bug is at backend site

If you want a field named "count", you need to include the field name in an object or map result.
#PreAuthorize("hasAnyAuthority('WORKER')")
#RequestMapping(value = "/countFiles", method = RequestMethod.GET)
public ResponseEntity<Integer> countFiles(HttpServletRequest request)
{
Integer count = fileService.countFiles(request);
if (count == null) {
return ResponseEntity.badRequest().build();
}
return ResponseEntity.ok(Collections.singletonMap("count", count));
}
FYI, it may be easier to use the static ResponseEntity.* methods to create new ResponseEntity instances. Also, you don't need #ResponseBody if the return value is ResponseEntity.

Related

spring CRUD DELETE action that return viewmodel or empty body

I want to write a DELETE action that return a no content body if no id error exist. If id not exist I want to redirect to the coresponding GET view.
Controller code:
#RequestMapping(value = "/todo/delete/{id}", method = RequestMethod.GET)
public String getDeleteTodo(Model model, #PathVariable("id") String id)
{
Optional<Todo> todo = todoRepository.findById(Long.decode(id));
if (todo.isEmpty()) {
model.addAttribute("msginfo", "ctl-todo.delete.msginfo.id-not-exist");
model.addAttribute("requestedId", id);
}
else {
model.addAttribute("todo", todo.get());
}
return "v-todo-delete";
}
#RequestMapping(value = "/todo/delete/{id}", method = RequestMethod.DELETE)
public String deleteTodo(#PathVariable String id, RedirectAttributes redirAttrs)
{
boolean exists = todoRepository.existsById(Long.decode(id));
if (exists) {
todoRepository.deleteById(Long.decode(id));
return ""; //here I want to return a no-content body response
}
else {
redirAttrs.addFlashAttribute("msginfo", "ctl-todo.delete.msginfo.id-not-exist");
redirAttrs.addFlashAttribute("requestedId", id);
return "redirect:/todo/delete" + id;
}
}
More informations about the view:
The GET view is juste a view that display the todo entity corresponding to the id. The deletion is make with a button using ajax to call the DELETE method. Then response is return as 204 with no content into the body, i redirect the user with javascript to the main page... If an id not exist in the DELETE method, I want to redirect to the GET method to show an error message.
If someone have an idea to do this.
Thanks in advance.
Try using return type as ResponseEntity with whatever response body along with a response status. Please refer below code changes:
#RequestMapping(value = "/todo/delete/{id}", method = RequestMethod.DELETE)
public ResponseEntity deleteTodo(#PathVariable String id, RedirectAttributes redirAttrs)
{
boolean exists = todoRepository.existsById(Long.decode(id));
if (exists) {
todoRepository.deleteById(Long.decode(id));
return new ResponseEntity(HttpStatus.NO_CONTENT); //This will return No Content status
}
else {
redirAttrs.addFlashAttribute("msginfo", "ctl-todo.delete.msginfo.id-not-exist");
redirAttrs.addFlashAttribute("requestedId", id);
return new ResponseEntity( "redirect:/todo/delete" + id, HttpStatus.OK);
}
}
Final anwser for me:
#RequestMapping(value = "/todo/delete/{id}", method = RequestMethod.DELETE)
public ResponseEntity<?> deleteTodo(#PathVariable String id, RedirectAttributes redirAttrs)
{
boolean exists = todoRepository.existsById(Long.decode(id));
if (exists) {
todoRepository.deleteById(Long.decode(id));
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
else {
redirAttrs.addFlashAttribute("msginfo", "ctl-todo.delete.msginfo.id-not-exist");
redirAttrs.addFlashAttribute("requestedId", id);
/* I use CONFLICT here to explain that the entity was possibly deleted
by another user between the moment the user give the view containing
the DELETE ajax link and the moment he click on it. */
return new ResponseEntity<String>( "redirect:/todo/delete" + id, HttpStatus.CONFLICT);
}
}
Thank you Mandar Dharurkar & Jeethesh Kotian for your help ;)

#JsonGetter doesn't work

I want to make this method return {"valid":true/false}
#ResponseBody
#RequestMapping(value = "/checkUser", method = RequestMethod.POST)
Boolean checkUsersAvailable(#RequestParam("username") String username) {
return contentService.getUser(username) == null;
}
I add these annotations:
#JsonGetter("valid")
#JsonProperty("valid")
But it's still not working.
You can't return a primitive type and get JSON object as a response.
You can use a wrapper or something like that:
#ResponseBody
#RequestMapping(value = "/checkUser", method = RequestMethod.POST)
Map<String, Boolean> checkUsersAvailable(#RequestParam("username") String username) {
boolean result = contentService.getUser(username) == null;
return Collections.singletonMap("success", result);
}

how to check if a request param/query param is passed in the request in Spring MVC app?

I have two different requests to handle
localhost:8080/myapp/status
localhost:8080/myapp/status?v
Please note that in the second request, just a request param is passed. No value is required to be set for it. That is the requirement.
How will I handle this in my controller?
#RequestMapping(value = "/status", method = RequestMethod.GET)
#ResponseBody
public void status(
#RequestParam(value = "v", required = "false") final String verbose) {
//check if v is in query params
...logic
//else
..logic
}
You could use HttpServlerRequest.getParameterMap() like this:
#RequestMapping(value = "/status", method = RequestMethod.GET)
#ResponseBody
public void status(HttpServletRequest request) {
boolean verbose = request.getParameterMap().containsKey("v");
if (verbose) {
...
} else {
...
}
}

how to return not found status from spring controller

I have following spring controller code and want to return not found status if user is not found in database, how to do it?
#Controller
public class UserController {
#RequestMapping(value = "/user?${id}", method = RequestMethod.GET)
public #ResponseBody User getUser(#PathVariable Long id) {
....
}
}
JDK8 approach:
#RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public ResponseEntity<User> getUser(#PathVariable Long id) {
return Optional
.ofNullable( userRepository.findOne(id) )
.map( user -> ResponseEntity.ok().body(user) ) //200 OK
.orElseGet( () -> ResponseEntity.notFound().build() ); //404 Not found
}
Change your handler method to have a return type of ResponseEntity. You can then return appropriately
#RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public ResponseEntity<User> getUser(#PathVariable Long id) {
User user = ...;
if (user != null) {
return new ResponseEntity<User>(user, HttpStatus.OK);
}
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Spring will use the same HttpMessageConverter objects to convert the User object as it does with #ResponseBody, except now you have more control over the status code and headers you want to return in the response.
With the latest update you can just use
return ResponseEntity.of(Optional<user>);
The rest is handled by below code
/**
* A shortcut for creating a {#code ResponseEntity} with the given body
* and the {#linkplain HttpStatus#OK OK} status, or an empty body and a
* {#linkplain HttpStatus#NOT_FOUND NOT FOUND} status in case of a
* {#linkplain Optional#empty()} parameter.
* #return the created {#code ResponseEntity}
* #since 5.1
*/
public static <T> ResponseEntity<T> of(Optional<T> body) {
Assert.notNull(body, "Body must not be null");
return body.map(ResponseEntity::ok).orElse(notFound().build());
}
public static ResponseEntity of(Optional body)
A shortcut for creating a ResponseEntity with the given body and the OK status, or an empty body and a NOT FOUND status in case of an Optional.empty() parameter.
#GetMapping(value = "/user/{id}")
public ResponseEntity<User> getUser(#PathVariable final Long id) {
return ResponseEntity.of(userRepository.findOne(id)));
}
public Optional<User> findOne(final Long id) {
MapSqlParameterSource paramSource = new MapSqlParameterSource().addValue("id", id);
try {
return Optional.of(namedParameterJdbcTemplate.queryForObject(SELECT_USER_BY_ID, paramSource, new UserMapper()));
} catch (DataAccessException dae) {
return Optional.empty();
}
}
it could be shorter using Method Reference operator ::
#RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
public ResponseEntity<User> getUser(#PathVariable Long id) {
return Optional.ofNullable(userRepository.findOne(id))
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
Need use ResponseEntity or #ResponseStatus, or with "extends RuntimeException"
#DeleteMapping(value = "")
public ResponseEntity<Employee> deleteEmployeeById(#RequestBody Employee employee) {
Employee tmp = employeeService.deleteEmployeeById(employee);
return new ResponseEntity<>(tmp, Objects.nonNull(tmp) ? HttpStatus.OK : HttpStatus.NOT_FOUND);
}
or
#ResponseStatus(value=HttpStatus.NOT_FOUND, reason="was Not Found")

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.

Resources