spring mvc - How to retrieve values from controller without creating a view - java

I have a problem here and I need your help.
Im trying to retrieve an integer value from the controller to the jsp.
In my jsp I have an ajax call:
$("#hdnCustomerSize").load(contextPath+"/customer/size", function() {
// some codes
});
In my controller:
#RequestMapping(method = RequestMethod.GET, value="/size")
public void getCustomerSize(Model model) {
model.addAttribute("customerSize", customerService.getCustomers().size());
}
My problem is Im getting an exception:
javax.servlet.ServletException: Could not resolve view with name 'customer/size' in servlet with name 'tombuyandsell'.
I know Im getting this exception because I intentionally did not map this in views.properties. The reason is I only want to get the integer value size and not a whole jsp page. Please help.

Use the #ResponseBody annotation and return the int as a String. #ResponseBody will cause the return type to be written to the response HTTP body.
#RequestMapping(method = RequestMethod.GET, value="/size")
#ResponseBody
public String getGroupChatSize(Model model) {
return Integer.toString(customerService.getCustomers().size());
}
Documentation

Try with #ResponseBody:
#ResponseBody
#RequestMapping(method = RequestMethod.GET, value="/size")
public int getGroupChatSize() {
return customerService.getCustomers().size();
}

Related

How to return json/xml from Spring Boot #Controller?

I'm trying to return JSON/XML from a function of my Controller. First I was using #RestController and it worked good, but now I need to change to #Controller, because I will use also some other functions and pass there some objects for my view.
#Controller
#RequestMapping("/game")
public class ViewController {
#RequestMapping(value = "/statistic", method = RequestMethod.GET,
produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public GamerData[] getStatistic() {
RestTemplate restTemplate = new RestTemplate();
try {
String uri_get_statistic = "http://localhost:8081/statistic/";
ResponseEntity<GamerData[]> response = restTemplate.getForEntity(uri_get_statistic, GamerData[].class);
GamerData[] statisticData = response.getBody();
return statisticData;
} catch(Exception e) {
e.printStackTrace();
return null;
}
}
}
After I've changed to Controller I get error 404 not found. With RestController I've got json. (GamerData is just a class with 2 simple fields (int and String), setters, getters, consructor).
UPDATE:
I've added #ResponseBody to my function, but now I have Internal Server error
Resolved [org.springframework.http.converter.HttpMessageNotWritableException: No converter for [class [Lgame.mainservice.mvc.GamerData;] with preset Content-Type 'null']
try to add #ResponseBody like
public #ResponseBody GamerData[] getStatistic....
#RequestMapping(value = "/statistic", method = RequestMethod.GET,
produces = {MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
#ResponseBody // add this one
public GamerData[] getStatistic() {}
Thank you all for answers, I've added #ResponceBody annotation to my function and removed "produces" part from #RequestMapping annotation and my function works great:
#RequestMapping(value = "/statistic", method = RequestMethod.GET)
#ResponseBody
public GamerData[] getStatistic() {
//function code
}

AWS lambda/api gateway does not redirect

I have a very simple spring route that im attempting to run on aws lambda. The route simply returns the text/string "redirect:/upload" instead of redirecting. I have the html file in the /resources/templates folder.
#RequestMapping(path = "/test", method = RequestMethod.POST)
public String UploadPage2() {
return "redirect:/upload";
}
I think the problem is from the return type of method: String.
You can do:
public RedirectView UploadPage2() {
return new RedirectView("/upload");
}
Second question
To return an view on path /test with GET request, you need another method with same path but different method
#RequestMapping(path = "/test", method = RequestMethod.GET)
public ModelAndView testGet(){
return new ModelAndView("uploadview");
}

Spring REST service to consume and produce both HTML form POST and AJAX/JSON in a single method

I'm trying to teach myself Spring by creating a very simple web application. I have a class to create "Note" objects:
#Controller
#RequestMapping(value = "/notes")
public class NoteRestController {
#Autowired
private MappingJackson2JsonView jsonView;
[...]
#ResponseStatus(HttpStatus.CREATED)
#RequestMapping(method = RequestMethod.POST, consumes = {
MediaType.APPLICATION_JSON_VALUE,
MediaType.APPLICATION_FORM_URLENCODED_VALUE })
public ModelAndView create(final Model model,
#Valid #ModelAttribute final Note note, final BindingResult result) {
ModelAndView mav;
// how can I test the request source?
if (<requesting from HTML FORM>) {
// return jsonView
mav = new ModelAndView(jsonView);
} else {
// return JSP view
mav = new ModelAndView("note", "model", model);
}
model.addAttribute("note", note);
if (result.hasErrors()) {
model.addAttribute("errors", result.getAllErrors());
// on error, redirect back to note page with form
// return new ModelAndView("note/note", "model", model);
return mav;
}
note.setId(daoService.createNote(note));
return mav;
}
}
I would like to be able to use a single method (like the above) to handle requests from both an AJAX post AND a HTML form post. If triggered by AJAX I would like to return JSON (with validation errors if present), and if it is triggered by a HTML form, I would like to return to the JSP using the form taglib
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
and show validation errors next to input fields using e.g.
<form:errors path="title" cssClass="errorMessage"></form:errors>
Is this possible, or should I be creating two controllers; one for the REST/JSON, and one for HTML/form? Maybe there is something I can pass into the method that can be interrogated to determibne the request source, but I can't see it right now.
What would be the "best practice" in this case?
EDIT 1:
Trying answer from #ring-bearer first as it allows for the same URL pattern, but having issues.
Using methods:
// used to handle JSON/XML
#RequestMapping(method = RequestMethod.POST, produces = {
MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
public #ResponseBody Note create(
#Valid #ModelAttribute final Note note, final BindingResult result) {
[...]
}
// used to handle form view
#RequestMapping(method = RequestMethod.POST)
public ModelAndView createForView(final Model model,
#Valid #ModelAttribute final Note note, final BindingResult result) {
[...]
}
Interestingly, the HTML form submission, still gets handled by create() and not createForView(). After looking at the form submission request headers, I see that this Accept header:
text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
By adding produces = "text/html" to #RequestMapping on createForView(), all 3 scenarios work (form, AJAX/JSON, AJAX/XML).
Is this normal, or am I still missing something?
This can be achieved using "content negotiation". Spring MVC needs to be enabled for content negotiation using a "contentNegotiationManager" definition. It can be set up using Java or XML configuration. The configuration will centrally manage media type mappings(json, xml etc). Once that is set up, a controller class can be built to cater to both JSON and View(HTML). Below is a generic example(uncompiled), it should be easy to refactor your class to similar structure to avoid violation of DRY.
#Controller
class ReportController{
//1- Method for JSON/marshalling types(XML)
#RequestMapping(value="/report", produces={"application/xml", "application/json"})
#ResponseStatus(HttpStatus.OK)
public #ResponseBody List<ReportPara> generateReport(Principal principal) {
return reportService.generateReport(principal);
}
//2- For View technologies ( Eg:JSP HTML)
#RequestMapping("/report")
public String generateReportForView(Model model, Principal principal) {
model.addAttribute( generateReport(principal) );
// Return the view to use for rendering the response
return ¨reports/main¨;
}
}
Which of the two #RequestMapping methods will execute? It is determined by content negotiation definition. Eg: URLs such as report.xml or report.json map to the first method, any other URLs ending in report.anything map to the second.
The following will be easier to maintain:
#Controller
class NoteController {
#Autowired NoteService service;
#RequestMapping(method = RequestMethod.POST, value = "/note")
public ModelAndView createFromForm(#ModelAttribute #Valid Note note, BindingResult result) {
return new ModelAndView("note", create(note));
}
#RequestMapping(method = RequestMethod.POST, value = "/api/note")
#ResponseBody
public Note createFromApi(#RequestBody Note note) {
return create(note);
}
private Note create(Note note) {
return service.create(note);
}
}

#ResponseBody annotated method do not return Model as JSON Spring 3.2.10

My method is annotated as
#RequestMapping(value = "/keepAlive", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE,consumes = MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody ModelMap test(HttpServletRequest req, final ModelMap model) {
model.addAttribute("keepAlive", true);
return model;
}
when I call is using ajax using JQuery
it returns 500 server error and at server log I can see that it is looking for KeepAlive.jsp, I am using spring 3.2.10 and have jackson 2 at class path. When I debugged source code request is passed to ModelAndViewMethodReturnValueHandler rather than RequestResponseBodyMethodProcessor , It seems Model and view handler is registered before req res handler. How to solve this. Same code worked for spring 3.1.2.
Thanks

.getJSON 404 Error with ModelAndView

I am trying to retrieve some JSON data in my javascript by making a call to the controller. The controller returns a MappingJacksonJsonView ModelandView, but the .getJSON is always reporting a 404 at .../handhygiene.json.
Is there a problem with the way I am returning the ModelandView from the controller?
Controller
#RequestMapping(value = "/{room}/handhygiene.json", method = RequestMethod.GET)
public ModelAndView getHandHygienePageAsync(
#PathVariable(value = "room") String roomCode) {
ModelAndView mav = new ModelAndView(new MappingJacksonJsonView());
mav.getModelMap().addAttribute(blahblahblah); //adds some attributes
...
return mav;
}
Javascript
var currentURL = window.location;
$.getJSON(currentURL + ".json",
function(data) {
... //does stuff with data
}
If you're trying to get only an JSON object from Ajax request, you need to add #ResponseBody to your method, and make you result object as return from your method.
The #ResponseBody tells to Spring that he need to serialize your object to return to the client as content-type. By default, Spring uses JSON Serialization. ModelAndView will try to return an .JSP page. Maybe you don't have this jsp page on your resources so, the server return 404 error.
I Think this code should work for you:
#RequestMapping(value = "/{room}/handhygiene.json", method = RequestMethod.GET)
public #ResponseBody Room getHandHygienePageAsync(#PathVariable(value = "room") String roomCode) {
Room room = myService.findRoomByRoomCode(roomCode);
return room;
}
I'm assuming you're using the Room as your result object, but it may be another object or ArrayList, for example.
You cant take a look here for Spring example, and here for example and configuration.

Categories