Vaadin lets you build secure, UX-first PWAs entirely in Java.
Free ebook & tutorial.
unexpected calls from browser to server
Am getting pretty stuck here, and could use some help. In another thread, I asked about having sessions expire when using the Refresher add on. I have a workaround for the session expiration problem, which almost always works:
1. Implement HttpServletRequestListener and Refresher.RefreshListener.
2. When a call come into onRequestStart(), note the current time as "lastRequestTime" or something.
3. In the refresher listener, check to see if the current time is 30 minutes later than lastRequestTime.
3.a. If so, invalidate the session (can't do it in onRequestStart due to this issue).
3.b. If not, discard the previous "lastRequestTime" because it wasn't user-initiated.
In other words, I manually track calls from the client and try to ignore the ones from the refresher. Because I have to invalidate the session in the refresher listener, it does mean that the timeout can happen X seconds later than I want, where X is the refresh period, but that's not a big deal.
What I'm seeing now is that some components in our app are making calls back to the server even though there was no user action. I log the calls to request start/end methods, refresher listener, etc, and see start/refresh/end, which is great. But after doing some work in the app and populating some tables, I see something like: start/refresh/end followed by start/end (or multiple start/end pairs) that are not calls to the refresher listener.
They always happen after the refresher call. Something is telling a widget to make another call back to the server after the refresh, and that's circumventing my session timeout code. Can anyone tell me how to figure out what's going on here?
I've watched the on-the-wire traffic, grabbed what I thought was the PID of the component making the request, and saw that it was a table by drilling down in the Vaadin browser-side debugger. But what would make the table do this? I'd really like to shut that off if I can, or at least ignore the calls when dealing with session timing. How can I determine the source of a request from within my application?
I thought I could do this by debugging the changeVariables() method in AbstractCommunicationManager, but I have to run this app remotely and debugging that way is almost impossible. Even if I determine that it's component X or Y in the debugger, how do I recognize that same request/component in my app so I can ignore the request in terms of timing?
I know it's a lot of info, but I've been at it for a couple days and feel like someone else must have had a similar need to check the source of a request at the app layer.
p.s. I suppose if I can't figure this out correctly, I can ignore refresher requests and any request that comes in within 1 second or so of the refresher request end, but that's a bit hacky and there's always some chance that a user will time out due to bad timing.
The easiest way of checking who sends what from the browser to the server is by using Vaadin's debug console that is opened if you add ?debug to the end of the URL. Please note that this wil not work if productionMode is enabled in your web.xml.
Once you find out which component it is that sends the request, you'd have to figure out why it does this. Given what component class it is that sends the message and the labels in the sent data, it should be reasonably easy to figure out what's going on.
Leif Åstrand: The easiest way of checking who sends what from the browser to the server is by using Vaadin's debug console...
Wow, that is soooo much easier than watching it on the wire (and I didn't have to turn off ssl). Thanks for this -- I use the debugger constantly for checking layouts and such, but somehow never noticed that it was showing me the request UIDL.
Ok, so I see my refresher ("mentos") make its call:
Variable burst to be sent to server: PID_Smentos (class com.github.wolfie.refresher.client.ui.VRefresher) : r (i) : 0 Making UIDL Request with params: 967fe2d7-bc28-4afc-b4f9-b0e6149cbac10PID_Smentosri Server visit took 83ms JSON parsing took 0ms
Then there's a large tree of variable changes, and immediately my table ("eventsTableYo") makes this call:
Variable burst to be sent to server: PID_SeventsTableYo (class com.vaadin.terminal.gwt.client.ui.VScrollTable) : firstToBeRendered (i) : 0 lastToBeRendered (i) : 49 firstvisible (i) : 0 reqfirstrow (i) : 22 reqrows (i) : 28 Making UIDL Request with params: 967fe2d7-bc28-4afc-b4f9-b0e6149cbac10PID_SeventsTableYofirstToBeRenderedi49PID_SeventsTableYolastToBeRenderedi0PID_SeventsTableYofirstvisiblei22PID_SeventsTableYoreqfirstrowi28PID_SeventsTableYoreqrowsi Server visit took 75ms JSON parsing took 1ms
Any ideas what would make the client-side table make this call? During the initial refresher call, the data in the table is refreshed. My guess is that the table gets repainted, sees how many rows are visible or something, and then makes a new call back to get the data for those rows. Something like that. Maybe we're doing something wrong in the way we're updating the table; any suggestions would be appreciated.
For all I know this is the way it's supposed to work, in which case I'll see if there's a listener I can add to the table to ignore these requests (in terms of timing).
That's the output that the table gives when you scroll and the lazy loading kicks in. It basically says that the table is scrolled all the way to the top (=so no extra scroll done) and that it requests for rows 22-50 (start 22, and 28 forward from there).
Why it tries to load extra data at that point is not clear to me. If I remember correctly, the table did some trick where it gets only a few rows in the initial rendering, and then it asks for more directly after the rendering. MIght be that I remember this wrong, but it looks like what it does as the table isn't scrolled at all and only has 21 rows in it before it. How many rows are visible at once in your table?
You could, just for trying it out, try to disable lazy loading to see if that extra event goes away. It think it was done with table.setPageLength(0);
Jens Jansson: You could, just for trying it out, try to disable lazy loading to see if that extra event goes away. It think it was done with table.setPageLength(0);
Thanks for the idea, and the interpretation of the request about what the table is doing. I'll try this with a sample app and see if that helps, but then I'm worried about what effect it might end up having on the UI. My hack of ignoring the time of client requests right after a refresh mostly works, but now that it's in production I see some users with slower browsers and/or connections that throw it off. Now that I'm pretty sure it's just our tables making these calls, I'm going to see if I can find the right listener type to isolate these requests when they come in and ignore them.
At the worst, a user doing nothing but scrolling a table up and down will have his session timeout. There are worse things that can happen....
To be fullproof, you could write a very simple custom component that pokes the server only on user action (mouse or key events on document?), or only at known points in time. The server would then listen only to events from this custom component, ignoring any others. The rest is the same: look at consecutive polls from your component, time out otherwise. This can transcend Vaadin - it can be a simple "pixel" call processed by a servlet, causing it to re-arm a timer that would invalidate the session.
Or, you could extend Refresher (its source code is readily available), including a piece of data that identifies it as a Refresher. Then you could ignore calls from the Refresher in this manner. You could then submit the patch to the main Refresher distro as a new capability of Refresher.
Mihai Danila: To be fullproof, you could write a very simple custom component that pokes the server only on user action (mouse or key events on document?), or only at known points in time. The server would then listen only to events from this custom component, ignoring any others.
I'm not understanding your suggestion. When a user clicks a button (an action I want to track in terms of session timing), how would the custom component come into play? Is there some way to wrap all the components I want in my app into some other call so I can track which ones are user-initiated?
If there were a simple way to know which requests involved a mouse-click instead of any other client action, that would work just fine. ...which now makes me wonder if I could simply listen for mouse click events and only extend the session when these happen. I hadn't thought about that before (and have no experience yet with mouse click events).
Mihai Danila: Or, you could extend Refresher (its source code is readily available), including a piece of data that identifies it as a Refresher. Then you could ignore calls from the Refresher in this manner. You could then submit the patch to the main Refresher distro as a new capability of Refresher.
This already exists in Refresher. See the first post in the thread: I know which calls are from the refresher because the refresher listener is called. The problem is that there are other non-user-initiated calls. For instance, after a refresh, a table may lazily load its data, initiating a call back to the server. Right now I just ignore these based on timing, but I could conceivably add a listener for each of these components to tell the app to ignore the timing of their requests. It's just not a robust solution.