Anser Waseem
Anser Waseem

Reputation: 37

How do i use variable defined in one controller be used across multiple different controller?

I have one controller as:

@Controller
public class UserController {
    @Autowired
    private UserService userService;

    protected int userId; // I need to use it across many other controllers. HOW?

    @GetMapping("/")
    private String viewHomePage(Model model) {
        
        return "eAccounts";
    }

    @GetMapping("/dashboard")
    private String getDashboardPage() {
        return "dashboard";
    }

    @GetMapping("/signup")
    private String getSignupPage(Model model) {
        User user = new User();
        model.addAttribute("user", user);
        return "signup";
    }

    @PostMapping("/verifySignup")
    private String verifySignup(@ModelAttribute("user") User user, Model model, HttpServletRequest request) {
    if (userService.verifySignup(user) == 1) {
        userId = user.getId();// save user id for later use
        return "redirect:/dashboard";
    }

    return "signup";
    }
}

And there are multiple controllers (e.g., assetController, liabilityController, etc):

@Controller
public class AssetController {
    @Autowired
    private AssetService assetService;

    @GetMapping("/assets")
    public String getAssetsPage(Model model) {
        model.addAttribute("listAssets", assetService.getAllAssets(userId)); // here i need to use userId, and at many more places
        return "assets";
    }
}

I don't want to merge all my controllers code in one single controller. I just need to save userId whenever user signs up or login in the website, and then use it across many other controllers. Any clean solution will be appreciated.

Upvotes: 0

Views: 992

Answers (4)

pcsutar
pcsutar

Reputation: 1821

Assuming you want share the user id across multiple controllers for a session.

In this case you can use session scoped bean to store userId. New instance of session scoped bean will be created for each session and it will remain active for that session. Session scoped bean will be automatically destroyed once session is invalidated. Please refer below example for how to create session scoped bean and its usage:

Session scoped bean:

@Getter
@Setter
@NoArgsConstructor
@Component
@SessionScope //scope of this bean is session
public class UserDetails {
    private String userId;
}

Inject session scoped bean to your controllers:

UserController

@Controller
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private UserDetails userDetails; //adding session scoped bean

    @GetMapping("/")
    private String viewHomePage(Model model) {

        return "eAccounts";
    }

    @GetMapping("/dashboard")
    private String getDashboardPage() {
        return "dashboard";
    }

    @GetMapping("/signup")
    private String getSignupPage(Model model) {
        User user = new User();
        model.addAttribute("user", user);
        return "signup";
    }

    @PostMapping("/verifySignup")
    private String verifySignup(@ModelAttribute("user") User user, Model model, HttpServletRequest request) {
        if (userService.verifySignup(user) == 1) {
            userDetails.setUserId(user.getId());// save user id in session scoped bean
            return "redirect:/dashboard";
        }

        return "signup";
    }
}

AssetController

@Controller
public class AssetController {
    @Autowired
    private AssetService assetService;

    @Autowired
    private UserDetails userDetails;

    @GetMapping("/assets")
    public String getAssetsPage(Model model) {
        model.addAttribute("listAssets", assetService.getAllAssets(userDetails.getUserId())); //get user id from session scoped bean

        return "assets";
    }
}

Please refer spring docs for more information on session scoped beans.

Note: Please make sure you are not accessing session scoped bean outside the active session.

Upvotes: 1

Ervin Szilagyi
Ervin Szilagyi

Reputation: 16775

The default scope for beans in Spring is singleton. Since I don't see anything in your code which changes that, I would assume that your controllers are singleton.

You don't want to create instance variables, which depend on sessions, in singleton classes. It is a bad idea to have this protected int userId instance variable. For example, if you have two users browsing your application in the same time, one user might retrieve information using the other user's userid.

Usually the recommended way to get user information is to use the SecurityContext (example of usage from another question. We can retrieve the SecurityContext from the SecurityContextHolder.

Other solution would be to inject an Authentication or a Principal at the endpoints, such as:

@Controller
public class MyController {

    @RequestMapping(value = "/username", method = RequestMethod.GET)
    @ResponseBody
    public String currentUserName(Principal principal) {
        return principal.getName();
    }
}

Both of these solutions assume that we have correctly implemented authentication with Spring Security.

Upvotes: 1

Pierre Bonnet
Pierre Bonnet

Reputation: 1

You can use sessions, sessions will store value for custom values from an user for a custom period of time the duration could be the time as the application is up.

to store you can set a controler like that:

@RequestMapping(method = RequestMethod.GET)
public String testMestod(HttpServletRequest request){
   User user= (User)request.getSession().setAttribute("userId",value);
   return "test";
}

and to get the value you can use this method:

User user= (user)session.getAttribute("userId");

more info on this link https://www.techgeeknext.com/spring-boot/spring-boot-session-management

Upvotes: 0

Tal Glik
Tal Glik

Reputation: 510

Instead of saving it as a local variable of UserController, save it in another Bean for example in UserService, and all controllers will do @Autowired to it and will get the user id info.

Upvotes: 0

Related Questions