Uniqueness of Session ID in a Distributed environment? - spring

We are using Spring Session (backed up with pivotal Gemfire) for our Spring Boot applications running in an Distributed environment.
In such a distributed environment,
does Spring Session ensure that a unique session id is used for new
sessions being created across different JVMs ?

Just reviewing old SO posts for Spring Session Pivotal GemFire support, so my apologies your question never got answered in a timely manner.
In a nutshell, Spring Session uses the UUID class to generate "unique" Session IDs. For instance, see here, or more generally, here.
NOTE: Spring Session Data Redis support uses/wraps the MapSession class to store Session state in Redis, by default.
There are appears to be a lot of discussion about the effectiveness, or rather uniqueness, of UUID across JVMs in a cluster. This one in particular, though dated, caught my attention as it originated from the Oracle Java community forums.
However, keep in mind that it is your application(s) use of Spring Session that ultimately determines whether Session IDs are unique; i.e. it is not dependent on the number of nodes in a GemFire cluster since individual GemFire nodes are not generating the Session ID (applications using Spring Session are).
Therefore, if only 1 application (probably not likely in the Microservices state of the world) is ever present with Spring Session in use, then the UUIDs are probabilistically guaranteed to be unique. Even then, based on references available, it seems highly unlikely that 2 or more "application" nodes employing Spring Session will ever generate IDs that collide (though, (almost?) anything is possible ;-).
Though, I suppose if it is of paramount concern/importance, following with the beautiful tradition of Spring, it would be a simple matter to extend the GemFireOperationsSessionRepository and override the createSession() method, calling the appropriate GemFireSession constructor to pass the desired Session ID in.
However, in all cases (GemFire, Redis, etc), the Session ID uniqueness problem is agnostic of underlying, backing data store.
Hope this helps...
Cheers!

Related

Why is Spring boot User Session stored in ThreadLocal a bad pratice?

I'm new to an ongoing project/company and this project is using ThreadLocal to store user session data. It's a Springboot project.
I already know that this is BAD design, but i'm trying to find documentation to explain then why this will probably fail badly when the number of users/requests grow.
Can someone help me with links that explain the relation of Threads and Spring Sessions or provide an explanation on how this is a design flaw?

XA support for Microservices

Scenario: I have multiple XA compliant databases fronted by different microservices which perform CRUD operations on them. I need to perform a 2 phase commit among these microservices. This means that I have a server running which makes API calls into these microservices to do some update, and these updates should be transactional.
We are planning to create a transaction manager to manage this.
Question: All the available solutions like Atomikos etc. mandate the different transactions to happen on the same server but in my case these happen in different microservices.
How can we provide transaction management in this case?
Ultimately we wanted to prepare transactions and then commit them in a different session as managed by our own transaction manager.
Is that possible?
It is definitely possible (you can do xa_prepare and xa_commit on separate sessions on most, if not all by now, resource managers) but indeed in the end you will end up writing essentially a Java EE (JTA) style transaction manager with transaction context propagation over REST or messaging or whatever communication mechanism you are using. This has been done eg in Rest-AT specification that Narayana/JBoss implemented and a few others.
Weblogic has an operator with a number of years on it now that takes it into the Kubernetes space and so XA/2PC can simply continue to be used there and Tuxedo will be putting out a product to achieve the same end (over Rest).
The saga pattern should also definitely be considered. It is not to be blindly accepted nor dismissed out of hand as a great pattern/fit in the microservices space. Use cases in transaction management, like any other area, continue to be more and more optimized and specialized and so the fact that it involves eventual consistency, compensation, etc. should not be non-starter in and of itself as it has a number of significant advantages as far as deployment models, scaling, and, to your point, the removal of XA distributed locks, etc. The best solution depends on the specific use case and it's requirements.
A number of the microservices frameworks, such as Narayana (WildFly/Quarkus/SpringBoot), Helidon, and even inside the Oracle DB itself, have Saga engines now. Full disclosure, I work at Oracle and am putting out a workshop on this very product in the next few weeks which will build on the existing "Simplifying Microservices with converged Oracle Database Workshop" which has a very basic choreography-based saga (as opposed to the orchestration-based products/engines I mentioned).
Very happy to talk more on this topic as I've spent the last 25 years writing transaction managers. :)
For the scenario described in the question, you should try using Oracle Transaction Manager for Microservices (MicroTx). It is a free product that comes with a transaction manager and client library for microservices written in Java and node.js. With this, you can create XA transactions involving multiple microservices.
Oracle MicroTx - https://www.oracle.com/database/transaction-manager-for-microservices
I don't think you mean a different Session exactly, but one Application tier level transaction where application components one different server are inside the transaction boundary.
The issue that you are facing is that those who created Microservices were not aware or experienced enough with information systems to understand these scenarios.
Microservices are essentially a false generalization and derivative of a stereotyping
Transactions and many other basic concepts that historically allow Enterprise information systems to exchange information globally without proprietary vendor locking are simply not part of the Microservices understanding.
So your question is really how do you retrofit the architecture concept to do normal day-to-day computer stuff.
In the end, if you keep solving those problems, you will be back to a Java EE application server. (Spring went through the same failings and just ended up wrapping and rebranding Java EE standard functions but with more obnoxious rhetoric)
My business logic on Glassfish can talk to the business login on WebLogic and the CICS tx on the mainframe, and everyone's databases and message queues all on different servers in one transaction. The XA spec lays out how to do this.

Spring session for session sharing(clustering) between servers

I'm trying to let two machines with the same base domain (subdomains differ) to share session.
spring-session-jdbc seems to be a solution I could use to achieve the goal.
When a user logs into server-a, session info is stored in SPRING_SESSION db.
What worries me is the fact that custom org.springframework.security.core.userdetails.UserDetails class is stored in that db as well.
When server-b tries to read session data from the db, it has to use the same custom subclass of the org.springframework.security.core.userdetails.UserDetails.
So I'm copying codes that relates to the UserDetails class from server-a to server-b.
I'm feeling a little awkward doing this, because server-a and server-b might want different UserDetails in general.
Is this really intended way of using spring-session-jdbc ?
Another question is, is it mandatory to use spring-security for both server-a and server-b?
Spring Session is meant to easily enable session clustering, i.e. have the multiple instances of the same app share the external session store therefore making it easier to scale your app.
For the problem you are trying to solve it might be a good idea to use an appropriate higher level protocol such as OAuth 2.0 and OpenID Connect and implement single sign-on without coupling you applications through the session store.
While the idea of sharing session store between different apps might seem convenient initially, such arrangement is usually very problematic, as you noted yourself with the UserDetails example.
In line with Vedran Pavic's answer it sounds like you should be using sso. That said there are instances where different code bases may want to share the same session such as in micro-service clusters. In this case you should simply put your UserDetails into a base jar/module that the other jar/module's are dependent upon. You can use a build automation tool to make this packaging easier to accomplish.
To answer your final question, if these two applications are regularly communicating with each other then I'd recommend either using spring security everywhere or nowhere.
Default mechanism to persist and load session is through the SecurityContextRepository (Spring Security) or SessionRepository (Spring Session).
If you use Redis for session sharing the repository implementation could be RedisSecurityContextRepository (spring-security-redis) or RedisIndexedSessionRepository (Spring Session).
The latter one for sure serialize UserDetails so you cannot share the session unless you use same Frameworks & user classes versions.
I would use custom SessionRepository and store shared user info in portable Json or XML, or whatever you like, not the Java object serialized ))

Scope confusion regarding session beans, proxies, and singletons in a Spring 3 managed JSF app

This seems like it's basic Spring 101 stuff, but I can't seem to find the correct way to do this. The situation is as follows; in my web app there is a single entry point which is a controller that handles users coming from an outside system. The transfer is just a POST request with a bunch of associated information pertaining to that user. Apon entry, I need to create a new User bean and load it with that users information. Additionally, when the user hits a view which triggers some service, I need for that service to be able to access the appropriate User bean instance.
The first way to do this that came to mind was to have a UserManager service which would create a new instance of User, fill it w/ data, and then register it in the Spring container with the username as the bean name. Then when a service is invoked, the service would do something like Factory.getBean(username) to find the appropriate User instance. The problem I see here is that I'm losing the link between the user & which User bean belongs to them. Additionally, I'd like to avoid having the user carry the bean around in the session if at all possible. Is this where I am supposed to be using Spring AOP & proxies?
What is the typical Spring pattern for solving this type of situation?
So it is now many weeks later (since asking this question), and consequently my knowledge level has been expanding exponentially, so I figured I might as well answer my question for anyone who might find it helpful (not to mention the question wasn't very clear to begin with).
The basic answer is: use proxies. Since a singleton is only instantiate 1 time, you cant inject another class which has a shorter lifespan, eg. session scope. For those requiring more information, checkout stateful vs stateless beans. More or less what I ended up doing is this... the services contain STATELESS code for manipulating data (think verbs; RegisterUserSvc, AddPartSvc, etc). The data which these services manipulate is stateful. For instance, each user has a own copy of their own data object, lets say TodoListBean, which is in a different state for each user.
So how does a service, AddTodoItemService for instance, manipulate this data? This is where the proxy comes into play. When instantiated, the AddTodoItemService gets injected with a proxy for the TodoListBean, instead of the actual object. That way when the service needs to access the TodoListBean the container will serve up the a TodoListBean out of the current users session, and therefore the service will be operating on the correct bean (based on which user invoked the service), instead of doing something silly like having numerous copies of the service included in each users session scope.

What are the advantages and disadvantages of the Session Façade Core J2EE Pattern?

What are the advantages and disadvantages of the Session Façade Core J2EE Pattern?
What are the assumptions behind it?
Are these assumptions valid in a particular environment?
Session Facade is a fantastic pattern - it is really a specific version of the Business Facade pattern. The idea is to tie up business functionality into discrete bundles - such as TransferMoney(), Withdraw(), Deposit()... So that your UI code is accessing things in terms of business operations instead of low level data access or other details that it shouldn't have to be concerned with.
Specifically with the Session Facade - you use a Session EJB to act as the business facade - which is nice cause then you can take advantage of all the J2EE services (authentication/authorization, transactions, etc)...
Hope that helps...
The main advantage of the Session Facade pattern is that you can divide up a J2EE application into logical groups by business functionality. A Session Facade will be called by a POJO from the UI (i.e. a Business Delegate), and have references to appropriate Data Access Objects. E.g. a PersonSessionFacade would be called by the PersonBusinessDelegate and then it could call the PersonDAO. The methods on the PersonSessionFacade will, at the very least, follow the CRUD pattern (Create, Retrieve, Update and Delete).
Typically, most Session Facades are implemented as stateless session EJBs. Or if you're in Spring land using AOP for transactions, you can create a service POJO that which can be all the join points for your transaction manager.
Another advantage of the SessionFacade pattern is that any J2EE developer with a modicum of experience will immediately understand you.
Disadvantages of the SessionFacade pattern: it assumes a specific enterprise architecture that is constrained by the limits of the J2EE 1.4 specification (see Rod Johnson's books for these criticisms). The most damaging disadvantage is that it is more complicated than necessary. In most enterprise web applications, you'll need a servlet container, and most of the stress in a web application will be at the tier that handles HttpRequests or database access. Consequently, it doesn't seem worthwhile to deploy the servlet container in a separate process space from the EJB container. I.e. remote calls to EJBs create more pain than gain.
Rod Johnson claims that the main reason you'd want to use a Session Facade is if you're doing container managed transactions - which aren't necessary with more modern frameworks (like Spring.)
He says that if you have business logic - put it in the POJO. (Which I agree with - I think its a more object-oriented approach - rather than implementing a session EJB.)
http://forum.springframework.org/showthread.php?t=18155
Happy to hear contrasting arguments.
It seems that whenever you talk about anything J2EE related - there are always a whole bunch of assumptions behind the scenes - which people assume one way or the other - which then leads to confusion. (I probably could have made the question clearer too.)
Assuming (a) we want to use container managed transactions in a strict sense through the EJB specification then
Session facades are a good idea - because they abstract away the low-level database transactions to be able to provide higher level application transaction management.
Assuming (b) that you mean the general architectural concept of the session façade - then
Decoupling services and consumers and providing a friendly interface over the top of this is a good idea. Computer science has solved lots of problems by 'adding an additional layer of indirection'.
Rod Johnson writes "SLSBs with remote interfaces provide a very good solution for distributed applications built over RMI. However, this is a minority requirement. Experience has shown that we don't want to use distributed architecture unless forced to by requirements. We can still service remote clients if necessary by implementing a remoting façade on top of a good co-located object model." (Johnson, R "J2EE Development without EJB" p119.)
Assuming (c) that you consider the EJB specification (and in particular the session façade component) to be a blight on the landscape of good design then:
Rod Johnson writes
"In general, there are not many reasons you would use a local SLSB at all in a Spring application, as Spring provides more capable declarative transaction management than EJB, and CMT is normally the main motivation for using local SLSBs. So you might not need th EJB layer at all. " http://forum.springframework.org/showthread.php?t=18155
In an environment where performance and scalability of the web server are the primary concerns - and cost is an issue - then the session facade architecture looks less attractive - it can be simpler to talk directly to the datbase (although this is more about tiering.)

Resources