Search code examples
springrestsoapstatelessstateful

How to keep a data between requests at web service?


Suppose I develop a ticket order web service. There are some steps to order a ticket and need to keep some users data between the steps.

Suppose I use Spring (Boot) technology stack and MVC

How is better to implement it?

  1. Use stateless REST and move the date back and forth from step to step using cookies?
  2. Store it in session context?
  3. Use stateful beans (what are they like in Spring? Prototype? )
  4. Use some stateful protocol, like SOAP (is it stateful?)

Solution

  • It depends.

    1 If you want to use multiple instances of your web service (for balance load, etc) then your choice is a stateless REST and token-based authentication

    2 If you don't need this functionality you can store your session information in MVC Model (It will put it in session, anyway)

    @RestController
    @SessionAttributes("armUserSession")
    public class SessionController {
    
        @Autowired
        private LoginService loginService;
    
        @ModelAttribute("armUserSession")
        public ArmUserSession getArmUserSession() {
            return new ArmUserSession();
        }
    
        @CrossOrigin
        @RequestMapping({"/login"})
        public ArmUserSession login(@ModelAttribute("armUserSession") ArmUserSession userSession,
                                    Model model,
                                    @RequestParam(required = false) String login,
                                    @RequestParam(required = false) String password) {
            if (!userSession.isLoggedIn()) {
                userSession = loginService.login(login, password);
                model.addAttribute("armUserSession", userSession);
            }
    
            return userSession;
    }
    
        @CrossOrigin
        @RequestMapping({"/logout"})
        public ArmUserSession logout(SessionStatus status) {
            status.setComplete();
            return new ArmUserSession();
        }
    
    
    }
    

    3 You can use session scoped beans too, but it is a little more complicated. By default Spring beans are singletons. When you want to use session scoped bean (they are not singletons) in singleton your need a proxy.

    @Service
    public class LoginServiceImpl implements LoginService {
    
        @Autowired
        private ArmUserSessionProxy armUserSessionProxy;
    
        @Override
        public ArmUserSession login(String login, String password) {
            ArmUserSession armUserSession = armUserSessionProxy.getArmUserSession();
    
    ...................................
    }
    
    @Component
    @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
    public class ArmUserSessionProxy {
    
        private ArmUserSession armUserSession = new ArmUserSession();
    
        public ArmUserSession getArmUserSession() {
            return armUserSession;
        }
    
    }