Play-Framework & Ajax how to? - java

I'm looking to do the following with AJAX...
I have a request to my server that takes a considerable amount of time to complete. The request is made in the controller and upon completion a HTML page is loaded informing the user of its completion.
However, what I'd like to do is have the request sent asynchronously, load the completion page and then load the requests result once it become available. I assume I would use AJAX to do this but I'm not exactly sure how. Can anyone point me to a good guide for doing something like this?
In case my explanation above is too confusing here is what I want to do...
1) Send request to server from Controller asyncronously.
2) load HTML page.
3) When request has completed fill field in already loaded HTML page with the response from the request.

I wrote a tutorial recently that walks through how to do this with Play 1.2, JSON, and jQuery:
Tutorial: Play Framework, JPA, JSON, jQuery, & Heroku

There are 2 parts you need to take into account here:
The client side
The server side
For the client side; an Ajax request (for example, using jQuery.ajax) is per definition asynchronous. This means that you should be able to do the following - again using jQuery, which makes things easier - in your HTML page:
// The ready handler, which fires when the page has been loaded
$(function() {
jQuery.ajax(
// Do your thing here
);
});
For the server side; in case your operation is going to be running for a relatively long time on the server (for instance several web service calls or long running IO operations) you'll want to use Play's asynchronous capabilities to let the Play! server execute things as effeciently as possible. It does this by offloading the long running operation(s) to their own threads.
The only thing left to do is set-up a route to your controller, implement the handler method and render something that your client-side JavaScript code is capable of parsing (JSON is probably the easiest, using Play's renderJson()).
I haven't used this set-up myself - maybe someone can confirm this would be the way to do it?

Related

validate REST endpoint design

REST endpoint design says: Not use verb
In an workflow-like create Employee which has multi-tab style like "Basic Details", "Educational Details", "Work Experience", etc... One first tab data is filled continue button is pushed resulting in an backend API call which just validates the detail in that tab and returns the list of validation errors if any or moves to next tab for the user to fill data. So basically this calls for validate API for each of the tabs with no intention of saving data. Now one thing that comes naturally is below:
POST /employee/basic/validate
(removing api versioning details from endpoint for simplicity)
But using validate in API means verb. How to design then?
There's a separate flow where one can just save "basic details" of employee - so its like any normal API validate and save - so POST /employee/basic/ is good for that case.
REST endpoint design says: Not use verb
That's not a REST constraint - REST doesn't care what spellings you use for your resource identifiers.
All of these URL work, exactly the way that your browser expects them to:
https://www.merriam-webster.com/dictionary/post
https://www.merriam-webster.com/dictionary/get
https://www.merriam-webster.com/dictionary/put
https://www.merriam-webster.com/dictionary/patch
https://www.merriam-webster.com/dictionary/delete
Resources are generalizations of documents; the nature of the HTTP uniform interface is that we have a large set of documents, and a small number of messages that we can send to them.
So if you want a good resource identifier, the important thing to consider is the nature of the "document" that you are targeting with the request.
For instance, the document you are using to validate user inputs might be the validation policy; or you might instead prefer to think of that document as an index into a collection of validation reports (where we have one report available for each input).
Seems that what you try to do in the end is to run your operation in dry-run mode.
My suggestion would be to add a dry-run option as request parameter for instance.
/employee/basic?dry-run=true
REST says that you should use standards like HTTP to achieve a uniform interface. There are no URL standards as far as I know, even OData says that its URL naming conventions are optional.
Another thing that the browser is a bad REST client. REST was designed for webservices and machine to machine communication, not for the communication of browsers with webapplications, which is sort of human to machine communication. It is for solving problems like automatically order from the wholesaler to fill my webshop with new items, etc. If you check in this scenario both the REST service and REST client are on servers and have nothing to do with the browser. If you want to use REST from the browser, then it might be better to use a javascript based REST client. So using the browser with HTML forms as a REST client is something extreme.
If you have a multitab form, then it is usually collected into a session in regular webapplications until it is finalized. So one solution is having a regular webapplication, which is what you actually have, since I am pretty sure you have no idea about the mandatory REST constraints described by Fielding. In this case you just do it as you want to and forget about REST.
As of naming something that does validation I would do something like POST /employee/basic/validation and return the validation result along with 200 ok. Though most validation rules like "is it a date", "is it a number", etc. can be done on the clients currently they can be done even in HTML. You can collect the input in a session on server or client side and save it in the database after finilazing the employee description.
As of the REST way I would have a hyperlink that describes all the parameters along with their validations and let the REST client make tabs and do the REST. At the end the only time it would communicate with the REST service is when the actual POST is sent. The REST client can be in browser and collect the input into a variable or cookies or localstorage with javascript, or the REST client can be on server and collect the input into a server side session for example. As of the REST service the communication with it must be stateless, so it cannot maintain server side session, only JWT for example where all the session data is sent with every request.
If you want to save each tab in the webservice before finalizing, then your problem is something like the on that is solved with the builder design pattern in programming. In that case I would do something like POST /employeeRegistrationBuilder at the first step, and which would return a new resource something like /employeeRegistrationBuilder/1. After that I can do something like PUT/POST /employeeRegistrationBuilder/1/basics, PUT/POST /employeeRegistrationBuilder/1/education, PUT/POST /employeeRegistrationBuilder/1/workExperience, etc. and finalize it with PUT/POST /employeeRegistrationBuilder/1/finished. Though you can spare the first and the last steps and create the resource with the basics and finish it automagically after the workExperience is sent. Cancelling it would be DELETE /employeeRegistrationBuilder/1, modifying previous tabs would be PUT/PATCH /employeeRegistrationBuilder/1/basics. Removing previous tabs would be DELETE /employeeRegistrationBuilder/1/basics.
A more general approach is having a sort of transaction builder and do something like this:
POST /transactions/ {type:"multistep", method: "POST", id: "/employee/"}
-> {id: "/transactions/1", links: [...]}
PATCH /transactions/1 {append: "basics", ...}
PATCH /transactions/1 {append: "education", ...}
PATCH /transactions/1 {remove: "basics", ...}
PATCH /transactions/1 {append: "workExperience", ...}
PATCH /transactions/1 {append: "basics", ...}
...
POST /employee/ {type: "transaction", id: "/transactions/1"}
-> /employee/123
With this approach you can create a new employee both in multiple steps or in a single step depending on whether you send actual input data or a transaction reference with POST /employee.
From data protection (GDPR) perspective the transaction can be the preparation of a contract, committing the transaction can be signing the contract.

REST API Single Request - Multiple responses

I am writing a REST API in JAX-RS 2.0, JDK 8 for the below requirement
POST API /server/fileUpload/ (Multipart Form data) where I need to send a Big .AI (Adobe Illustrator) File in this.
The Server, takes the file and return Status 202 (Accepted), Acknowledging that file transfer happened Successfully. (From endpoint to Server)
Now at the Server, I am using Java + Imagemagik to convert .AI File (20-25 MB File) to small JPG Thumbnail, place on a Apache HTTP Server and share the location (like http://happyplace/thumbnail0987.jpg)
Now the Second Response should come from Server with Status 200 OK and Thumbnail URL
is it feasible with one REST API? (Async/similar)
or should I split it to 2 API calls, Please suggest
No. In http, one request gets one response. The client must send a second request to get a second response.
You can use WebSockets for that.
If you are calling from script the call will be async you can handle the Thumbnail URL when you get a response. When you are calling from java program i suggest to run it on a different thread, If the execution is not sequential i.e ( Remaining lines can be executed without getting URL). If url is needed for the remaining section of code you can make one call and wait for the response then execute remaining code.
You need to make different APIs for both scenarios. One for showing file upload status and another for all file conversion and manipulation.
On the client side second request must be callback of first request.
The best way to handle these kind of scenario is to use Java Reactive (Project Reactor, WebFlux).
You can return two response using custom middlewares in asp.net (however not recommended).
Return response from one middleware and subsequently you can invoke next middleware and return second response from second middleware

Redirect webpage after having sent some content

I am working with a web framework (uPortal) that is handling errors by just throwing an exception and then hanging. The framework works by rendering XML into HTML. When there is an exception, the browser recieves rendered content up to the XML template element that is failing, and then the browser just sits and waits for a timeout. Our team's theory is that the content is sent before the error occurs, which surprised me. Other frameworks I've worked with seem to finish rendering before sending content.
My question is, is there a way to redirect the browser after content has already been sent? In this case, we are in the middle of rendering the content of a <script> tag, but the error could occur potentially anywhere in the html.
My only current thought is to inject some javascript at the top of the page, and to try to change the framework's behavior to fail quickly and close the connection and add </body> and </html> tags when an error occurs. Then the above mentioned javascript would run on pageload and detect if the entire page's content was there and do a client-side redirect if not. Maybe it could look for a special hidden div at the bottom of the page.
Are there any examples of frameworks solving this problem differently or of people using similar framework working around this issue?
You must either capture the error, or capture the output in a buffer. If you can handle the exception, you can probably print a simple script tag like
<script> window.location.href = 'some_new_url';</script>
If the browser understands the doctype to be something related to HTML, it will execute that tag.
If you can capture the output in a buffer, when you handle the error you can decide to send an HTTP redirect to the browser and destroy the output buffer up to that point.
As for other frameowrks, in PHP, you can simply enable output buffering with ob_start(), which won't start sending content until the request is fully completed.
I don't know that framework, but
In http, every response has a response-code associated with it. Since the page is already half-way transferred / rendered that status code (usually "200") was sent (and received) already.
There's no way for the browser to accept another response code (like "301" for redirect) for the same response! Also the server is not able to send another response code, because the original response code was already commited and sent to the client.
Your description of the error and knowledge of the http-protocol implies that there is probably some implementation error in the framework / server components used, OR it was done deliberatly, risking the situation that you are in now...
to redirect a page , you need to set redirect information in header. but you can write header once you start writing content ( may be header is already received by client by the time you compete writing whole document )
But, you can do it in different way as below
1.let document loading complete and record if you need to redirect the page while rendering
2. add a unique request-id identifier for each page load
3. invoke ajax call with request-id ( may be rest call) to server asking if page needs to be redirected.
4. if page needs to be redirected , do so, via javascript in browser at client end.
A HTTP response consists of headers and an optional response content.
Once you have started to write the response to the socket connection you can't revert it. In your example: If you run into an error in the middle of content generation you can't add a redirect header - the header section has already be written.
The statement above is not entirely true: in HTTP chunked transfer encoding the response is sent in separate chunks. The last chunk can have an optional trailer containing entity-header fields and theoretically a redirect header. But if you can use these mechanism is a different question. For instance a servlet container may use chunked transfer encoding but does not give you an API to set the trailer.
But writing must not start immediately: For instance HttpServletResponse maintains a buffer for the response content. If you set headers and start writing the content only the buffer is filled and you still can reset the response and start all over. But once the buffer overflows the response is written to the connection and the HttpServletResponse is now committed.
Such a mechanism gives you way to deal with errors during content generation which happen when the response is not yet committed: Just reset the response and send an error message instead. You could examine your framework if it supports such an mechanism. But obviously this is not a solution for larger responses.
A second way to avoid errors during content generation is simply to make sure that they can't happen. First gather all your data needed for the response (e.g. making unsafe database calls), then in a second step generate the response - the second now step should not fail (except if you have bugs in your code).
You already mentioned a third way to handle an error, by having the client sanitize the response and take some action it errors are detected (e.g. by including a script in the generated HTML response).
The only reliable way to do this is to create a proxy HttpServletResponse object that caches the response. You'd need to give the uPortal this proxy instead of the actual HttpServletResponse, and only send the output using the real response once the processing completes / send redirect if the processing fails.
It is HTTP protocol design limitation that you cannot send HTTP redirect once output was started.
Other possible ways rely on HTML or Javascript redirects, but since you write that the error may happen at any moment, it would be difficult to print it out in a way that the browsers would reliably interpret it as redirect.

Real-time Process Progress Logs for the User

Well, I'm Trying to Make a Data Importing Module. From the module, the user choose the .txt File with Data and then click the upload button. I want to make a Textarea or textbox (My project is a Java EE WebApp) where the webapp shows the real-progress of the upload proccess with Descriptive Messages.
I'm thinking (And i've searched) about Multiple Ajax Requests, and, Multiple Ajax Responses with one Request (The last one is not valid, as i read), but, i'm confused about the usage of AJAX in this case. It is Valid the user hit "Upload", and then, i call an AJAX Request that returns the text with the progress of the actual registry imported?
I'm thinking to use:
jQuery 1.6.2
GSon (For ajax)
Any suggestion would be appreciated
I would recommend using JBoss RichFaces 'poll' mechanism for that, or just a simple jquery script on the client side:
Ajax Poll Example with RichFaces: http://richfaces-showcase.appspot.com/richfaces/component-sample.jsf?demo=poll&skin=blueSky
JQuery (loads of examples on the web):
http://net.tutsplus.com/tutorials/javascript-ajax/creating-a-dynamic-poll-with-jquery-and-php/
jQuery AJAX polling for JSON response, handling based on AJAX result or JSON content
How about using a iframe that handles the upload form? This way it would not require the browser to update (by AJAX calls) the contents of a page that "we're already leaving". The iframe could be styled so that it's indistinguisable from other content.
AJAX-calls to a some method that keeps an eye on to some progress-variable (lets say a double that indicates percentage) is perfectly valid. Below is a barebones pseudo-example.
!PSEUDO!
double progress = 0.0d
void upload(request, response) {
// updates progress real-time
}
void ajaxProgress(request, response) {
// set progress to response
}
You may want to consider all the traffic back and forth showing real time processing information of uploaded files.

Is it a good practice to use asynchronous requests in this scenario?

I have a scenario that I have a button in JSP page which sends an email, the request is send to servlet asynchronously using jQuery Ajax and JSON, servlet searches in DB, if the user has an email, it returns the email address and sends an email to it, then forwards to the result page with success or fail of sending the email, but in a case that the user doesn't have an email, it returns false values using JSON to JSP and then a JSP form appears to the user to enter his email.
Is it good practice to use Ajax and I know that not each time there's a return value to the user or send request to servlet using get method which return a parameter in a case that the user doesn't have an email?
Using ajax is in practically all cases very good for User Experience. With ajax, the user will experience instant feedback without the need to face an annoying "flash of content" or a (partially) empty page because the whole HTML response needs to be generated/buffered by the server first. This is really a huge plus of using JS/ajax.
Using JSON is generally favorable above XML, HTML or even plain text. But there is no "best practice" with regard to the ajax data exchange format between client and server. Just pick whatever suits the requirement the best. JSON is perfectly fine for this case. jQuery understands it out-the-box and in Java you have choice of a plethora of easy-to-use JSON parsers.
However, when developing an ajax-enabled webapplication, you really need to take into account that the core functionality does not break when the client has JS disabled. This is called Unobtrusive JavaScript. Most of the searchbots, mobile browsers and textbased browsers don't use JS. You should try to use JS only for Progressive Enhancements. To test this yourself, in Firefox you can use for example the Web Developer Toolbar to easily enable/disable JS support. Run your website with JS disabled and observe if the core functionality is maintained as well.
The best way to achieve this is to start developing the website without any single line of JS code, even without a single onclick, onsubmit, onwhatever attribute on the HTML elements. Once you get the core functionality to work, then you can start adding JS in flavor of a script which executes during document ready and attachs functions to the HTML elements of interest (even here, you should not change the original HTML code!). Let the JS functions fire ajax requests on the same URL or maybe a different one, depending on the requirement. You can in the Servlet distinguish between an ajax and normal request as follows:
if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
// Handle ajax request. Return JSON response here.
} else {
// Handle normal request. Return normal HTML response here (by JSP).
}
See also:
Simple calculator in JSP - contains unobtrusive JSP/Servlet/jQuery example
Json is just a data-interchange format. Using Json or not has nothing to do with using asynchronous communication or not... You can do both communication types using Json (or XML, or serialized objects, it doesn't matter).
Now, in your problem, it looks like you just want to use Asynchronous communication to improve the user experience (it will not flick the user's browser). If that's the case, Asynchronous communication is the way to go!
I don't think you need ot use AJAX in this.
The main idea of the ajax is to render server response without postback and in your case you are redirecting page after you get some kind of result.
In my opinion you shoul choose on of these two ways.
1) Use AJAX, send data to servlet and then render response from server wether the mail is sent or not.
2) Submit your form to servlet and sent email and then redirect to jsp with the success/fail result.
Hope it helps.

Categories

Resources