Thursday, April 20, 2023

How to use Session attributes in Spring MVC? @SessionAttribute and @ModelAttribute Annotation Example Tutorial

Hello Java and Spring developer, if you are wondering how to use the session attribute in Spring MVC application, then you have come to the right place. In the past, I have shared how to build REST API using Spring and several other Spring tutorials like Spring Boot + React fullstack application, and in this article, I will share a couple of strategies to use session attributes in Spring MVC application. Using session attributes in Spring-MVC is a major concern in each web application as there is session management in most of the web applications right now. Because Spring MVC is such a sophisticated framework for web development, it comes with its own tools and API for working with sessions. 

This tutorial will explain some basic processing with the spring application to understand the session attributes in Spring MVC. So we will discuss different strategies used to handle the session attributes here.


Using the @SessionAttribute annotations in Spring MVC

Now, let's see how you can use the session attribute in a Spring MVC application:

1. Using a scoped proxy

Following dependencies are common in all these methods; we need to configure the pom.xml as below.

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>





2. Using the @SessionAttribute annotations

So let's have a look into @SessionAttribute annotation in Spring. We can declare the Student class in the @ModelAttribute and add the @SessionAttributes to handle the session for the controller as below.


@ModelAttribute("student")
public class Student {
    private Grade grade;

    public Student(Grade grade) {
        this.grade = grade;
    }
}



The Student class declared in the above is annotated with @ModelAttribute so that the Controller can find and identify it. 

@Controller
@RequestMapping("/studentsession")
@SessionAttributes("student")
public class StudentSessionController {
    //your methods in here.
}


So here, the controller will be informed to make the student class a session-scoped attribute. We can use the bean with a request to reference the @RequestMapping.

@GetMapping("/student")
public String requestStudents(
    Model model,
    @ModelAttribute("student") Student student) {
    return "studentsessions";
}


So in the post mapping method, this will be slightly different as we need to add the  RedirectAttributes call and addFlashAttribute before returning the RedirectView.

@PostMapping("/student")
public RedirectView create(
    @ModelAttribute Student student,
    @ModelAttribute("student") Student student,
    RedirectAttributes attributes) {
    return new RedirectView("/studentsessions/studentview.html");
}


To support the URL parameters in spring boot, these RedirectAttributes are used. Normally, any Model characteristics would only be available to the framework if they were included in the URL during a redirect.





3. Using a scoped proxy

Another example of creating session attributes in Spring MVC has the scoped proxies. In the below Student class, this is configured as a session-scoped @Bean that is backed up by the proxy.

The Spring Framework is responsible for creating the Student to inject as a dependency, as shown in the below code segment.

@Bean
@Scope(
    value = WebApplicationContext.SCOPE_SESSION,
    proxyMode = ScopedProxyMode.TARGET_CLASS)
public Student students() {
    return new Student(); //return the student class to inject as a dependency
}


After that, we need to declare the bean as a dependency and inject other dependencies, as shown in the below code example.

@Controller
@RequestMapping("/studentproxy")
public class StudentController {
    //all the request mappings in here.
}


So we can call the methods using the beans in the class, as shown in the code snippet below.

@GetMapping("/student")
public String allstudents(Student student) {
    //method to return all students
    return "studentscopedproxy";
}


This is all about the scoped proxy, and from the above code examples, it is clear that using the scoped proxy strategy, there is no impact on request mapping method signatures. Using this method, you can keep higher readability than the @SessionAttribute strategy.




We must utilize a proxy rather than injecting a non-proxied session-scoped bean.  A bean with a smaller scope cannot be injected into a bean with a larger scope. In this situation, attempting to do so would result in an error with the message: Scope'session' is not active for the current thread.

So let's have a real question you might be getting in creating the session attributes in spring-MVC.

Write Spring MVC style analog for this code.

session.setAttribute("name","value");


And how to add an element that is annotated by @ModelAttribute annotation to the session and then get access to it?

If you want to delete an object after each response, you don't need a session; if you want to keep an object during a user session, 

There are some ways:


1. directly add one attribute to the session:

@RequestMapping(method = RequestMethod.GET)
public String testMestod(HttpServletRequest request) {
    ShoppingCart cart = (ShoppingCart) request.getSession().setAttribute("cart", value);
    return "testJsp";
}


and you can get it from the controller like this :

ShoppingCart cart = (ShoppingCart)session.getAttribute("cart");


2. Make your controller session-scoped

@Controller
@Scope("session")


3. Scope the Objects; for example, you have a user object that should be in session every time:

@Component
@Scope("session")
public class User {
    String user;
    /* setter getter*/
}

then inject class in each controller that you want

@Autowired
private User user

That keeps class in the session.


4. Make your controller session-scoped


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">

<bean id="user" class="com.User" scope="session">
<aop:scoped-proxy/>
</bean>
</beans>

Then inject the class into each controller that you want.


@Autowired
private User user


5. Pass HttpSession to the method:

String index(HttpSession session) {
    session.setAttribute("mySessionAttribute", "someValue");
    return "index";
}


6. Make ModelAttribute in session By 

     @SessionAttributes("ShoppingCart"):
    public String index(@ModelAttribute("ShoppingCart") ShoppingCart shoppingCart,
        SessionStatus sessionStatus) {
        //Spring V4
        //you can modify session status by sessionStatus.setComplete();
    }


or you can add Model To the entire Controller Class like,

@Controller
@SessionAttributes("ShoppingCart")
@RequestMapping("/req")
public class MYController {

    @ModelAttribute("ShoppingCart")
    public Visitor getShopCart(....) {
        return new ShoppingCart(....); //get From DB Or Session
    }
}


Each one has advantages and disadvantages:

1. For example, @session may use more memory in cloud systems. It copies the session to all nodes,
and the direct method (1 and 5) has a messy approach; it is not good to unit test.


To access a session in JSP, you can use the following code:

<%=session.getAttribute("ShoppingCart.prop")%>


in Jstl :

<c:out value="${sessionScope.ShoppingCart.prop}"/>


in Thymeleaf:

<p th:text="${session.ShoppingCart.prop}" th:unless="${session == null}"> . </p>



How to use Session attributes in Spring MVC? Example Tutorial


That's all about using the session attribute in the Spring MVC application. It's an important way to store data and transfer between pages, and as a Java and spring developer, you should know about it. So in this article, we have discussed how to use session attributes in Spring-MVC. 

We focused on two strategies named using the @SessionAttribute annotations and a scoped proxy. And also, you need to keep in mind that any attributes stored in the session will only survive for the life of the session.

No comments:

Post a Comment