2

I'm using JSF 2.2, PrimeFaces 6 and Spring Framework 4.3 in my web application.
Users are redirected to the homepage after they logged in. In the homepage there are some charts, tables etc. are loaded. They show some real-time information and it takes some time to load the homepage. I don't want the user wait in login page too long. So I used the following code to load charts after page load as stated in here:

<h:form id="hiddenForm" style="display: none;">
    <p:remoteCommand name="onload" actionListener="#{homeMB.onload}"
        update=":firstChartForm :secondChartForm :thirdChartForm" global="false"/>
</h:form>

And this is the onload method of backing bean:

public void onload() {
    fillFirstChart(); //Takes 5 seconds
    fillSecondChart(); //Takes 1 second
    fillThirdChart(); // Takes 3 seconds.
}

Charts are filled by those methods and updated with the help of update parameter of p:remoteCommand, but it takes 9 seconds. I want to run those methods concurrently and update each of those charts with the datas provided by corresponding methods as soon as the datas are loaded.

I mean, users should be redirected to the homepage as soon as they clicked on login button, and in the homepage firstly SecondChart should be filled/updated in 1 second, and 2 seconds later ThirdChart filled/updated, and finally 2 seconds later FirstChart should be filled/updated. So it should take ~5 seconds in total.

EDIT: This answer does not work for me because when I load the charts asynchronously, JSF waits for the slowest one to update them all. Ok, it takes 5 seconds instead of 9 seconds in total but as I stated "in the homepage firstly SecondChart should be filled/updated in 1 second, and 2 seconds later ThirdChart filled/updated, and finally 2 seconds later FirstChart should be filled/updated". But if I apply the way described in the first answer, they are all updated in 5 seconds

This answer may be applied. I mean, as soon as the user clicks to login button, the server can gather and push the datas to the charts and they can be updated from backing bean by RequestContext.getCurrentInstance().update("foo:bar"); as showed here. But I thought there could be some easier way for this because I think many people may have faced a similar problem before.

Thanks.

Selcuk
  • 857
  • 2
  • 11
  • 32

1 Answers1

1

Don't do that much heavy lifting, blocking the UI, at a users request... at least not without starting an asynchronous Ajax call. Use the remote command with async="true" (on the p:remoteCommand), and keep the user informed on what is happening (using a p:poll for example) and add some form of caching. Or, take the order, let a scheduled job take care of the order in the background and report back to the user when it is done.

See also:

Jasper de Vries
  • 19,370
  • 6
  • 64
  • 102
  • After the user logged in and all the charts filled the first time, I'm using `p:poll` to retrieve them later. I could do the same with scheduled jobs as showed [here](https://stackoverflow.com/a/6151574/1046569). But for the first time I need something different. By the way, I'm already calling the `p:remoteCommand` with `async=true` but if I use only one remote command, all of them are updated 5 seconds later all together. If I use multiple remote commands, can you show me how to call them asynchronously? It is not allowed to use the same `onload` name for multiple remote commands. – Selcuk Jun 02 '17 at 12:11
  • You could use something like a timeout to start the remote commands simultaneously. See https://stackoverflow.com/questions/9516900/how-can-i-create-an-asynchronous-function-in-javascript – Jasper de Vries Jun 02 '17 at 12:22
  • By the way, I don't see `async="true"` in your question. You should use it in the `p:remoteCommand`. – Jasper de Vries Jun 02 '17 at 15:00
  • oh, I mean I tried it in my code before, but I removed it later because it didn't solve my problems. but thanks anyway. – Selcuk Jun 02 '17 at 15:09
  • I just analyzed the link you shared, but it does not work for my situation. I mean I changed the code a little bit [here](http://jsfiddle.net/5H9XT/92/), ok it runs asynchronous but doesn't run concurrent. But in my situation I need them to run simultaneously. I think I can solve it with Web Workers. Thanks again. – Selcuk Jun 02 '17 at 16:42
  • Web Workers doesn't work neither. As it is stated [here](https://www.html5rocks.com/en/tutorials/workers/basics/) Workers do not have access to the DOM (it's not thread-safe), the window object, the document object, the parent object. So, the only way left is using asynchronous push with websockets... – Selcuk Jun 04 '17 at 17:12