I have controller method that handles “Download ” button click on my page. This method makes call to our Service, where query is made.
My problem is that it takes around 20-30 sec for Service to execute the query before it will be returned to controller and put to outputStream to return back to user. So user is blocked and cannot do anything for this 30 sec until actual download start.
How can I resolve this issue? I don’t want my user wait. I am new to spring mvc and async programming. So please, explain me how can I do it asynchronously ?
#RequestMapping(value = "/download")
public void downloadCSV(#RequestParam(“vendorId”), #RequestParam(“startDateString”),#RequestParam(“startDateString”),
HttpServletResponse response) throws IOException
{
List<Objects> listFromService = getListFromService();
String fileName = vendorId + "_metrics.csv";
response.setHeader("Content-disposition", "attachment;filename="+fileName);
ServletOutputStream outputStream = response.getOutputStream();
listFromService.stream().forEach(item -> {
try {
processListItem(item, outputStream);
} catch (IOException e) {
e.printStackTrace();
}
});
outputStream.flush();
}
You could use AJAX call from your view(JSP) to the controller as follows.
JSP Form:
<FORM NAME="form1" METHOD="POST">
<INPUT TYPE="BUTTON" VALUE="Download" ONCLICK="downloadCSV()">
</FORM>
Ajax functions:
<script type="text/javascript">
function downloadCSV() {
console.log("Download called..");
$.ajax({
type : "GET",
url : '${home}/download',
dataType : "json",
crossDomain : true,
success : function(data) {
processResponse(data);
},
error : function(data) {
}
});
}
function processResponse() {
console.log("Your response processing goes here..");
}
</script>
Related
I'm trying to post a JSON Object, with Ajax, to an Rest Spring MVC Controller, but I met some troubles.
Let's present you my code:
Controller
#RequestMapping(value = "/register/checkUsername.html", method = RequestMethod.POST, produces=MediaType.APPLICATION_JSON_VALUE)
public #ResponseBody JsonResponse checkUsername(#RequestBody JsonUsername username) {
String usernameString = username.getUsername();
JsonResponse response = new JsonResponse();
response.setMessage(usernameString + "Available");
return response;
}
Ajax Function
function displayUsernamError(data) {
var json = "<h4>Eroare</h4><pre>"
+ JSON.stringify(data, null, 4) + "</pre>";
$('#usernameError').html(json);
}
function checkUsername(){
var username = document.getElementById("username");
var search = {
"username" : username.value
}
$.ajax({
type : "POST",
contentType : 'application/json; charset=utf-8',
dataType : 'json',
url : "http://localhost:8080/skill-assessment/register/checkUsername.html",
data : JSON.stringify(search),
success : function(result) {
console.log("SUCCESS: ", data);
displayUsernamError(result);
},
error: function(e){
console.log("ERROR: ", e);
displayUsernamError(e);
},
done : function(e) {
console.log("DONE");
}
});
}
And finally the html form:
<form:form modelAttribute="user" method="POST" enctype="utf8">
<tr>
<td><label>Username</label></td>
<td><form:input path="name" id="username" /></td>
<td>
<p id="usernameError">
</p>
</td>
</tr>
<button type="button" onClick="checkUsername()">Register</button>
</form:form>
So, I'm calling the checkUsername method when I press click on the Register button, only for test.
The ajax function is called and this send the JSON to the controller. I used the debug and the controller seems to get the JSON Object.
The problem is with the controller Response, because in the error div from my html page, I get this error:
HTTP Status 406
The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request \"accept\" headers.
Where is the problem? Who can give me an idea?
You need to specify the below code inside of the request mapping annotation
#RequestMapping(value = "/register/checkUsername.html", method = RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE)
you no need to specify the produces attribute because #Responsebody will produce the content based on the request object content type[optional]. if you want other then it then only you have to mention it.
; charset=utf-8 is the default one in Ajax call. you no need mention it separately. try do these changes.
use #ResponseBody need object to json,
seems missing some jar file
(jackson-mapper-asl.jar and jackson-core-asl.jar)
try to import it
First check if your controller is returning a JSON. You can use any REST client and see what is the return header. If not then add the Jackson mapper bean.
Also, try setting the Accept header in the ajax call.
$.ajax({
headers: {
Accept : "application/json",
Content-Type: "application/json"
},
data: "data",
...
})
in .js(java script)
ajax function
var variable="test";
$.ajax({
url: baseUrl + "nameController/test1",
async: false,
data: {val: variable},
dataType: 'html',
success: function (dat) {
console.log(dat);
}
});
you create nameController.java
controller
#RequestMapping(value = "test1", method = RequestMethod.POST)
public #ResponseBody
String checkRoomStatusReservation(#RequestParam(value = "val", required = true) String parse) {
System.out.println("parse"+parse);
//value from parse=test
return parse;
}
you can try this
Hi I'm trying to simply send a string once a button is pressed in my website using ajax to my java code in Play framework. I can't find a simple tutorial which simply explains how to do this. They are all using templates.
Lets say my java method is:
public static Result upload() { }
and my button is calling a javascript method which gets a String from another input when clicked:
<input id="submit" type="submit" onclick="send();">
I didn't test, but something like this should work.
Application controller
public static Result upload() {
JsonNode node = request().body().asJson().get("stringField");
String inputString = node.getTextValue();"
System.out.println(inputString) // prints the string from the form field
return ok();
}
Routes
POST /uploadfoostring controllers.Application.upload()
Template
<input type="text" id="string-field">
<input id="submit" type="submit" onclick="send();">
<script type = "text/javascript" >
$('#submit').click(function(evt) {
var inputString = $('#string-field').val();
var obj = {
stringField: inputString;
};
$.ajax({
url: "#routes.Application.upload()",
data: JSON.stringify(obj),
headers: {
'Content-Type': 'application/json'
},
type: 'POST',
success: function(res) {
if (res) {
console.log("Success!");
} else {
console.log("Failed...");
}
}
});
}
</script>
POST /home/testPost controllers.Application.testPost
//Server Side.
def testPost = Action { request =>
println("testPost Called");
println(request.body.asFormUrlEncoded.get("name").head);
Ok("Succeeded");
}
Client Side:
public static testPost(){
$.ajax({
url:"/dialog/testPost",
type:"POST",
data:{
name:"Varadharajan R"
},
success:function(response){
alert(response);
}
});
}
Am doing the JAVA code found below, to call the servlet doGet() method from JSP page through AJAX call.
Here is my AJAX call..
Am sending the clicked text captured by ng-click of Angular js as a querystring to Servlet's doGet() method .
In my JSP file,
$scope.requestFunc = function (clickData) {
var urlquerystring = clickData;
jQuery.ajax({
type: 'GET',
url: "/Charts/testExecution/"+"?"+ urlquerystring,
dataType: 'html',
success: function(respnsedata)
{
window.location.assign(respnsedata);
}
});
}
In my Servlet's doGet() method,
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.err.println("In TestExecutionESO servlet..");
String teamnametextfield= req.getParameter("teamnametextfield");
System.out.println("Teamname is.."+teamnametextfield);
try {
dcmanager = DataCollectorManager.getInstance();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String selectedteam= req.getQueryString();
String testexeclistofobjectsjson = null;
if(selectedteam!=null)
{
String release=selectedteam.replace("%20"," ").toString();
testexecutionobjlist = dcmanager.getRallyDcMgr().gettestExecutionobjlist(release);
}
Gson gson = new Gson();
testexeclistofobjectsjson = gson.toJson(testexecutionobjlist);
System.out.println(testexecutionobjlist);
System.out.println(testexeclistofobjectsjson);
req.getSession().setAttribute("testexeclistofobjectsjson", testexeclistofobjectsjson);
resp.sendRedirect("TestExecutionESO.jsp");
}
Am getting the querystring perfectly..After the processing, I will do SetAttribute() and redirect to next JSP page..
Redirect is not working..
Here is my error code,
Failed to load resource: net::ERR_TOO_MANY_REDIRECTS..
http://10.112.81.95:9000/Charts/testExecution/TestExecutionESO.jsp.... Failed to load resource: net::ERR_TOO_MANY_REDIRECTS
Please help me resolve the problem..
how to redirect to next JSP page by doing the setAttribute() .??
resp.sendRedirect("TestExecutionESO.jsp");
This is the culprit in your code. when you call sendRedirect(), it will issue a 302 response containing the location-header, URI of the new resource. When the browser sees this header, it will issue a new request for that new URI.
All of this works well for a synchronous request but in case of AJAX calls, we use an XMLHttpRequest, which will not handle redirects so well.
I'd suggest you to use a RequestDispatcher instead to forward to the JSP like this
RequestDispatcher rd = req.getRequestDispatcher("path-to-ur-jsp");
rd.forward(req,res);
I am trying to implement the below scenario in Spring MVC.But I am facing issues and not able to decide about the right Approach.
I am Using jsonRequest/jsonResone(Restful Webservices)
1.I have a SignUP.jsp Form which contains few field which need to be submitted to controller.
<form method="POST" onsubmit="javascript:signupObj.signup()">
<table>
<tr>
<td>Username : </td>
<td><input id="username"/></td>
</tr>
<tr>
<td>Password :</td>
<td><input id="password"/></td>
</tr>
<tr>
<td>
<button type="submit">Submit</button>
</td>
</tr>
</table>
</form>
2.onSubmit of form it will invoke signup javascript function mentioned below
var signupObj = {
showSignup : function() {
//There are Two Ways to Declare Function The Other Way is function showSignup().Checkout the reasons
$.ajax({
type: "GET",
url: "showSignup",
success: function(response) {
$("#signupView").html( response );
}
});
},
signup : function() {
alert("In Signup function");
var input = '{';
input += '"username":"'+$('#username').val()+'",';
input += '"password":"'+$('#password').val()+'"';
input += '}';
alert(input);
$.ajax({
type: "POST",
url : "signup",
contentType: "application/json; charset=utf-8",
data: input,
dataFilter: function (response) {
return response;
},
// crossDomain: true,
async:false,
success: (function(data) {
alert("In ajax Sucess");
alert(data.profileID);
signupObj.redirectview("success",data);
}),
error : function(data,textStatus,error){
alert("In ajax Failure");
alert(error);
signupObj.redirectview("failure",data);
},
dataType: "json"
});
alert("ajax finished");
},
redirectview : function(message,data) {
alert("inside redirect view");
if(message == "success"){
url = "success";
}
else{
url = "error";
}
$.ajax({
type: "POST",
url : "success",
contentType: "application/json; charset=utf-8",
data: data,
async:false,
dataType: "json",
dataFilter: function (response) {
return response;
},
// crossDomain: true,
success: (function(data) {
alert("data");
}),
error : function(data,textStatus,error){
alert("In ajax Failure redirect");
alert(error);
},
});
}
};
3.The Above javascript function does the ajax call to the controller(input is jsonRequest)
#RequestMapping(value="/signup",method=RequestMethod.POST)
#ResponseBody
public ProfileDTO signup(#RequestBody LoginDTO loginDTO) {
ProfileDTO profileDto = new ProfileDTO();
//In case no errors in backend logic
profileDto.setError(null);
profileDto.setProfileID("profileID");
profileDto.setProfileName("profileName");
System.out.println("Submitting SignUP Form Will Return ProfileID");
return profileDto;
}
//Below method is for success view
#RequestMapping(value="/success",method=RequestMethod.POST)
#ResponseBody
public String checkSignup(#RequestBody ProfileDTO profileDto,HttpServletRequest httprequest,HttpServletResponse httpResponse
) {
//model.addAttribute(loginDTO);
System.out.println("In loginSuccess");
return "loginSucess";
}
4.The Controller gives the JSON Response of profileDTO. Now based on the profileDTO.getErrors I have to call either loginSuccess.jsp or loginFailure.jsp
Now My Question is:
1) How I can use jsonResponse in ajax call to redirect to loginSuccess.jsp or loginFailure.jsp and how will pass my profileDTO data to the loginSuccess view.
2.)Please Suggest me the Best Practice Which should be Followed.
1.) First of all you can reduce your code in javascript like below, Directly serialize the form object.
var signupObj = {
signup : function() {
alert("In Signup function");
$.ajax({
type: "POST",
url : "signup",
data: $('#myForm').serialize(),// add "myForm" as the form id
async:false,
success: (function(data) {
alert("data"+data);
redirectView("success",data);
})
error : function(data, textStatus, errorThrown) {
alert(error_occured);
redirectView("error",data);
}
});
}
};
<script
function redirectView(message,data){
var url = "";
if(message == "success"){
url = "/success";
}else{
url = "/error";
}
$.ajax({
type: "POST",
url : url,
data: data
async:false,
success: (function(data) {
alert("data"+data);
})
error : function(data, textStatus, errorThrown) {
alert(error_occured);
}
});
}
</script>
2.) Redirect the success or failure view from the controller itself.
3.) Pass my profileDTO data to the loginSuccess view.
Spring MVC, from version 3, allows you to return objects directly converted into JSON using the #ResponseBody annotation in a Controller as shown here
#RequestMapping(value="/signup",method=RequestMethod.POST)
#ResponseBody
public ProfileDTO signup(#ModelAttribute("LoginDTO") LoginDTO loginDTO,BindingResult bindingResult) {
ProfileDTO profileDto = new ProfileDTO();
//In case no errors in backend logic
profileDto.setError(null);
profileDto.setProfileID("profileID");
profileDto.setProfileName("profileName");
System.out.println("Submitting SignUP Form Will Return ProfileID");
return profileDto;
}
If Forward from controller
With a prefix of forward, Spring will get a RequestDispatcher for the specified path and forward to it. Part of that process will include taking the Model from the ModelAndView created for that request handling cycle and putting all its attributes into the HttpServletRequest attributes.
The Servlet container will take the RequestDispatcher#forward(..) and again use your DispatcherServlet to handle it. Your DispatcherServlet will create a new ModelAndView with a new Model for this handling cycle. Therefore this Model doesn't contain any of the attributes from before but the HttpServletRequest attributes do.
In your case, this
modelMap.put("key", "value");
will end up being in
HttpServletRequest request = ...;
request.getAttribute("key");
I have a form on my jsp page. In this form i choose a file (zip archive) and after click submmit call servlet to upload this file. For file upload im use Apache Commons FileUlpoad library. After upload im unzip archive. Them i do redict to this jsp.
jsp code:
<form action="Upload_Servlet" method="post" enctype="multipart/form-data">
<div id="up">
<input id="fileUpload1" type="file" name="filename1"value="Browse..."/>
</div>
<div>
<input id="btnSubmit" type="submit" value="Загрузить">
<input type="button" id="del" onclick="deleting()" value="Удалить">
</div>
</form>
servlet code:
public class uploadfile extends HttpServlet
{
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, java.io.IOException {
System.out.println(response.getCharacterEncoding());
response.setCharacterEncoding("UTF-8");
System.out.println(response.getCharacterEncoding());
response.setContentType("text/html");
PrintWriter writer = response.getWriter();
writer.println("wtpwebapps<br/>");
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (!isMultipart) {
writer.println("<HTML>");
writer.println("<HEAD <TITLE> Upload4 </TITLE> </HEAD>");
writer.println("<BODY>");
writer.println("<FORM action = \"Upload_Servlet\" method = \"post\" enctype = \"multipart/form-data\">");
writer.println("<INPUT type = file name = ufile>");
writer.println("<INPUT type = submit value = \"Attach\">");
writer.println("<h1>its not multipart</h1>");
writer.println("</FORM>");
writer.println("</BODY>");
writer.println("</HTML>");
return;
}
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> list=null;
String mifpath= "1";
String path = " ";
String mif = " ";
String from = "\\\\";
String to ="/";
String error="";
try{
list = upload.parseRequest(request);
Iterator<FileItem> it = list.iterator();
response.setContentType("text/html");
while ( it.hasNext() )
{
FileItem item = (FileItem) it.next();
File disk = new File("C:/uploaded_files/"+item.getName());
path = disk.toString();
String code = new String(path.substring(path.lastIndexOf("."), path.length()).getBytes("ISO-8859-1"),"utf-8");
if (code.equalsIgnoreCase(".zip"))
{
mifpath=path;
mif = mifpath.replaceAll(from, to);
item.write(disk);
error=unzip.unpack(mif, "C:/uploaded_files");
}
else
{
error = "Выбранный файл не является архивом zip";
}
}
}
catch ( Exception e ) {
log( "Upload Error" , e);
}
request.setAttribute("error", error);
request.getRequestDispatcher("/Home.jsp").forward(request, response);
// String redictedURL="http://localhost:8080/redicted_test/Home.jsp";
// response.sendRedirect(redictedURL);
writer.close();
}
}
Now i want to do this on the portal. Its mean that i dont want to reload my jsp after I upload a file. So i have to use Jquery. And i have some questions:
How to submit form to use jquery in my case?
My servlet code will be work in portlet?
How to send parametrs to jps from portlet?
Using Jquery it can be done easily:
Set a click event on the submit button (or on the form submit).
Post data to servlet:
$.ajax({
url : base_url + 'Upload_Servlet',
type : "post",
data:$('form').serialize(),
cache : false,
success : function(data) {
//do some stuff
},
error : function(xhr, status, err) {
//do error stuff
},
timeout : 3000
});
//End ajax call
After the servlet is done, just use the response writer to write an aswer back (If it contains a lot of data, I'd recommend sending a response in the form of json, see here) and then the success callback is called and you can do whatever you like with this data.
IMPORTANT: Since you are submitting a form, you need to use e.preventDefault() so the form will not be actually submitted but rather be handeled by your ajax.