I have a couple of queries for a web site that take a long time to run due to the data model and the amount of data held in the tables. So far I've been running them manually against the database to avoid any timeout issues etc.. however the site owner has asked for these to be made available on the site so he can get the query results.
I had thought of doing this via a .NET web service and having the classic ASP page call this asynchronously. The web page would just initiate the process and before redirecting the user to another screen. The web service would then run the query and email the user the results in a CSV.
However, I can't seem to get this to work. The service runs ok if I invoke it through the screen in IE but calling it through an Ajax call in ASP seems to be an issue - no error is generated but neither is the CSV file created.
I've enclosed the classic ASP code below. The service only has one method with a parameter of the name email which is of the type string. Can anyone see anything wrong with it? Also, this the best way to be doing this or should I be thinking of another approach?
CODE
<%
message = "http://wwww.example.com/service/query.asmx/GetResults?email=test"
set req = server.createobject("MSXML2.XMLHTTP")
With req
.open "GET", message, False
.setRequestHeader "Content-Type", "text/xml"
.send
End With
works = req.responseText
response.redirect "http://www.bbc.co.uk"
%>
The idea of asynchronously requesting the work and arranging for its later delivery seems very reasonable to me. I don't speak ASP well enough to know what's wring with your attempt, but is that really an asnch call you have there? Would the seb service also suffer from an HTTP connection timeout?
My approach would have been for an Ajax request to place a request on a queue and return, no need for a redirect, you're still on the page where the user makes the request, your JavaScript could just acknowledge that the request was sent. Alternatively, your more traditional "submit a page, stash the request, display another page" appraoch can work, but the the stashing is just to put the request on a queue.
An advantage of the queueing approach is that by controlling the number of daemons we can get controlled parallelism in servicing the requests - avoid overloading the DB. Also the queues can persist and allow a leisurely delivery of the responses.
I assume that MS queues then let you have a daemon processing the reuquest and delivering the responses. Clearly email works, but strikes me as a tad unfriendly. With Ajax style interfaces it would be quite easy to invisibly poll for the status of requests and obtain the results when they are ready, or even to use Comet-style push delivery of the responses.
The problem here, as djna noted, is that you are not calling a callback function.
Due to the asynchronously aspect of Ajax, you have set up a callback function that will be executed when the Ajax call ends.
Long story short:
Call the webservice from a javascript function, preferably using JQuery to avoid cross browser incompatibilities
Code:
<div id="results">Processing query. Please wait</div>
<script type="text/javascript">
$(document).ready(function(){
$("#results").load("http://wwww.mywebsite.com/service/query.asmx/GetResults?email=test&Rnd=" + Math.random().toString());
});
</script>
Related
I have a VS 2013 Lightswitch HTML Client application to which I've added a button that makes a Web API REST post. This basically 'refreshes' the data in the table from the original upstream source. This is all working correctly, but the operation takes a few minutes, and I want to report status to the user as it runs.
Right now, I've tried attaching a simple Refresh when the post returns as follows:
$.post("/api/data/", "Refresh", function (response) {
screen.getData().then(function (newData) { screen.reQuery(); });
});
This doesn't actually seem to do a refresh (screen.reQuery is apparently the wrong call), but the better option would be to instead have the server show progress of this long-running application.
One thought I had would be to have the server call return data in the form of "percent done" in the response as it processes it, but I don't know if this would be delivered to the client piecemeal, nor the best way to display this to the user in Lightswitch.
I'm open to other third-party libraries that might help with this, but I'd like to stick with WebAPI for commanding instead of adding something like SignalR for now, if possible. Thanks!
In general this seems like not the best idea to run operations that takes minutes on the server.
A reasonable alternative is to create a single call, that will in turn create multiple Web Jobs (see Azure Web Jobs for more info). The Web Jobs will be broken to smaller individual tasks, and your html will query the web jobs rather than your Web API.
I need to cancel renderProcessing (doView method) from executing after processing Action or Event phase (As i don't want the whole page or any portlets to be refreshed). Something like ajax resource acquiring which is not leading to refresh all portlets (I mean serveResource method). Can we use "destroy()" method at the end of ProcessAction or ProcessEvent to prevent renderPhase from executing. I'm using MVCPortlet framework and events ipc extensively in my portlets. Thanks for your help.
As Georgy Gobozov stated in the comment: The answer to your question is "No".
If you are using the standard portlet request handling and rely on event handling, you're bound to a full page reload. There's nothing that keeps you from implementing custom event handling (e.g. with JS on the browser, through your business layer etc.) but unfortunately you'll have to do exactly this.
When you start the original request, e.g. through an action handler, the page has already started to reload (from the browser perspective). Any attempt to cancel the processing server side will result in the stream to break and the browser signalling an error on the page (e.g. "can't load": The result must come with an HTTP status - and it will most likely be an error code (e.g. 50x), or it must contain the whole page's HTML.
Im pretty new to struts2 and Ajax ,Actually i have a drop down menu in JSP lets say first.jsp, When user select a choice from dropdown menu,I am calling a function of Action class lets say Method1.In this method i am fetching some value from DB(lets say:a,b,c) and one value from java memory lets say d.Then I am forwarding to second.jsp and display all the parameters(a,b,c and d) in tabular format.
Now problem is that the parameter d is dynamic ,this is updating by some other application and if its change then I have to show it on JSP wihout any action.
One solution is I use in second.jsp , so after interval of 10 second again Mehod1 will call and it will fetch value(a,b,c) from db and updated value of d from java memory. and disply it to second.jsp.But in this case i am unnecessary retrieving value from db while my purpose is just to get value d from memory.This is working but this is causing my application to slower.
Can any body suggetst some other solution? or can i do it using ajax and how?
Any other advice? any help is appreciated.try to be more clear, i'm in lack of ideas in this problem, even it sounds like a classic :I have spend hours trying to play around with this but have got nowhere
Okay... What you're asking is a little fuzzy so let me rephrase:
You have a user (USER1) who opens a web page and sees some data.
You have a second user (USER2) (who may be an application) who is able set a value from time to time.
When USER2 updates that value you want USER1 to see it change in their open browser window?
If this is the case you need to understand basic ajax. For that get these demo applications working:
This example uses dojo and perhaps the S2 ajax tag lib I don't remember I prefer not to use ajax tags (as they are deprecated and prefer jquery for ajax):
http://struts.apache.org/2.x/docs/struts-2-spring-2-jpa-ajax.html
This example here shows a very similar application but using jquery, no tag library, upgraded to Spring 3, it still needs polish:
http://www.kenmcwilliams.com/Downloads/
Now that you know how to get data via ajax, look at the request with firebug. You'll see that the request is just like a typical function call, the browser keeps waiting for the data to come back.
What you do is simply not return from the action until new data is provided. This is called long polling see: http://en.wikipedia.org/wiki/Comet_%28programming%29#Ajax_with_long_polling
If you have not written a simple chat program, using just terminal windows I recommend you do so. Two windows per client (client-send, client-receive windows) and you'll need a server program. I remember hacking one together in a few hours using _Thinking In Java 2nd Edition (Later books took out the networking section if I remember correctly). Anyways between understanding client server interaction and long polling will let you get things working. It would be fun to extend the simple terminal based chat application to a S2 ajax chat application. Would make an awesome tutorial! PS: This is just an application of the producer/consumer problem (If you understand that then I guess you don't need to do the fun exercise).
The interfaces would look very pretty if the server was managed by spring. I know there must be nice servers already written but I am not familiar with any, but would love to hear of one.
I'm familiar enough with Ajax and JSON that I can send a request and get a parse a JSON request. Ideally I'd like to receive multiple response to periodically update a progress bar. This way clients can have a positive feedback.
I've heard of JSON streams but have not found a good resource on how to implement this. Does anyone know of a good resource or how to do this?
JSON is just yet another format of data going over the HTTP protocol (like text, html, pdf, etc). You are probably referring to cometd.
This allows you to open a persistent connection and push data from the server to the client (ie stream it). Any format is valid to push, the client just needs to understand it.
Found a technique called page streaming.
Basically you write <script>some js</script> entries into the persistent connection and flush them into the network interface. As browser receives that, it will parse and execute the script.
Try looking into the library "comet." It's implements what's known as "reverse AJAX." It'll allow you to send events from the server to the client easily.
The polling suggestion made just before mine, is also perfectly valid.
<script language="JavaScript">
function doSomething() {
// do something here...
}
setInterval('doSomething()',10000);
<script>
That will call a function every 10 seconds. So you can poll the server every 10 seconds (or 1 second) to get a response on the status of whatever event you're trying to track. Simply put your AJAX call inside that function and it'll send.
I have an ASP.NET web service which does some heavy lifting, like say,some file operations, or generating Excel Sheets from a bunch of crystal reports. I don't want to be blocked by calling this web service, so i want to make the web service call asynchronous. Also, I want to call this web service from a web page, and want some mechanism which will allow me to keep polling the server so that i can i can show some indicator of progress on the screen, like say, the number of files that have been processed. Please note that i do not want a notification on completion of the web method call, rather, i want a live progress status. How do i go about it?
Write a separate method on the server that you can query by passing the ID of the job that has been scheduled and which returns an approximate value between 0-100 (or 0.0 and 1.0, or whatever) of how far along it is.
E.g. in REST-style, you could make a GET request to http://yourserver.com/app/jobstatus/4133/ which would return a simple '52' as text/plain. Then you just have to query that every (second? two seconds? ten seconds?) to see how far along it is.
How you actually accomplish the monitoring on the backend hugely depends on what your process is and how it works.
I think XML web service is slow, so creating multiple methods and polling the progress will be extremely slow and will generate huge load on the server. I wouldn't do it in production environment. I see the same (but smaller) problems with database polling.
Try SOAP extensions instead. It implements an event-driven model. See Adding a Progress Bar to Your Web Service Client Application on MSDN.
You can also use SoapExtensions to notify your client of the download/process progress. The server can then send events to the client. Nothing in the client has to be changed if you don't use it.
Allows for something like this in your client:
//...
private localhost.MyWebServiceService _myWebService = new localhost.MyWebServiceService ();
_myWebService.processDelegate += ProgressUpdate;
_myWebService.CallHeavyMethod();
//...
private void ProgressUpdate(object sender, ProgressEventArgs e)
{
double progress = ((double)e.ProcessedSize / (double)e.TotalSize) * 100.00;
//Show Progress...
}
Have the initial "start report generation" web service call create a task in some task pool, and return the caller the ID of the task.
Then, provide another method that returns the "percent done" for a given taskId.
Provide a third method that returns the actual result for a completed task.
Easiest way would be to have the Web Service update a field on a database with the progress of the call, and then create a Web Service that queries that field and returns the value.
Make the web service to return some sort of task ID or session ID. Make another web method to query with that ID, which returns the information needed (% completion, list of files, whatever). Poll this method at some interval from the client.
Use a database to store the process information, if you do this in memory of the web service, this will not scale well in web farm environment, as it may happen that the task runs on another server, than the one you are polling.
EDIT: I just saw another similar answer, and comment to it. The commenter is right - you can use in-memory table to avoid disk operations, but still using a separate db server.