I'm using Vaadin Flow (14.1.18) and my question is a very bizarre behavior I've faced.
I have added the following configs into my Spring Boot project's application.properties file.
// Expected behavior: Vaadin Client to send heartbeat to the server every second
vaadin.heartbeatInterval=1
// Expected Behavior: Vaadin Server to close Idle sessions after 3 seconds (3 rounds of failed heart beats)
vaadin.closeIdleSessions=true
I have checked these configs to be applied practically on runtime using below code
DeploymentConfiguration deployConf = VaadinSession.getCurrent().getConfiguration();
int hbi =deployConf.getHeartbeatInterval();
boolean killIdle = deployConf.isCloseIdleSessions();
logger.info("Deployment Config >> KillIdleSessions : {} -- HeartBeatInterval : {}", killIdle, hbi);
And I get the following result which shows my configs got applied
2020-03-05 23:16:01.015 INFO 19224 --- [nio-9200-exec-3]
com.package.sandbox.MainView : Deployment Config >> KillIdleSessions :
true -- HeartBeatInterval : 1
But, the problem is, during the runtime, it seems Vaadin is ignoring all these configs, and despite I close the browser (UI instance won't be there anymore to send heartbeats) the session stays open indefinitely and never get closed (or destroyed, in Vaadin's perspective).
The heartbeats are used to close other UIs in the session, it won't help in closing the last UI.
When the VaadinService has finished handling a request, it calls VaadinService#cleanupSession. This loops through all UIs in the session, and checks if the time passed since the last heartbeat is longer than three heartbeat intervals, in which case the UI is closed. The point of this is to clean up inactive UIs in the session, such as from closed tabs or refreshed windows.
When you close the last tab, the server will not receive any more requests for that session. As the cleanup code is run at the end of a request, it will not be triggered anymore. This prevents your last UI from being closed.
Instead, the session timeout comes into play. You can configure it with server.servlet.session.timeout, e.g. 120s or 2m. The embedded Tomcat has a reaper thread that is run once every minute, and it will close any inactive sessions. Note that with Spring, the minimum value for the session timeout is one minute.
If you leave a UI open but idle, the heartbeats will keep the session active, and prevent the session timeout handler form closing it. This is where closeIdleSessions comes into play. If it is set to true, after a request ends, Vaadin will check the last timestamp of a non-heartbeat request, and if the session timeout is exceeded, it will be closed by Vaadin.
So, in short
heartbeatInterval controls how quickly other inactive UIs in a session are closed, but does not affect the last UI.
closeIdleSessions controls whether or not heartbeats should prevent a session timing out for an otherwise idle UI.
Note: After changing values in application.properties, you might need an incognito window to test your changes, as the last session might've been serialized and re-used after a restart.
Related
Here I wanted to register to 2 endpoints and send requests to them. You can see this in the code below. I name one env1 and the other env2.
val client = Http.client
.configured(Transport.Options(noDelay = false, reuseAddr = false))
.newService("gexampleapi-env1.localhost.net:8081,gexampleapi-env2.localhost.net:8081")
So far everything is normal. But env1 instance had to be down for some reason(for a few hours' maintenance etc. not sure why.). Under normal circumstances, our expectation is that it continues to send requests through the env2 instance. But this didn't happen. Could not send requests to both servers. Normally it was working correctly, but it didn't work that day for a reason we don't know.
Since the event took place months ago, I only have the following log.
2022-02-15 12:09:40,181 [finagle/netty4-1-3] INFO com.twitter.finagle
FailureAccrualFactory marking connection to "gExampleAPI" as dead.
Remote Address:
Inet(gexampleapi-env1.localhost.net/10.0.0.1:8081,Map())
To solve the problem, we removed gexampleapi-env1.localhost.net:8081 host from the config file. and after restarting it continued to process requests. If you have any ideas about why we may have experienced this problem and how to avoid this next time, I would appreciate it if you could share them.
Our Java 8 and Spring-based application is generating bulk reports (PDF files) in the background. This might take more than one to two hours. The progress as a percentage value has been updated in the UI (front end) after generating each report, so the UI is active till completing the reports generation, but for some reason we're getting Session Expired messages in the UI from Vaadin framework in the middle of the report generation process.
Vaadin framework version : 7.6.2
Web Server : Tomcat 7
Value for heartbeat duration : default value (no explicit value configured)
Value for session timeout duration in web.xml : 30 min by default
No change for the value for closeIdleSessions (By default closeIdleSessions=false)
Can anyone please help to find the reason?
If the only activity is through pushing out status updates through the #Push websocket, then that might not be enough to postpone session expiration on the servlet level.
You could work around this by ensuring there is a normal request from the client every now and then just to reset the session timeout. This can be done by enabling UI polling with a long interval, e.g. ui.setPollInterval((int) Duration.ofMinutes(25).toMillis());.
Remember to disable the polling after the long task is done, or it will continue to keep your session alive.
I'm upgrading our application to MQ7 (7.5.0.5) and I'm seeing some odd behavior in a small test application that I have written.
My application uses Springs CachingConnectionFactory and is configured to use only one thread.
I can see that by debugging through the code 2 tcp connections are created, one for the initial connection and one for the JMS session. Every 60 seconds, the 2 tcp connections that are used by my message sink are broken and replaced with 2 new connections.
The following error is present in the error logs on the queue manager.
05/16/2016 09:38:26 AM - Process(1609.14) User(mqm) Program(amqrmppa)
Host(xxxxxxxxx) Installation(Installation1)
VRMF(7.5.0.2) QMgr(xxxxx)
AMQ9271: Channel 'XX.XXXX.X' timed out.
EXPLANATION:
A timeout occurred while waiting to receive from the other end of channel
'XX.XXX.X'. The address of the remote end of the connection was '57.4.4.145'.
ACTION:
The return code from the (recv) [TIMEOUT] 60 seconds call was 0 (X'0').
Record these values and tell the systems administrator.
I have the following settings on my channel: DISCINT(60), SHARECNV(1), the exceptions are linked to the DISCINT time, changing that changes the frequency of the exceptions, also the
exceptions disappear with a SHARECNV value >1
Can anyone tell my why the connections are broken even when the channel is active and messages are being sent and received?
Thanks!
This sounds like APAR IV62728 which describes the symptoms you're seeing:
http://www-01.ibm.com/support/docview.wss?rs=171&uid=swg1IV62728
Fixed in 7.5.0.6. Try upgrading to that level and see if it solves the problem.
I managed to find a solution to this issue. When using the CachingConnectionFactory with an underlying IBM connection factory, an initial connection is created in a stopped state. That connection in then used to create JMSSessions.
The issue was that the initial common connection was timing out.
I managed to keep the connection active by adjusting the HBINT value to 5. It appears that a number of heatbeats are required to keep the connection open and my initial value of 20 was too high.
I have been handling a application which uses wicket+JPA+springs technologies.Recently we got many 5XX error in logs(greater than threshhold).During that time,There were some general problems due to unstable response times of the mainframe db2 which is backend for our application.
But after that once the mainframe is OK this application servers did not come to normal again.
There are a lot of hanging transactions (from my appplication).
There are many threads in the server that may be hung.
As users will go on keeping login or will access the links in aplication during that time the situation becomes worse.
When I look at webspehere logs I found following exceptions:
00000035 ThreadMonitor W WSVR0605W: Thread "WebContainer : 88" (000005ac)
has been active for 637111 milliseconds and may be hung.
There is/are 43 thread(s) in total in the server that may be hung.
In application logs i found following exceptions:
-->CouldNotLockPageException: Could not lock page 4. Attempt lasted 3 minutes
-->DefaultExceptionMapper - Connection lost, give up responding.
org.apache.wicket.protocol.http.servlet.ResponseIOException:
com.ibm.wsspi.webcontainer.ClosedConnectionException: OutputStream encountered error during
write.
--> JDBCExceptionReporter - [jcc][t4][2030][11211][3.67.27] A communication error occurred
during operations on the connection's underlying socket, socket input stream,
or socket output stream.
Error location: Reply.fill() - socketInputStream.read (-1). Message:
Connection reset. ERRORCODE=-4499, SQLSTATE=08001DSRA0010E: SQL State = 08001, Error Code = - 4.499
Now we are working on the solutions to this problem.The follwing are two solutions that we are thinking as of now.
1.I have gone through many forums and found that whenever we get CouldNotLockPageException then it would be better to invaidate the session and force user to login page.Currently We do not have session invalidation (logout) mechanism.So we will implement that one.
2.We need to implement transaction timeouts so that we can stop hanging transactions.
I need solution for this problem from java or server side.Here we are using wicket,jpa and springs frameworks.I have few queries.
1.How can we implement transaction timeouts in the above frameworks?
2.Will invalidating session can stop hanging transaction or threads that may hung?
Since you are already using Spring, it's as simple as that:
#Transactional(timeout = 300)
The Transaction annotation allow you to supply a timeout value(in seconds) and the transaction manager will forward it to the JTA transaction manager or your Data Source connection pool. It works nice with Bitronix Transaction Manager, which automatically picks it up.
You also need to make sure the java.sql.Conenction are always being closed and Transaction are always committed (when all operations succeeded) or rollbacked on failure.
Invalidating the user http session has nothing to do with jdbc connections. Your jdbc connection should always be committed/rollbacked and closed(which in case on connection pooling, will release the connection to the pool).
And make sure the max pool size is not greater than tour db max concurrent connections setting.
I am working on a website using Java Servlets and my research showed me that it is best to keep one database connection per user (rather than have only one connection sitting all the time on the background or connect to the database every time that a transaction needs to be made). I don't know how to accomplish this, however. What I am currently doing is in my Data Access Object class I have a
private static Connection conn;
and I have a HTTPSessionListener - on sessionCreated event I connect to the Database using this static "conn" variable, and on sessionDestroyed event I disconnect the "conn" variable:
...in my "MySessionListener"...
public void sessionCreated(HttpSessionEvent sessionEvent) {
System.out.println("Session created!");
DAO.connect();
}
public void sessionDestroyed(HttpSessionEvent sessionEvent)
{
System.out.println("Session destroyed");
String user = (String) sessionEvent.getSession().getAttribute("userid" );
if (user != null) DAO.signUserOut(user);
DAO.disconnect();
}
Now the problem with this is that:
I am afraid that this way I essentially degrade to only having one connection that everyone shares(instead of a connection per user as I wanted), just that I disconnect from time to time if there are no users. Correct?
If multiple users are online and one closes their session, they will close the connection for everyone until someone else starts a session and creates a new connection for everyone, correct? I cannot test this very well because I am testing it locally on my laptop, with 3 browsers, but even when I close a browser that had my website on, the session doesn't die immediately and I am not sure what exactly is going on. All i know is that sometimes I get an exception saying "No transactions allowed after connection is closed".
Typically this is achieved using connection pool. You can configure it to have specific number of connections available and the pool manages open and closing connections. Your code will only take available connection from the pool and return it when done.
See this (fairly generic) Wikipedia article.
Some well known pools are DBCP and C3P0.
There ate two issues here:
http session timeout
database session connectivity
You seem to be mixing the two session concepts.
HTTP session
You need to further familiarize yourself with client-server http mechanism. Closing the browser does not close the http session. When you close the browser, you have to code into your pages "on close". "On close"?? Absolutely not - there is no such thing as onclose in html/javascript. But there is onunload (as well as onload).
Why isn't there "onclose" in javascript/html? I think the people who invented http/html were paranoid over many contingencies. Perhaps, rightly so. Perhaps, we have to understand the mindset and motivation of html/http invention. So, you have no choice but concoct a chain-reaction of onunload events. ONUNLOAD/ONLOAD are html page events, not browser events. The whole html mechanism is page driven not browser driven. Therefore, when you close the browser, it would trigger onunload event for every tab on the browser.
You will have to make use of page onunload to inform the server that the user has intention to close the session. Otherwise, the server would have to depend on session timeout value to end the session. What if the user closes the browser on one of your pages on which you did not code in the onunload event? Too bad - that is why I wrote "concoct a chain reaction of onunload" on every page. Which is very tiresome and bothersome.
Sometimes. especially for highly mathematical servlets, the server takes a long time to respond. Then the client page would need an indication to differentiate between a server still processing a response vs the server has gone dead - session timeout enforced on the browser. e.g. http://support.microsoft.com/kb/813827 (How to change the default keep-alive time-out value in Internet Explorer).
May be, the server should poke at the browser page once a while to see if the browser session is still alive. Nope. Http is client pull technology. The server cannot push responses to the client. Why not? Why so silly? You have to read up on the whole http/html mindset/paranoia to understand. The browser can poke at the server but not vice versa.
Therefore AJAX and comet was invented/concocted. To simulate, to pretend on server push. With ajax you have some means for the server to psuedo-poke at the client. And that is what you have to do -- use ajax e.g. jquery or gwt. I prefer gwt.
What if the client computer had a power failure or the OS hit a blue screen, or the browser process was abruptly terminated? There would be no opportunity to trigger the onunload event for any of the pages.
Database connection session
Alex's answer hit the nail -- connection pooling. However, there are situations when I needed to have a database connection per session. Hmmm ... how do I do it? Yes, I store the connection as the session attribute. Therefore, there would be as many db connections as there are sessions. Which, essentially has the same effect as what you are currently doing.
Developing stateful web applications for a stateless(despite the cookies) and presumed unstable client requires cautiousness. What if the user presses the back button after logging out? The backed/prev page might contain an action that causes the server to use a db connection, which was already closed by the log-out page before the user pressed the back button. Or, it may be the server timed out due to client not having poked at the server for a duration longer than the session keep-alive timeout value.
Therefore, before developing a "multi-tier" client-server app, you have to sit down and chart out all your contingencies, with a good understanding of the mindset/paranoia of http technology. You need to infect yourself with http's compulsive obsessions in order to design your applications.