Spring boot + Vaadin Flow + Spring session (REDIS) + Spring Security. Sessi

Hi all, Im trying to integrate spring session with Vaadin flow, but its seems it’s not working properly, when I login, my home page is refreshing continously, and the console is giving me the error I have attached. My maven dependencies for spring session are:

spring-session-data-redis

lettuce-core

spring-session-redis

I will aprecciatte any kind of help ! THANKS

17277286.png

Hi, are you able to share a minimal running project so I can reproduce the issue locally?

I experienced the exact same problem as you and when I looked at the forum, the first post was my problem.

When the spring-session-data-redis is present in the project. The page reload continuously and have the response didn’t contain a server id.

@Alejandro Duarte:

I read your article about HA Microservices: https://vaadin.com/blog/microservices-high-availability

But I found those issues in github:
https://github.com/vaadin/spring/issues/340
https://github.com/vaadin/framework/pull/9189

Can you confirm that it is possible to have session replication or the session in Vaadin is not compatible with that ?

Hi Alejandro, of course.

Download the vaadin bakery starter project https://vaadin.com/start/latest/full-stack-spring

Add the following dependencies to the pom.xml to use spring sessions:

<dependency>
	<groupId>org.springframework.session</groupId>
	<artifactId>spring-session-data-redis</artifactId>
</dependency>
	
<dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
    <version>5.0.5.RELEASE</version>
</dependency>

And finally configure the application.properties with these lines:

spring.session.store-type=redis
spring.redis.host= #my redis server ip
spring.redis.port=6379

When I login, the main page of the application is continuously refreshing giving me the following lines in the browser console:

Navega a http://localhost:8080/login
Setting heartbeat interval to 300sec. client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Scheduling heartbeat in 300 seconds client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:196:18
Starting application ROOT-2521314 client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Vaadin application servlet version: 1.0.5 client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Handling message from server client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:976:565
Handling dependencies client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:923:37
StateTree after applying changes: client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:941:114
Object { pushConfiguration: {…}, elementData: {…}, clientDelegateHandlers: [], polymerServerEventHandlers: []
, synchronizedPropertyEvents: [], virtualChildrenList: []
, elementChildren: (1) […]
, classList: [] }
client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
handleUIDLMessage: 16 ms client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
First response processed 2886 ms after fetchStart client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
 Processing time was 503ms client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Sending xhr message to server: {"csrfToken":"e93f7e75-ef36-471a-99c6-4f6fa2cc7a82","rpc":[{"type":"event","node":41,"event":"opened-changed"},{"type":"publishedEventHandler","node":33,"templateEventMethodName":"setDetailsVisible","templateEventMethodArgs":[null]
},{"type":"publishedEventHandler","node":33,"templateEventMethodName":"sortersChanged","templateEventMethodArgs":[[]
]},{"type":"publishedEventHandler","node":33,"templateEventMethodName":"confirmUpdate","templateEventMethodArgs":[0]
}],"syncId":0,"clientId":0} client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Server visit took 309ms client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
JSON parsing took 0ms client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Received xhr message: for(;;);[{"meta":{"sessionExpired":true}}]
 client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Response didn't contain a server id. Please verify that the server is up-to-date and that the response data has not been modified in transmission. client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:961:114
Handling message from server client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:976:565
Handling dependencies client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:923:37
handleUIDLMessage: 0 ms client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Navega a http://localhost:8080/
Setting heartbeat interval to -1sec. client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Disabling heartbeat client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:815:99
 Processing time was 5ms client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Setting heartbeat interval to 300sec. client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Scheduling heartbeat in 300 seconds client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:196:18
Starting application ROOT-2521314 client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Vaadin application servlet version: 1.0.5 client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Handling message from server client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:976:565
Handling dependencies client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:923:37
StateTree after applying changes: client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:941:114
Object { pushConfiguration: {…}, elementData: {…}, clientDelegateHandlers: [], polymerServerEventHandlers: []
, synchronizedPropertyEvents: [], virtualChildrenList: []
, elementChildren: (1) […]
, classList: [] }
client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
handleUIDLMessage: 16 ms client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
First response processed 2766 ms after fetchStart client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
 Processing time was 512ms client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Sending xhr message to server: {"csrfToken":"e93f7e75-ef36-471a-99c6-4f6fa2cc7a82","rpc":[{"type":"event","node":41,"event":"opened-changed"},{"type":"publishedEventHandler","node":33,"templateEventMethodName":"setDetailsVisible","templateEventMethodArgs":[null]
},{"type":"publishedEventHandler","node":33,"templateEventMethodName":"sortersChanged","templateEventMethodArgs":[[]
]},{"type":"publishedEventHandler","node":33,"templateEventMethodName":"confirmUpdate","templateEventMethodArgs":[0]
}],"syncId":0,"clientId":0} client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Server visit took 307ms client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
JSON parsing took 0ms client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Received xhr message: for(;;);[{"meta":{"sessionExpired":true}}]
 client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Response didn't contain a server id. Please verify that the server is up-to-date and that the response data has not been modified in transmission. client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:961:114
Handling message from server client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:976:565
Handling dependencies client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:923:37
handleUIDLMessage: 0 ms client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Navega a http://localhost:8080/
Setting heartbeat interval to -1sec. client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Disabling heartbeat client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:815:99
 Processing time was 4ms client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18
Setting heartbeat interval to 300sec. client-D1AD34905AC1AA5B4DBECA8FB0306D92.cache.js:182:18

The session apparently is working, because when i restart my embedded Tomcat, the login page doesn’t appear and I can see in my redis-cli the logged user.

Following the instructions in your article https://vaadin.com/blog/microservices-high-availability Im getting exactly the same issue. Same console messages and same behaviour with page refreshing all the time.

Thanks.

@Alejandro Duarte, any update on this topic ? Is there any other solution to have a session control outside a Vaadin & Spring boot application?

Right now we are developing an application with spring boot (jar packaging) and we are using the blue and green philosophy with Nginx, do you guys know a session solution for this ?. Everytime we stop and start the service to make some updates, the user is kicked out from the application and Spring security is requesting again the user credentials.

Many thanks, best regards.

Alejandro Rioja.

@Alejandra R.
To avoid requesting user credentials again you can think about using the remember-me function of spring security or a central oauth server like keycloak. Thats how i avoid many user logins.
And the keycloak solution also works for different applications that use the same keycloak-realm.

But of course i am also looking for the spring-session compability. Otherwise dynamic pod-scaling in an environment with kubernetes is killing active user-sessions if the overall load is reducing and some pods are killed.

@Tobias Kahl, thank you for your response, unfortunately the “remember-me” function of spring security reload the page to re-authenticate after a server restart.
This means, that if for example the user is editing a form, it loses all the introduced information . We can not permit that,
do you know if there is a solution for that ?

Unfortunately we are thinking to discard Vaadin due to this problem, we can not assume that a user editing a form and after a server update, loses all the introduced information. It seems Vaadin is not prepared for a zero downtime ecosystem

Also it seems there is no solution to stop an infinite loop when a user close a browser tab. We need to monitor certain data until the user exits (and can close it directly pressiong the close tab button in the browser)

https://vaadin.com/forum/thread/17228199

Many thanks, best regads.

We are also stuck with this problem. We would like to employ Vaadin Flow in a horizontally scaling cloud environment, but it would be a deal-breaker for us if distributed sessions are not supported.

Will shared sessions with Redis and Spring session be supported? Is there any news about this topic?

I was able to get something working using sticky sessions and memcached-session-manager(Redis version) in async mode. This lib looks in memory for a session and use it, if not found it looks into Redis.

Nginx do the stickyness and will redirect to an another instance when the instance is shutdown.

But it’s not perfect:

  • When a server is shutdown, not all user are transferred to another node perfectly. Often, they lose their session and they need to refresh their browser. I assume using async mode of saving session didn’t complete before the node was shutdown. (Sync version was too slow)
  • Using K8S I had to set a PodDisruptionBudget to ensure that no reschedule are done otherwise user risk losing their session at anytime.
  • It’s difficult to keep everything serializable or using dependencies that contains only serializable class.

So with this setup, we can manage to have an horizontal scaling and not a lot of downtime, but no garantee that users will stay connected.

Maybee some peaple have idea how to improve this solution.

Alejandro R.:
@Alejandro Duarte, any update on this topic ? Is there any other solution to have a session control outside a Vaadin & Spring boot application?

Right now we are developing an application with spring boot (jar packaging) and we are using the blue and green philosophy with Nginx, do you guys know a session solution for this ?. Everytime we stop and start the service to make some updates, the user is kicked out from the application and Spring security is requesting again the user credentials.

Many thanks, best regards.

Alejandro Rioja.

Unfortunately, not. I don’t know the details of your implementation but keep in mind that Vaadin requires locking the session on each request and afaik solutions such as Redis don’t support this. So, using Spring Session with Redis might fail when you use the app in several tabs in the same browser for example.

See the discussion in this issue: https://github.com/vaadin/flow/issues/4746

If it’s not an option you should remove the article on your blog, because people think it’s possible : https://vaadin.com/blog/microservices-high-availability

Ml LL:
If it’s not an option you should remove the article on your blog, because people think it’s possible : https://vaadin.com/blog/microservices-high-availability

I should at least add a note clarifying that certain apps might fail when used in multiple browser tabs. It’s not the case of the example application developed in the series of articles, though. Also I didn’t use Redis there, but Hazelcast.

I am also getting the infinite loop. I am not using multiple tabs. Just like the OP stated, once I add the spring-session-data-redis dependency and configuration I get infinite loop reloading. I even tried adding the VaadinSessionRewriteFilter to the Spring context, but that didn’t fix this issue.

Any ideas on how this can be fixed? Its been a year since the original post.

J Martinez, please follow and up-vote this issue: https://github.com/vaadin/spring/issues/340

J Martinez:
I am also getting the infinite loop. I am not using multiple tabs. Just like the OP stated, once I add the spring-session-data-redis dependency and configuration I get infinite loop reloading. I even tried adding the VaadinSessionRewriteFilter to the Spring context, but that didn’t fix this issue.

Any ideas on how this can be fixed? Its been a year since the original post.

You should take a look at this blog post: https://vaadin.com/blog/session-replication-in-the-world-of-vaadin

This seems like a massive flaw in the vaadin framework. I recall reading an article where they tried to explain why they thought this was a better solution but I would argue that multi-nodal systems are the more prevalent architecture style for most development teams. Vaadin really is nearly useless with out either shared session support or just getting rid of that session lock altogether. It seems to me that it would be a better solution to let the lock be an optional configuration that could be added for people who can use sticky sessions.

Vaadin’s current server-side architecture is centered around the convenience that you get from having a consistent server-side representation of what is currently shown in the user’s browser. That convenience does of course also have its price in the form of increased server-side memory usage and the necessity of a synchronization mechanism to protect that state against concurrent modification.

Whether this is a worthwhile trade-off depends on which constraints are most important for any specific application.

On the other hand, we are also investigating alternative ways of building applications without sacrificing end-to-end type safety and convenient access to backend services. You can read more about that initiative at https://vaadin.com/labs/vaadin-connect.