What I want is to get database updates.
i.e If any changes occur to the database or a new record is inserted it should notify to the user.
Up to know what I implemented is using jQuery as shown below
$(document).ready(function() {
var updateInterval = setInterval(function() {
$('#chat').load('Db.jsp?elect=<%=emesg%>');
},1000);
});
It worked fine for me, but my teacher told to me that it's not a good way to do recommended using comet or long polling technology.
Can anyone give me examples for getting database updates using comet or long polling
in servlets/jsp? I'm using Tomcat as server.
Just taking a shot in the dark since I don't know your exact environment... You could have the database trigger fire a call to a servlet each time a row is committed which would then run some code that looked like the following:
Get the script sessions that are active for the page that we want to update. This eliminates the need to check every reverse ajax script session that is running on the site. Once we have the script sessions we can use the second code block to take some data and update a table on the client side. All that the second code section does is send javascript to the client to be executed via the reverse ajax connection that is open.
String page = ServerContextFactory.get().getContextPath() + "/reverseajax/clock.html";
Browser.withPage(page, new Runnable() {
public void run() {
Util.setValue("clockDisplay", output);
}
});
// Creates a new Person bean.
Person person = new Person(true);
// Creates a multi-dimensional array, containing a row and the rows column data.
String[][] data = {
{person.getId(), person.getName(), person.getAddress(), person.getAge()+"", person.isSuperhero()+""}
};
// Call DWR's util which adds rows into a table. peopleTable is the id of the tbody and
// data conta
ins the row/column data.
Util.addRows("peopleTable", data);
Note that both of the above sections of code are pulled straight from the documentation examples # http://directwebremoting.org/dwr-demo/. These are only simple examples of how reverse ajax can sent data to the client, but your exact situation seems to be more dependent on how you receive the notification than how you update the client screen.
Without some type of database notification to the java code I think you will have to poll the system at set intervals. You could make the system a little more efficient even when polling by verifying that there are reverse ajax script sessions active for the page before polling the database for info.
Related
I am trying to do live streaming example app, where I can live update the list in the browser. I want to return all elements and then still listening (don't stop the stream) when new item is add to the database. Then I want to show new item in the browser. My current solution all the time prints all items (second by second) but I think there is better solution, when I can a) find the difference in list from last processing repository.findAll() and return only currList - prevList b) I can listen to some kind of events? Like inserting to table and add new item to still opened stream.
Here is my current code:
#RestController
#RequestMapping("/songs")
public class SongController {
private final SongRepository songRepository;
public SongController(SongRepository songRepository) {
this.songRepository = songRepository;
}
#GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Song> getAllSongs() {
return Flux.interval(Duration.ofSeconds(1))
.flatMap(x -> songRepository.findAll());
}
#PostMapping
public Mono<Song> addSong(#RequestBody Song song) {
return songRepository.save(song);
}
}
Here is how it looks like now:
As you can see, Its obviously looped, and I just need plain list with 7 elements on begining and then +1 element every time I post new song (by addSong()).
I don't need a entire ready solution, I just don't know what should I use.
Thank you in advance, cheers
In my experience there are three options that have different pros and cons.
You could create a web socket connection from the browser to your backend service. This will create a bi-directional connection that will allow you push updates from the server to your browser. In this instance whenever you add a song you would then write that song to the web socket connection and handle that on the browser side, so adding it to the list in the browser.
The cons of this are in my experience web socket connections are finicky and aren't the most stable or reliable.
You could use server side events. I haven't used this personally but I have heard this can be a viable options for pushing events from the server to the browser. https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
You could poll the endpoint. I know this approach gets a lot of hate in recent years but it is a viable options. The benefit with polling the endpoint is that it is resilient to failures. If your backend is overloaded and can't respond for one request it will likely be able to respond to a subsequent request. Also there are ways of improving commonly used endpoints so you're not hammering your database like a cache or something of that nature.
As I wrote in title we need in project notify or execute method of some thread by another. This implementation is part of long polling. In following text describe and show my implementation.
So requirements are that:
UserX send request from client to server (poll action) immediately when he got response from previous. In service is executed spring async method where thread immediately check cache if there are some new data in database. I know that cache is usually used for methods where for specific input is expected specific output. This is not that case, because I use cache to reduce database calls and output of my method is always different. So cache help me store notification if I should check database or not. This checking is running in while loop which end when thread find notification to read database in cache or time expired.
Assume that UserX thread (poll action) is currently in while loop and checking cache.
In that moment UserY (push action) send some data to server, data are stored in database in separated thread, and also in cache is stored userId of recipient.
So when UserX is checking cache he found id of recipient (id of recipient == his id in this case), and then break loop and fetch these data.
So in my implementation I use google guava cache which provide manually write.
private static Cache<Long, Long> cache = CacheBuilder.newBuilder()
.maximumSize(100)
.expireAfterWrite(5, TimeUnit.MINUTES)
.build();
In create method I store id of user which should read these data.
public void create(Data data) {
dataRepository.save(data);
cache.save(data.getRecipient(), null);
System.out.println("SAVED " + userId + " in " + Thread.currentThread().getName());
}
and here is method of polling data:
#Async
public CompletableFuture<List<Data>> pollData(Long previousMessageId, Long userId) throws InterruptedException {
// check db at first, if there are new data no need go to loop and waiting
List<Data> data = findRecent(dataId, userId));
data not found so jump to loop for some time
if (data.size() == 0) {
short c = 0;
while (c < 100) {
// check if some new data added or not, if yes break loop
if (cache.getIfPresent(userId) != null) {
break;
}
c++;
Thread.sleep(1000);
System.out.println("SEQUENCE: " + c + " in " + Thread.currentThread().getName());
}
// check database on the end of loop or after break from loop
data = findRecent(dataId, userId);
}
// clear data for that recipient and return result
cache.clear(userId);
return CompletableFuture.completedFuture(data);
}
After User X got response he send poll request again and whole process is repeated.
Can you tell me if is this application design for long polling in java (spring) is correct or exists some better way? Key point is that when user call poll request, this request should be holded for new data for some time and not response immediately. This solution which I show above works, but question is if it will be works also for many users (1000+). I worry about it because of pausing threads which should make slower another requests when no threads will be available in pool. Thanks in advice for your effort.
Check Web Sockets. Spring supports it from version 4 on wards. It doesn't require client to initiate a polling, instead server pushes the data to client in real time.
Check the below:
https://spring.io/guides/gs/messaging-stomp-websocket/
http://www.baeldung.com/websockets-spring
Note - web sockets open a persistent connection between client and server and thus may result in more resource usage in case of large number of users. So, if you are not looking for real time updates and is fine with some delay then polling might be a better approach. Also, not all browsers support web sockets.
Web Sockets vs Interval Polling
Longpolling vs Websockets
In what situations would AJAX long/short polling be preferred over HTML5 WebSockets?
In your current approach, if you are having a concern with large number of threads running on server for multiple users then you can trigger the polling from front-end every time instead. This way only short lived request threads will be triggered from UI looking for any update in the cache. If there is an update, another call can be made to retrieve the data. However don't hit the server every other second as you are doing otherwise you will have high CPU utilization and user request threads may also suffer. You should do some optimization on your timing.
Instead of hitting the cache after a delay of 1 sec for 100 times, you can apply an intelligent algorithm by analyzing the pattern of cache/DB update over a period of time.
By knowing the pattern, you can trigger the polling in an exponential back off manner to hit the cache when the update is most likely expected. This way you will be hitting the cache less frequently and more accurately.
I have a task where a user consumes XML from a third party. The XML feed is only updated once a day. The XML is stored in a database and returned to the user when requested. If the XML is not in the database, then it is retrieved from the third party, stored in the database and returned to the user. All subsequent requests will simply read the XML from the database.
Now my question. Say it takes 10 seconds for the request to the third party to return. In this period, there are multiple server calls for the same data. I don't want each of these to fire off requests to the third party and I don't want the user to receive nothing or an error. They should probably wait for the first request to complete at which point the XML would be available. This is a relatively simple problem but I want to know what the best way of catering for it is.
Do I just use a simple flag to control requests or maybe something like a semaphore? Are there better solutions based on the stack I intend to use which is the Play framework and a cassandra backend. Is there something I could do with callbacks or triggers?
By the way, I need to lazy load the data when the first request comes in. So, in this task it isn't an option to get the data in a separate process or when the app starts...
Thanks
All you need to do is create a separate component that is responsible to get the XML from the third party and save it to the database.
In your code the various thread try to "fetch" the XML from this component.
This component returns the XML from the database if it exists. If it does not exist then you use a ReentrantLock to synchronize.
So you do a trylock and only one of your threads succeeds. The rest will be blocked. When the lock is released the other threads are unblocked but the XML has already been fetched from the third party and stored to the database by the thread that first managed to gain the lock. So the other threads just return the XML from the DB.
Example code (this is just a "pseudo code" to get you started. You should handle exceptions etc but the main skeleton can be used. Do NOT forget to unlock in a finally so that your code does not block indefinitelly):
public String getXML() {
String xml = getXMLFromDatabase();
if(xml == null) {
if(glocalLock.tryLock()) {
try{
xml = getXMLFromThirdParty();
storeXMLToDatabase(xml);
}
finally {
globalLock.unlock(); //ok! got XML and stored in DB. Wake-up others!
}
}
else {
try{ //Another thread got the lock and will do the query. Just wait on lock!
globalLock.lock();
}
finally {
//woken up but the xml is already fetched
xml = getXMLFromDatabase();
globalLock.unlock();
}
}
return xml;
}
I'm new to server side.
I'm creating a database app for my company that stores links to all our marketing videos. Each entry is a url(to video), description, industry etc.
I already have the front end somewhat set up in HTML/JavaScript. Using a local XML source file, it populates a list with video names, and has text fields for all props of the video item.
Here's my question:
How do I handle updating my view when I send the form data (new entry) to the back end?
Should I insert a new entry based on local data?
Should I wait for the response from the server, and if success then update view based on local data?
Or, same as above, but update view based on back end data?
The goal is to make sure my view always reflects the state of data on the back end.
(Back end is Java / Google App Engine)
When using AJAX:
There is a callback function included in it, which triggers asynchronously when the response of the request comes back from the server.
In this function you can call your page update functions to execute on the page updating processes.
I have a web page that has a function that will send an initial request to a web service.
After some predefined time, the user can send a second request.
After the user sends the first request, I want the web page to countdown when the user may send the second request.
After the countdown, I want a DB field to be updated automatically, indicating that the appropriate time has passed.
When the time has passed and the DB updated, I'd like the webpage updated to show a button that would allow the user to send the second request.
After the initial request, call a JavaScript user-defined function "countdown()" using the in-built JavaScript function "setTimeout("countdown()", 4000)", where the number "4000" resembles the number of micro-seconds that need to be passed to fire the function mentioned in the first parameter.
In the "countdown()" function, write the logic for the AJAX call, where you will be updating the database that the desired time of 4 seconds (for example) has passed & now the user can send the second request.
Also in the same AJAX call, you can print out some word (let the word be "yes" for example), which you can catch / fetch it in the "countdown()" function definition, using the "responseText" keyword of JavaScript's "XMLHttpRequestObject", in a dummy variable "flag".
Now you can write something like the following in the "countdown()" function definition:-
function countdown() {
document.getElementById("btn_second_req").style.display = 'none';
var flag = '';
// all code to prepare for AJAX call
// AJAX called, return also fetched in a variable "flag".
if (XMLHttpRequestObject.readyState == 4 && XMLHttpRequestObject.status == 200) {
flag = XMLHttpRequestObject.responseText;
}
if (flag == 'yes') {
document.getElementById("btn_second_req").style.display = 'block';
}
}
So by default, the second request firing HTML button is hidden from the very first time, & only activated when the "flag" variable condition is satisfied.
Also since the details of the first call of any user is being kept in the DB, so in the second call, you need to check with server validation that there exists details for the first call, otherwise the second request call will not be entertained.
These type of logic can easily be implemented using any JavaScript framework library (like jQuery or Prototype) or by plain JavaScript only.
Hope it helps.
Yes, it can be done. Here is how I would do it, which is almost as you describe it.
1- The web page sent the request to the service. The service compute the time until the next request can be executed, store it in a db field/in session (depending how your service work), and send it back to the client, plus whatever it is your service send back.
2- You create a timer with the setTimeout function of javascript (or an equivalent if you use a javascript library) http://www.w3schools.com/js/js_timing.asp .
3- When the timer execute, you send a request to the webservice to ask if its ok to start the second request. The server check the time in the db field. If it is past "next request time", the server respond positive, else it return the remaining time, and the client then create a new timer.
4- You send your new request. The server check again if its "next request time" (in case someone smart hack the javascript, or if their is a bug on the client). If it is time, it execute the second request.
The only difference is that with the way I described, everything on the server execute as the result of a client action, so you don't have to mess with thread/cron job to auto update your db field.
Good luck!