0

I have this case where I have two session-scoped beans. One is used for Login-functionality. So this bean remembers what the current user is, which it sets after a user has successfully logged in.

There is another session scoped bean that allows the user to configure some stuff, which is also supposed to be be kept along the session. The user can go back to the configuration-site whenever he wants and see his old (from the same session) data. Important to know is that the user does not need to be logged in to use this site. Imagine like a cart on a webshop, with many shops you can put stuff in the cart before even logging in and it will remain throughout your session. Here is where it gets tricky: On this configuration-site, the user can access some special functionality, such as permanently saving his configuration-stuff, but only if he is logged in. If not, he simply won't have the option. Again, very similar to a webshop, if you actually want to order the cart of your session you usually have to log in at that point.

The problem is that if the user first goes onto the configuration-site, then this session bean will be created first. The session bean retrieves the user by a binding-annotation (CurrentUser) which is @Provided by the Login-Bean via it's getter for the current user. However, at creation time of the configuration-site bean, there is no current user. Now, if the user then decides to go and login, the configuration-site bean will still think that there is no currentUser, since that field was initialized when the bean was initialized and there is no logic that will update it.

How can I handle this situation? Do I have to start manually putting and retrieving stuff from the Session-Objects? So far everything was handled automatically by JSF / Application Server simply because of the @SessionScoped annotations.

Edit: Here goes some code to explain the situation further:

The Login-Bean:

@SessionScoped
@Named
public class LoginUserManager implements Serializable {
  private UserBean currentUser;
  // Logic that does the login and set the currentUser if successfull
  // ...
  // "Produces" currentUsers for other beans, that want to inject it simply 
  // via the @CurrentUser annotation, see below
  @Produces
  @CurrentUser
  public UserBean getCurrentUser() {
    return currentUser;
  }
}

Then there is the configuration-manager

@SessionScoped
@Named
  public class ConfigurationManager implements Serializable {
  // Session based configuration data here
  // And, the current user (if any)
  @CurrentUser
  private UserBean currentUser;
}

The CurrentUser annotation should be a simple "binding annotation" if I understood correctly. It's taken from a snippet I saw on the internet, to be honest. I found it elegant, thought it's smooth to read and functionally identical to injecting the LoginUserManager directly and then calling it's getCurrentUser() getter.

@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD})
@BindingType
public @interface CurrentUser {
}
Mercious
  • 378
  • 3
  • 25
  • 1
    Seems to me there is a design flaw somewhere (or I'm not fully grasping the question). Why not just allow the configuration site bean to just inject a User/CurrentUser session scoped bean? If it's empty and its fields are not initialized you know the user is not logged in. [mcve] please. – Adam Waldenberg Jan 29 '19 at 21:12
  • I haven't tried this, because I assumed the following: if the configuration-site bean, which itself is also session-scoped, injects an instance of the Login-Bean (which holds the current user and is also session scoped) then if the configuration-site bean is initialized first (because the user goes to the registration site before logging in) then this injected instance of the Login-Bean won't magically update once the user logs in, right? I assume that at initialization-time of the configuration-site bean there wont be any valid Login-Bean for this session yet? Can append code if still unclear – Mercious Jan 29 '19 at 21:21
  • Yes it will magically be updated since a reference is 'injected' initially (a proxy wrapper actuall if using CDI) – Kukeltje Jan 29 '19 at 21:25
  • Uh, then the annotation-magic that I copied without understanding probably screwed me over, deservedly. See original question, I edited it so you guys can see what I mean. – Mercious Jan 29 '19 at 21:33
  • 1
    @Mercious The solution in this case would be to make sure you create the `UserBean` from the start (when the session scoped bean is initialized) and just update `currentUser` on login. You really don't need the producer though. Everything placed in session scope is for the "current" user/client. – Adam Waldenberg Jan 29 '19 at 21:48
  • 1
    I see, I understand - I thought they are kind of working the same way, so I did not expect the direct injection of the other bean to work. Well, part of the requirements for the project I am doing (educational purposes) was to have at least one application of a self-written producer for injected components. I honestly have no clue where the hell I am supposed to put that as I see no real application for it in my use-cases, this one was the one that made the most sense. But screw that, I don't want to make my code less pretty and more dependend on each other just to have a producer-case. – Mercious Jan 29 '19 at 21:52
  • Either way: Thanks alot to everyone for the answers, I just tried it with injecting the other bean directly and it works like a charm. Feel free to post that as an answer, maybe with a short explanation on how CDI is capable of syncing these two session-scoped beans via proxy (or however it works) and why the producer-thingy I used is not. – Mercious Jan 29 '19 at 21:53
  • 1
    @Mercious The producer works... But it's unnecessary. The problem is that it's probably null when you first get started. You are not initializing `currentUser` in the above code. – Adam Waldenberg Jan 29 '19 at 21:56
  • 1
    For further reading on the subject, check out this answer https://stackoverflow.com/questions/7031885/how-to-choose-the-right-bean-scope from @BalusC. – Adam Waldenberg Jan 29 '19 at 21:59

0 Answers0