Spring Ajax controller - Accept submissions without refreshing page - java

I am using Starbox in my Spring page. I want to submit the user rating so I can store it in the database and not have to refresh the page for the user. How can I have a Spring controller that accepts this value and doesn't have to return a new view. I don't necessarily need to return any updated html - if the user clicks the Starbox, that is all that needs to happen.
Similarly, if I have a form with a submit button and want to save the form values on submit but not necessarily send the user to a new page, how can I have a controller do that? I haven't found a great Spring AJAX tutorial - any suggestions would be great.

If you use annotations, perhaps the more elegant way to return no view is to declare a void-returning controller method with #ResponseStatus(HttpStatus.OK) or #ResponseStatus(HttpStatus.NO_CONTENT) annotations.
If you use Controller class, you can simply return null from handleRequest.
To post a from to the controller via AJAX call you can use the appropriate features of your client-side Javascript library (if you have one), for example, post() and serialize() in jQuery.

The AJAX logic on the browser can simply ignore any data the server sends back, it shouldn't matter what it responds with.
But if you really want to make sure no response body gets sent back, then there are things you can do. If using annotated controllers, you can give Spring a hint that you don't want it to generate a response by adding the HttpServletResponse parameter to your #RequestMapping method. You don't have to use the response, but declaring it as a parameter tells Spring "I'm handling the response myself", and nothing will be sent back.
edit: OK, so you're using old Spring 2.0-style controllers. If you read the javadoc on the Controller interface, you'll see it says
#return a ModelAndView to render, or
null if handled directly
So if you don't want to render a view, then just return null from your controller, and no response body will be generated.

Related

How do I configure validation check in Spring MVC with JSP?

I need a quick help regarding validation check in Spring MVC. I have a basic HTML form not the JSTL Tag form. How do I check or implement a straight forward data validation check in Spring MVC? One way in my mind coming right now is to use regex to verify the user name is alphanumeric [a-zA-Z0-9].
But I have seen people use Validator do this job. I want to use Validator as it seems more profession.
Second question,
I'm trying to get a Exception handling working properly but it is not working. I want the absolute basic response to happen, the response throws a HTTP.404 response. My simple method:
#RequestMapping(value="/request/view/{id}",method=RequestMethod.GET)
public String requestSubmit(Model model)
Now with my response String, how can I do it? After search on Stackoverflow. They said to create a generic class such as NotFoundException and extend it RunTimeException. But I still don't know how to I set the response intentionally to be 404 or any other response actually, even Http.BANDWIDTH_EXCEEEDED_RESPONSE
Fist thing you should know: it's better to use POST instead of GET in form submitting. Because when you use GET, all your model properties sent as url parameter and it's not a good practice.
For using validation, you can use #Valid as this:
public String requestSubmit(#Valid Model model)
Then you can use validation annotation like #NotNull, #Size, ... at every property of Model class you want to validate it.
When a user submits your form, if every form attribute has validation problem, spring throws MethodArgumentNotValidException automatically. For getting validation errors, you can use try-catch block in your controller or better way is to have central exception handler with #ControllerAdvice.

Call controller method from JSP button in Spring MVC

I would like to call a controller method using a button on a JSP page in Spring MVC, but I would like it to stay on a current page, don't reload it or anything, simply call a method. I found it difficult. My button is on cars.jsp page. In order to stay on this page I have to do something like this:
#RequestMapping(value="/start")
public String startCheckingStatus(Model model){
System.out.println("start");
model.addAttribute("cars", this.carService.getCars());
return "car\\cars";
}
button:
Start
But this is not a good solution because my page is actually reloaded. Can I just call controller method without any refreshing, redirecting or anything? When I remove return type like so:
#RequestMapping(value="/start")
public void startCheckingStatus(Model model){
System.out.println("start");
}
I got 404.
Add an onclick event on your button and call the following code from your javascript:
$("#yourButtonId").click(function(){
$.ajax({
url : 'start',
method : 'GET',
async : false,
complete : function(data) {
console.log(data.responseText);
}
});
});
If you want to wait for the result of the call then keep async : false otherwise remove it.
As mentioned elsewhere you can achieve this by implementing an Ajax based solution:
https://en.wikipedia.org/wiki/Ajax_(programming)
With Ajax, web applications can send data to and retrieve from a
server asynchronously (in the background) without interfering with the
display and behavior of the existing page. By decoupling the data
interchange layer from the presentation layer, Ajax allows for web
pages, and by extension web applications, to change content
dynamically without the need to reload the entire page.
To achieve this you will need to make changes to both the client and server side parts of your app. When using Spring MVC it is simply a case of adding the #ResponseBody annotation to your controller method which:
can be put on a method and indicates that the return type should be
written straight to the HTTP response body (and not placed in a Model,
or interpreted as a view name).
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-responsebody
Thus, for example, to return a simple String in the Ajax response we can do the following (without the #ResponseBody the framework would try and find a view named 'some status' which is obviously not what we want):
#RequestMapping(value="/start")
#ResponseBody
public String startCheckingStatus(Model model){
return "some status";
}
For the client part you need to add some javascript which will use the XMLHttpRequest Object to retrieve data from your controller.
While there are various frameworks which can simplify this (e.g. JQuery) there are some examples at the below using vanilla javascript and it might be worth looking at some of these first to see what is actually going on:
http://www.w3schools.com/ajax/ajax_examples.asp
If we take this specific example:
http://www.w3schools.com/ajax/tryit.asp?filename=tryajax_callback
and [1] copy the <button/> and <script/> elements to your JSP, [2] change the URL to point to your controller and, [3] create an element <div id="demo"></div> in your JSP then, on clicking the button in your page, this <div/> should be updated to display the String returned by your controller.
As noted this is a lot of code for one action so you can use some JS framework to abstract a lot of it away.

How to generate a GET request from my jsp with a given "value"

I am new to Web Development.
I am trying to develop a web application using Spring 3. I have my "Hello World" code setup done and is working fine.
Now , in my controller I understand that I can create a Handling method with #RequestMapping annotation that would handle HTTP requests.
My question is, how do I generate a new request (say on click of a specific button) from my jsp page,so that it gets handled by a new method specific to that request in my controller.
One way I think I can do is submit a form like:
<form action="hi">
and handle that form with RequestMapping as:
#RequestMapping(value = "/hi", method = RequestMethod.GET)
Is there any other way to map specific requests from jsp page to specific methods in my controller?
The other way is to use links:
Method invocation

Do we need similar #RequestMapping value for both http get and post when we are going to use Spring #ModelAttribute

This is the question which is pressing my head since long time a go.
Suppose I have an index page and there's login form in there.
What I noticed is that for handling #ModelAttribute I should have instantiate the object of my model first in coming Http-GET request:
#RequestMapping(value="/index", method=RequestMethod.GET)
public String renderHomePage(#ModelAttribute("userCredential") UserCredential userCredential, ....){
return "index-page";
}
and then I can fetch my Object when I post the form using HTTP-POST:
#RequestMapping(value="/index", method=RequestMethod.POST)
public String checkCredential(#ModelAttribute("userCredential") UserCredential userCredential, ....){
//do some user credential checking
return "faileOrSuccessPage";
}
and both method must have the same #RequestMapping value for the submission form to work.
now I have several question:
suppose my index page(value="/index", method=RequestMethod.GET) has 10000 hit a day, Does it mean that for each coming get request, An object of UserCredential will be created? (I want to know about object life cycle)
Is there any methodology for us to bind a #ModelAttribute object with the second method (checkCredential) only (just when we want to submit a form)?
If in my case I just have to use #RequestParam to fetch my input values, how I can validate the #RequestParam without using BindingResult and return them back to the view for show?
Regarding your questions:
.1. suppose my index page(value="/index", method=RequestMethod.GET) has 10000 hit a day, Does it mean that for each coming get request, An object of UserCredential will be created? (I want to know about object life cycle)
Yes, but it is tied to the http request scope and the object will be eligible for garbage collection as soon as your page is rendered. 10000 is a fairly small number for the JVM to handle.
.2. Is there any methodology for us to bind a #ModelAttribute object with the second method (checkCredential) only (just when we want to submit a form)?
Depends on your flow - I am assuming you are using a spring form tag to show validation errors back to the user if the user or password don't conform to certain standards you have, if that is the case you will need to set the #ModelAttribute to populate your domain object at the point of redirection back to your index page.
If on the other hand you don't intend to show feedback to your user with the original values that have been set by the user then you don't to set the ModelAttribute, you can totally ignore it and use normal form html elements instead of spring tag.
.3. If in my case I just have to use #RequestParam to fetch my input values, how I can validate the #RequestParam without using BindingResult and return them back to the view for show?
I wouldn't recommend this, a wrapper type is way better and will be validated with the registered validator and the BindingResult will cleanly have the validation errors that you can directly carry over to the UI. If you absolutely want to validate the #RequestParam on your own, you can call the validator yourself. There are ways to set more model attributes to carry back the validation exceptions and present on the UI.

Ajax Request - Call different method on Spring Controller

I've been having a problem regarding using AJAX with Spring MVC. I have a form which has a lot of fields, and each field retrieves data depending on the associated button that was clicked.
So, each one of my buttons needs to call an AJAX request. Each response will be displayed on the associated field.
I wonder if it is possible to call a different method in my Spring controller once I clicked on a different button?
In other words, I want to make multiple ajax requests to the same controller where each request will call a different method in that same controller.
See this example :
// when get account detail is clicked it will call this method
#RequestMapping(method=RequestMethod.POST)
public #ResponseBody String getAccountDetails(#RequestParam(value="accountid") String accountid){
return somefunct.getAccountDetails(accountid);
}
// when get account summary is clicked it will call this method
#RequestMapping(method=RequestMethod.POST)
public #ResponseBody String getAccountSummary(#RequestParam(value="accountid") String accountid){
return somefunct.getAccountSummary(accountid);
}
/* when submit button is clicked... Form is submitted for saving*/
#RequestMapping(method=RequestMethod.POST)
public String submitForm(){
// save here
return "myform";
};*/
Currently, I can have only one AJAX request. How can I modify this code so that I can have different functionality for different AJAX requests?
First, consider that when you retrieve data from a server without modifying the state of that server, the commonly accepted standard is to use the HTTP GET method, not POST. Thus, for your first two methods, you are misusing the HTTP Methods.
Second, you can map individual URL patterns to a specific method using the value property of the RequestMapping annotation.
Third, the most RESTful way to represent your account details resource is to use the PathVariable annotation and include your identifying accountid in the actual path:
#RequestMapping(value="/account/{accountid}/details", method = RequestMethod.GET)
public #ResponseBody String getAccountDetails(#PathVariable(value="accountid") String accountid){
return somefunct.getAccountDetails(accountid);
}
Next, you can represent your account summary using a different URL pattern where the URL is built like a tree, where the first two parts of the path are once again "Account" and the accountid:
// when get account summary is clicked it will call this method
#RequestMapping(value="/account/{accountid}/summary", method=RequestMethod.GET)
public #ResponseBody String getAccountSummary(#PathVariable(value="accountid") String accountid){
return somefunct.getAccountSummary(accountid);
}
Now, your submit method, on the other hand, has side effects. This is just a fancy way of saying that the state of your server will be different at the end of this request, and any GET requests made to that resource will be different than they were prior to the change. The appropriate HTTP method to use when modifying a resource or adding a resource to a collection is the HTTP POST Method. When replacing a collection, the HTTP Method PUT is the generally accepted method of choice.
Another differentiating factor between PUT and POST is that PUT is idempotent, meaning that the same request repeated over and over again doesn't change the state on the server. If hitting the same request multiple times creates more records, then use POST.
Lastly, this request can be mapped to a URL as well. In the example below, I've assumed you are creating a new Account record and inserting a new record in the collection of accounts in the database. Thus, I've used POST. I also modified your parameter list to use PathVariable to take the accountid from the URL path, and I added a RequestBody annotation so that you can send an object in the body of the request, which could be deserialized into a Java object:
/* when submit button is clicked... Form is submitted for saving*/
#RequestMapping(value="/account/{accountid}", method=RequestMethod.POST)
public String submitForm(#PathVariable String accountid, #RequestBody Account account){
// save here
return "myform";
}
For more information on Spring MVC, please check out the Spring documentation on Spring MVC.

Categories

Resources