<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Shilpa Gore</title>
    <description>The latest articles on Forem by Shilpa Gore (@mumbocoder).</description>
    <link>https://forem.com/mumbocoder</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3678069%2F48936d06-b706-415d-82fe-b8aa938eba39.jpg</url>
      <title>Forem: Shilpa Gore</title>
      <link>https://forem.com/mumbocoder</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mumbocoder"/>
    <language>en</language>
    <item>
      <title>(Mis-)Use Spring proxy magic to inject Http request into business layer - should you?</title>
      <dc:creator>Shilpa Gore</dc:creator>
      <pubDate>Sun, 01 Feb 2026 14:22:46 +0000</pubDate>
      <link>https://forem.com/mumbocoder/mis-use-spring-proxy-magic-to-inject-http-request-into-business-layer-should-you-4fgb</link>
      <guid>https://forem.com/mumbocoder/mis-use-spring-proxy-magic-to-inject-http-request-into-business-layer-should-you-4fgb</guid>
      <description>&lt;p&gt;A few weeks ago, while reviewing a Spring Boot codebase, I came across a service that injected HttpServletRequest as a field into a singleton bean. This bean is called from service layer to construct and publish domain events, where events needed information from the incoming request. The code “worked,” and at first glance even looked convenient and served the purpose. But the deeper I looked, the more uneasy I felt. A request-scoped concern was quietly living inside a singleton bean, and a transport-layer abstraction had leaked straight into business logic. That small design choice opened the door to a larger conversation about how easily Spring’s magic can blur architectural boundaries if we’re not careful.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Component
public class EventFactory {
   @Autowired
   private HttpServletRequest request;

   public void prepareAndSendEvent(){
     OrderEvent ordEvent = new OrderEvent;
     ordEvent.sentClientIP(request.getRemoteAddr());
   } 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why does this feel off?&lt;/strong&gt;&lt;br&gt;
Any body familiar with the Spring bean's scope can easily tell that this is a singleton bean. Singleton beans are created and initialised only once, right during the startup phase. As the name suggests, the same object is used for serving every http request that comes in. On the other hand, HttpServletRequest is a request-scoped bean and a new object of it is instantiated for every incoming Http request. The natural question that needs to be answered is - how is request field variable initialised when during startup no http requests are expected? Will this even work without mixing up information between different Http requests? This where Spring magic steps in - Spring injects proxy as a placeholder for request-scoped beans. This is not a flaw, rather a powerful tool that Spring relies on to manage the request processing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bridging difference in scope&lt;/strong&gt;&lt;br&gt;
Spring during bean initialisation field realises that it cannot bind any object to request variable(in the code snipped above). But, it is familiar with HttpServletRequest being a request scoped variable - for managing lifecycle of a http request - whose current value is stored in the ThreadLocal(Scoped variable in future versions) until the thread created for the request processing is alive. Back to our code, Spring creates a proxy method and initialises the return value of that method to request variable. When the the business logic access value from request, the proxy method gets the actual value from the current HttpServletRequest. This is Spring's usual behaviour to deal with difference in scope of a bean and injected bean(s).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this is a smell?&lt;/strong&gt;&lt;br&gt;
Spring with its one request per thread execution model and different bean annotations such as "@Component", "@Service", "@Repository" makes the design a three layered architecture with stateless singleton beans encapsulating business logic a breeze. This separation of concerns in terms of controller layer where HttpRequests land and go no further, service layer which receives a DTO(Data Transfer Object) constructed out of Http Request body, Request header and Session Object. Service layer applies business logic and calls gateway layer/ repository layer further. In the same manner, the client responses end at gateway layer. DTO is created out of the received response for service layer, if needed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fetu3ojdodl1f768dbrcp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fetu3ojdodl1f768dbrcp.png" alt=" " width="800" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is the developer(s) responsibility to maintain and enforce the separation of concern in the application. But in this case, because Spring makes it possible to inject request scoped bean into a singleton bean through the mechanism of scoped proxies, it is tempting to (mis)use this magic. Since it works flawlessly many developers may argue for it. However, &lt;em&gt;&lt;strong&gt;the price that we pay is the silent degradation of clean code and compromise of layered architecture for very little convenience&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What problems can this cause?&lt;/strong&gt;&lt;br&gt;
Apart from the smells mentioned above this approach can pose challenges to maintainability and testing strategy of the application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Falls apart in asynchronous execution&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
The reason why the use of current http request in the method that prepares and sends the event works is that it is performed synchronously, in the same thread where the ThreadLocal created by Spring is available for real-time object resolution. It is not uncommon, that in the lifetime of an application - for speeding up response time - such a method comes to be executed asynchronously. In such a case, the code works but the ThreadLocal variable is not available as asynchronous execution is performed on a different thread outside of the current context. As a result the execution will be break with IllegalStateException.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Testing complexity increases&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Write unit tests for EventFactory gets complex because HttpServletRequest has to be mocked. Mocked HttpServletRequest is required to be mocked only while testing the controller beans in a Spring Boot application. With this approach, focus shifts from unit tests to mocking HttpServletRequest resulting in complex tests.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Recommended approach&lt;/strong&gt;&lt;br&gt;
The best approach to make information from HTTP request to be made available in business layers, is context extract and method injection. The required information is extracted into a DTO and send as a method parameter to the business layer beans.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@RestController
@RequestMapping("/orders")
public class OrderController {

    private final OrderService orderService;

    @GetMapping
    public List&amp;lt;OrderDto&amp;gt; getOrders(
            HttpServletRequest request,
            @RequestHeader("X-Tenant-Id") String tenantId) {

        String userAgent = request.getHeader("User-Agent");
        String clientIp = request.getRemoteAddr();

        RequestContext ctx = new RequestContext(tenantId, clientIp);

        return orderService.getOrders(ctx);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Component
public class EventFactory {
   public void prepareAndSendEvent(EventInfo eventInfo, RequestContext requestContext){
   // requestContext object has the needed information 
}

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;br&gt;
Injecting Request-Scoped HttpServletRequest into business layer works due to Spring magic, but it comes with a hidden cost and risk. It is the developer's responsibility to avoid using it when a cleaner alternative is available.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>springboot</category>
      <category>cleancode</category>
      <category>dependencyinversion</category>
    </item>
    <item>
      <title>Inheritance vs Abstraction in Java: Why Abstract Classes Exist?</title>
      <dc:creator>Shilpa Gore</dc:creator>
      <pubDate>Tue, 27 Jan 2026 09:09:27 +0000</pubDate>
      <link>https://forem.com/mumbocoder/inheritance-vs-abstraction-in-java-why-abstract-classes-exist-1ob3</link>
      <guid>https://forem.com/mumbocoder/inheritance-vs-abstraction-in-java-why-abstract-classes-exist-1ob3</guid>
      <description>&lt;p&gt;Encapsulation, polymorphism, inheritance, and abstraction form the foundation of object-oriented programming in Java. Encapsulation is usually easy to understand, but the lines between polymorphism, inheritance, and abstraction tend to blur—even for experienced developers. In this blog, we’ll revisit these concepts and unpack the subtle differences that are often the real source of confusion.&lt;/p&gt;

&lt;p&gt;Inheritance and abstraction are modelling tools that enable Java developers to design and simulate real-world entities as Java objects. This naturally brings us to the Object class in Java, which is implicitly inherited by every class—whether it’s user-defined or provided by the language itself, such as String. This implicit inheritance forms the foundation of Java’s type hierarchy and serves as the most fundamental example of inheritance in the language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Polymorphism&lt;/strong&gt;&lt;br&gt;
In real-world terms, refers to a single conceptual entity that exists in multiple concrete forms depending on context. A simple example is a bike: city bikes, gravel bikes, and mountain bikes are all bikes by design, yet each is built to function optimally in different terrain conditions with city bike being the most basic form of a bike. In Java, this kind of polymorphism is often modelled using inheritance—each variant satisfies the core characteristics of a (city)bike while providing specialised behaviour suited to its purpose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code reuse&lt;/strong&gt; through extension is an added advantage of inheritance. Continuing with the bike example, if a new type of bike designed for ferrying goods or young children needs to be introduced, a new LoadBike class can be created by inheriting all attributes of city bike with additional featues, such as the total load it can carry, while still reusing the common behavior of a bike.&lt;br&gt;
To stay within the scope we shall restrict ourselves to one way of achieving polymorphism in java. Yet, that is enough to make it clear that polymorphism is an outcome of modeling real-world entities, and inheritance is a powerful tool to achieve it in Java. With that foundation in place, it’s time to explore why abstract classes exist and what problems they are designed to solve.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcez9j7op4qur7hccuxy5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcez9j7op4qur7hccuxy5.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Abstraction in Java&lt;/strong&gt; &lt;br&gt;
Is realised through abstract classes and interfaces. At its core, abstraction defines behaviour and enforces contracts that can only be fulfilled by concrete objects. For this reason, neither abstract classes nor interfaces can be instantiated directly—they exist to describe what an object must do, not how it is created. Abstract classes enforce behaviour through shared implementation, while interfaces enforce expectations across class boundaries through contracts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Abstract class - a design choice&lt;/strong&gt;&lt;br&gt;
In our example, we could create a Bike class to model the concept of a bike and deliver common behaviour for city bikes, mountain bikes, gravel bikes, and load bikes. The shared implementation could be reused, overridden, or enforced through abstract methods- the choice is left  to the developer. By making the Bike class abstract, the developer prevents direct instantiation and can leverage polymorphism as a design pattern throughout the code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmk53ppuwtw9swlnq9cm4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmk53ppuwtw9swlnq9cm4.png" alt=" " width="800" height="481"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public abstract class Bike {

  private int yearOfMake;

  protected abstract maximumRpm();

  protected int setYearOfMake(int year) {
   this.yearOfMake = year;
  }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Need for interface&lt;/strong&gt;&lt;br&gt;
In Java, classes not only define attributes but also describe behaviour, giving them clear responsibilities. Objects of different classes work together to fulfil these responsibilities, modelling interactions in the real world. Interfaces in Java are a way to define and enforce the responsibilities of one class to another, without worrying about how each class achieves it. Built-in interfaces like Serialisable and Runnable are some interfaces that Java provides.&lt;/p&gt;

&lt;p&gt;TL;DR&lt;br&gt;
Inheritance is a means to realise polymorphism seen in real world objects. Abstraction is a definition and ability to impose it. Abstract classes are a design choice and  define behaviour. Interface enforce contracts and do not care about implementation.  &lt;/p&gt;

</description>
      <category>java</category>
      <category>oop</category>
    </item>
    <item>
      <title>OIDC UserInfo Endpoint explained for Backend Engineers</title>
      <dc:creator>Shilpa Gore</dc:creator>
      <pubDate>Mon, 12 Jan 2026 12:07:01 +0000</pubDate>
      <link>https://forem.com/mumbocoder/what-is-openid-connect-protocol--2d84</link>
      <guid>https://forem.com/mumbocoder/what-is-openid-connect-protocol--2d84</guid>
      <description>&lt;p&gt;&lt;strong&gt;OAuth 2.0&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OAuth2.0 is an industry standard that enables re-use of user resources across different unrelated entities(services) with the consent of the resource oner. This is made possible by the keeper of a user resource acting as a authorisation server which authorises the requesting entity to access resources of a user. The requesting entity receives a access token from authorisation server, which it has to present to resource server when requesting to read or edit a resource. Specification at &lt;a href="https://datatracker.ietf.org/doc/html/rfc6749" rel="noopener noreferrer"&gt;https://datatracker.ietf.org/doc/html/rfc6749&lt;/a&gt; is worth a perusal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OpenIdConnect&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OpenIDConnect protocol is built on top on OAuth2 framework and provides a REST API to fetch the profile information of a user. It has been detailed in &lt;a href="https://openid.net/specs/openid-connect-core-1_0.html" rel="noopener noreferrer"&gt;https://openid.net/specs/openid-connect-core-1_0.html&lt;/a&gt;. The picture below illustrates the steps to retrieve user profile information from resource owner through OpenId Provider. Providing a BFF is of course an implementation decision and not mandated by specification. In Step &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwe24l6otwl6nyrbri410.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwe24l6otwl6nyrbri410.png" alt=" " width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;ID Token&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Is a JWT token that conveys to the relying party that the user was successfully authenticated and the duration for which it is valid. It does provide the user data as claims but does not guarantee the freshness of data. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;/userinfo endpoint&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Is used by relying party to fetch user information by presenting the access token that was issued by OpenId provider. It enables the  relying entity to retrieve user's profile in a REST style, without requiring the user to share sensitive information such as password etc. The specification supports GET or POST /userinfo endpoint. The access token could be a JWT or an opaque token. If the token is valid(more on this later)the user profile information then shall be provided as claims in the response. It is always upto the BFF/Resource server to provide the request information. In case it choses not to provide or information is missing the claims is simply excluded from the response. An example of GET request and returned response is shown below:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /userinfo HTTP/1.1 Host: server.example.com  Authorization: Bearer SlAV32hkKG

HTTP/1.1 200 OK
Content-Type: application/json
{
  "sub": "23642801",
  "name": "Herr Jane Doe",
  "email": "janedoe@example.com",
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Access Token&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Access tokens may be issued in either JWT or opaque form, depending on the authorization server’s configuration. When an access token is a JWT, the resource server can validate it locally by verifying its signature and required claims (such as iss, aud, and expiration). If the token is valid and contains the necessary claims, the resource server may use those claims to authorize the request and return the protected resource.&lt;/p&gt;

&lt;p&gt;When an access token is opaque, the resource server cannot validate it independently. Instead, it must call the token introspection endpoint of the authorization server that issued the token to determine its validity and associated metadata. Once validated, the resource server can authorize the request and return the appropriate protected resource to the relying party.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scope vs Claims&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OAUTH2 is a Role Based Access Control(RBAC). Normally, Roles are associated with users such as Admin, Developer etc. However, in case of OpenId Connect the relying party requests the permission to read on behalf of the user. Hence, in order to keep the difference the use of Scopes to request claims was adopted. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security pitfalls and how to navigate them&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Some mistakes in implementation could lead to OpenId Connect flow being exploited. It is better to be aware of such scenarios and prevent them altogether.&lt;/p&gt;

&lt;p&gt;At the BFF / Resource Server:&lt;br&gt;
Failing to ensure that the presented token is a valid access token issued for that resource server (e.g., by not validating aud, token usage, or issuer) can allow an attacker to replay a stolen ID token against the API. This may result in unauthorized access to user profile or protected resources.&lt;/p&gt;

&lt;p&gt;At the Relying Party:&lt;br&gt;
Failing to verify that the sub claim returned by the /userinfo endpoint matches the sub claim in the ID token can lead to identity substitution attacks, where profile information belonging to a different user is incorrectly associated with the authenticated session.&lt;/p&gt;

&lt;p&gt;What next?&lt;br&gt;
In this blog -[&lt;a href="https://dev.to/mumbocoder/build-userinfo-endpoint-using-spring-32n4-temp-slug-5567840?preview=fe467a0664e4e9c2cd3bd79acaa9c2242297369b7599c2087fc997ea5f1992890d02468f1aec988c42a9bb8f3ab72edf02e2d25c3fff23f7e069cf44"&gt;https://dev.to/mumbocoder/build-userinfo-endpoint-using-spring-32n4-temp-slug-5567840?preview=fe467a0664e4e9c2cd3bd79acaa9c2242297369b7599c2087fc997ea5f1992890d02468f1aec988c42a9bb8f3ab72edf02e2d25c3fff23f7e069cf44&lt;/a&gt;], we shall implement /userinfo endpoint in a Spring Boot application. &lt;/p&gt;

</description>
      <category>oauth</category>
      <category>openidconnect</category>
      <category>spring</category>
      <category>authentication</category>
    </item>
    <item>
      <title>Stateful REST in Spring (Part 1): HTTP Sessions and their Limitations</title>
      <dc:creator>Shilpa Gore</dc:creator>
      <pubDate>Thu, 08 Jan 2026 14:57:57 +0000</pubDate>
      <link>https://forem.com/mumbocoder/building-stateful-distributed-http-applications-with-spring-84l</link>
      <guid>https://forem.com/mumbocoder/building-stateful-distributed-http-applications-with-spring-84l</guid>
      <description>&lt;p&gt;HTTP communication is stateless by design, meaning no context is automatically carried from one request to the next. This property aligns well with Spring’s request-processing model, where each HTTP request is handled independently by a thread from the server’s thread pool. However, there are scenarios where RESTful services must retain context across multiple HTTP requests. Common examples include preserving the contents of a shopping cart across user interactions or maintaining user-specific context in agentic AI applications to deliver personalized responses.&lt;/p&gt;

&lt;p&gt;To address this requirement, servlet containers such as Tomcat or Jetty provide the concept of an HttpSession. An HTTP session allows state to be associated with a client and reused across subsequent requests, enabling applications to introduce stateful behavior on top of an otherwise stateless protocol.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is HTTP session?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;HTTP sessions (also referred to as a Servlet sessions) are managed by the servlet container and therefore container-specific. A session is typically created when the application explicitly requests it—either by calling HttpServletRequest.getSession() or by accessing a session-scoped attribute during request processing. The session is identified by a unique session identifier, commonly named JSESSIONID. This identifier is sent to the client as part of the HTTP response, usually via a cookie, and is included in subsequent requests so the container can associate those requests with the same session.&lt;/p&gt;

&lt;p&gt;An HTTP session typically contains the following information:&lt;/p&gt;

&lt;p&gt;Session ID&lt;br&gt;
A unique identifier for the session, commonly represented by JSESSIONID.&lt;/p&gt;

&lt;p&gt;Attribute map&lt;br&gt;
A key–value store used to associate state with the session. Keys are strings, and values are arbitrary Java objects—for example, a shopping cart, authenticated user information, or personalization context.&lt;/p&gt;

&lt;p&gt;Session metadata&lt;br&gt;
Information such as session creation time, last accessed time, maximum inactive interval, and session validity (active or expired).&lt;/p&gt;

&lt;p&gt;The created session is maintained by server by using cookies, among other possible ways. Although HTTP sessions enable applications to introduce stateful behaviour, the default servlet container implementation stores session data in-memory. As a result, subsequent requests carrying the same JSESSIONID must be routed to the same server instance to preserve session continuity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8h38ycge3sjsnnz5v4e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8h38ycge3sjsnnz5v4e.png" alt=" " width="531" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This model becomes a serious limitation in modern distributed systems, where multiple application instances run behind a load balancer and restarts, redeployments, and scaling events occur frequently. Any deviation in request routing or instance availability can lead to session loss, inconsistent user experience, or forced re-authentication. While it is possible to configure load balancer say, F5 to create sticky sessions where subsequent requests are routed back to same server instance that created the session in the first place. For obvious reasons this is not a clean and scalable solution. This is where Spring Session can be leveraged to provide resilient and scalable session management for Spring-based REST services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spring Session&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Spring Session is an abstraction that externalises HTTP session management from the servlet container. It integrates with the web request lifecycle by intercepting incoming HTTP requests and delegating session handling to a Spring-managed SessionRepository instead of relying on the container’s in-memory implementation.&lt;/p&gt;

&lt;p&gt;While the session identifier is still exchanged with the client, Spring Session manages it independently of the servlet container. By default, the session data can be persisted in an external store such as Redis, a relational database, or another supported backend. This enables session sharing across multiple application instances and eliminates the need for sticky sessions, allowing requests to be freely routed by the load balancer.&lt;/p&gt;

&lt;p&gt;In the next blog we shall explore spring session in detail.&lt;/p&gt;

</description>
      <category>stateful</category>
      <category>architecture</category>
      <category>backend</category>
      <category>spring</category>
    </item>
  </channel>
</rss>
