I am getting Internal Error when trying to make an ajax POST Call which returns JSON.
The ajax call is made from JS page:
$.post(
'FilterAsJson',
$(formWithReportData).serialize(),
function(data){funtion_body}
);
This is my Spring MVC calling method:
#RequestMapping(value = "/Reporting/FilterAsJson", method = RequestMethod.POST)
public #ResponseBody PagedQueryResult<GetEntitlementOverviewReportResult> filterAsJson(#ModelAttribute GetEntitleReportQuery query, HttpSession session)
{
getEntitlementOverviewFromSession(session).updateFromQuery(query, session);
return queryDispatcher.dispatch(query);
}
The issue comes where I am setting only few fields in this class GetEntitlementOverviewReportResult(17 out of 30). This is a bean class with simple setter getters. If I set all the 30 fields it works fine.
Can you suggest how the JSON response is set so I can rectify this issue.
A 500 error means that your server encountered an error while processing the request. Since you are using AJAX, you do not see the full message from the server.
2 Options:
A - Check the server logs
B - See below:
Best way I know of to check this with an asynchronous call is to press F12 to bring up your developer tools in your web browser.
Then, you click the "Network" tab on the browser tool and you can see all of the requests that your application makes.
Make your request that is giving you a 500 error, then find it in the list of network requests. You should see the 500 error and be able to see the actual output (server response) that will give you an actual message.
#RequestMapping(value = "/Reporting/FilterAsJson", headers = "Accept=application/json", method = RequestMethod.POST)
public #ResponseBody PagedQueryResult<GetEntitlementOverviewReportResult> filterAsJson(#ModelAttribute GetEntitleReportQuery query, HttpSession session) {
getEntitlementOverviewFromSession(session).updateFromQuery(query, session);
return queryDispatcher.dispatch(query);
}
UPDATED
Oh, i see. I didn't understand question properly.
Show us please class GetEntitleReportQuery which propagate #ModelAttribute.
Also check what does method serialize when you filled not all fields. Does it exist?
UPDATED
An idea.
When u filled up not all fields of class, he try to find class with such fields and can't find. So, try to named your class in Controller and add binding result param: filterAsJson(#ModelAttribute("query") GetEntitleReportQuery query, HttpSession session, BindingResult result) also send from JSP with name "query".
Related
I have a web application written on Spring 3.1 (not boot) and running on Tomcat 7.
I have a #Controller implements method PUT on a certain URL.
In some cases When sending a PUT request from Postman, I get a 403 response instead of what is expected.
For example:
Sending the request to a non-implemented URL (on GET to the same URL I get a 404)
Sending an invalid JSON as the request body (Expected 400)
Sending a string instead of a numeric request parameter (Expected 400)
I also implement a filter that excepts all requests and just before the filter exists, I can verify I get the expected status from the rest of the chain.
This is an example of a controller code:
#RequestMapping(value = "/{book}", method = RequestMethod.PUT)
#ResponseStatus(HttpStatus.OK)
#ResponseBody
protected Book put(#PathVariable(value = "bookId") String id, #RequestBody #Valid Book book) {
return book; // just a stub
}
And this is the relevant part in the filter:
filterChain.doFilter(req, res);
// res.getStatus() is the expected status
return; // after this line I move to internal code of Tomcat which I cannot debug, but something happens there.
What do I miss?
Thanks
Check out CORS filter configuration first as Andreas said: https://tomcat.apache.org/tomcat-8.5-doc/config/filter.html
Check out this flowchart also https://tomcat.apache.org/tomcat-8.5-doc/images/cors-flowchart.png
Check out this stackoverflow post finally 403 on JSON PUT request to Tomcat with Spring 3.0.5 and Jackson
Your path variable value is bookId, but your url uses {book}; both should match. Try changing the url to "/{bookId}" or the path variable to #PathVariable(value = "book"). It might be useful to know the URL that you are calling to help analyse the issue.
I've got an ArticleFormModel containing data sent by normal html form which is injected by Spring using #ModelAttribute annotation, i.e.
#RequestMapping(value="edit", method=RequestMethod.POST)
public ModelAndView acceptEdit(#ModelAttribute ArticleFormModel model,
HttpServletRequest request, BindingResult errors)
{
//irrelevant stuff
}
Everything works perfectly fine up to some point. The problem is that the ArticleFormModel contains a double field (protected, set using normal setter). Everything works fine as long as data sent by user is a number. When they type a word, all I get is 400 Bad Request Http Error.
I've already registered a WebDataBinder for this controller
#InitBinder
protected void initBinder(WebDataBinder binder) throws ServletException
{
binder.setValidator(validator);
}
where validator is an instance of a custom class implementing org.springframework.validation.Validator interface
but I don't know what to do next. I'd like to be able to parse the model, get valid HTTP response and display error message in the form. The initBinder() method is called and I can call validator.validate() from it but it doesn't change the error (for that wrong data).
I'm aware that I could use a setter to parse the string, check if it's a number, if not, store that info in a variable, then retrieve that variable during validation, but that seems to be too much work. There has to be an easier way to force a type on the field without getting an error. Also, the issue is in data binding, not validation, so I feel that it should be placed in the respective code layer.
I was also thinking about implementing java.beans.PropertyEditor and calling binder.registerCustomEditor(), but I'm lacking a reliable knowledge source.
Client-side validation (checking if data is number via JavaScript) isn't a possibility.
TL;DR:
How can I force a field to be of specific type for a #ModelAttribute item without getting 400 Bad Request Http Error?
You can use <form:errors> for a binding error.
It looks like this:
Controller:
#RequestMapping(value="edit", method=RequestMethod.POST)
public ModelAndView acceptEdit(#ModelAttribute ArticleFormModel model,
BindingResult errors, HttpServletRequest request)
{
if (errors.hasErrors()) {
// error handling code goes here.
}
...
}
errors parameter is needed to be placed on the right after the model.
See below for details (Example 17.1):
http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-methods
jsp:
<form:form modelAttribute="articleFormModel" ... >
...
<form:errors path="price" />
</form:form>
message properties file:
typeMismatch.articleFormModel.price=customized error message
I am using Spring MVC 2.5. I have get and post methods for all the pages I have.
#RequestMapping(value = "/offer", method = RequestMethod.GET)
public ModelAndView getOffer(ModelMap model, HttpSession session) {
//code
return new ModelAndView(OFFER_SETTING_PAGE, model);
}
#RequestMapping(value = "/offer", method = RequestMethod.POST)
public ModelAndView postOffer(ModelMap model, #ModelAttribute("investorsEligiblitySetting")
//code
return new ModelAndView("redirect:/servlets/ProcessAction/privateplacement/createoffer/additionalinformation");
}
After passing the post method and displaying the next jsp file, when I try to hit the back button , instead of displaying the previous data from the cache (which is what I am looking for) it gets in to the get method of the specified url and causes some problems.
How can I make my application to look for cache first instead of getting in to a get method?
This is an old question, but I found this post that gives some ideas as to how to prevent the browser from resubmitting on the back button. You could also set something in your form when you handle the POST that the GET handler can look at to see if the POST already ran.
I have ajax requests that come into my controller and my validation is working great. In the controller I call a failure jsp page if there is a failure. The only problem is that I have no idea how I can output the errors to the user on the failure.jsp page. I don't have access to the form tags of spring obviously. What should you do in this scenario?
Edit: All I really want to know is how I can access the binding errors on a JSP page when I'm using an AbstractCommandController.
What I've done in the past is use HTTP headers to send back messages to the AJAX requester (the XMLHTTPRequest object). You will not get a full binding and validation support this way, but it's a simple way to pass messages.
Another option that will give you the full power of Spring binding and validation is as follows. I'm assuming you're submitting a form via AJAX. You could do the standard spring binding and validation, and in the case of an error, send back and replace the form with the exception messages next to the problem input. This way you can leverage the full power of Spring binding and validation while getting the AJAX goodness that you want. This would require you to separate your form into a separate JSP page, so you could just return that form on AJAX submission and error.
In response the comment
My issue is just how to access the
BindingErrors from a JSP if I'm using
an AbstractCommandController. Ajax
isn't really that important in the
equation. I just didn't want to use a
formController because it didn't make
sense.
I think you can simply set a variable in your model like this:
ModelAndView.addObject(this.getCommandName(), errors)
This would be done in AbstractCommandController's
protected abstract ModelAndView handle(
HttpServletRequest request,
HttpServletResponse response,
Object command,
BindException errors)
throws Exception
method. Be sure the name of the model attribute is the name of your command (set in the setCommandName method).
This is untested and from memory.
You can check the BindException object for errors (and also catch and handle exceptions), and return information about them in your Ajax response. If you're using JSON, you could pair a list of error information with an "errors" key. The front-end would then need to check for and display these errors.
I have a Spring Annonted Controller that is used to capture the information from a form and get a list of search results from the database.
Here is the definition of the method
#RequestMapping(method = RequestMethod.POST, params = {SUBMIT_BTN })
public ModelAndView processForm(#ModelAttribute(COMMAND_NAME){
// 1. Load search results using search parameters from form (Contained in a collection of some sort)
// 2. Create the ModelAndView
// 3. Redirect with RequestView or redirect: to generate a GET.
}
I think I need to redirect with redirect: since i have a list of items in a collection store in the session. Cannot add that as a url request param.
Basically I'm trying to prevent problems whith the back button where it says that the page is expired. I want to implement the PRG pattern in strings.
I'm having a hard time wrapping my head around converting the POST into a GET. Can I just redirect or do I need two methods? Thanks for any help you can provide.
The standard pattern is to have a controller method to handle the GET,and which shows the form (or whatever) to the user, and one to handle the POST, which is the form submission. The POST method sends a redirect after it has finished processing the submission, which comes back in to the GET method.
#RequestMapping(value="/myapp", method=GET)
public String showForm(#ModelAttribute(COMMAND_NAME){
return "form.jsp";
}
#RequestMapping(value="/myapp", method=POST)
public String processForm(#ModelAttribute(COMMAND_NAME){
// do stuff to process for submission
return "redirect:/myapp";
}
Returning a view name with the "redirect:" prefix forces Spring to send an HTTP direct rather than an internal request forward.
This is the same pattern that Spring 2.0 implemented with SimpleFormController, but the new way is far more transparent.