How to avoid static context

Hello,

I’m having trouble avoiding static ontexts when trying to cross-reference instances of different objects (like trying to modify a property of object A from object B ) in Vaadin.
The way I get around this in desktop applications is by instantiating the main class, but this can not be done in Vaadin (or can it?). Here’s my specific problem:

In my mainUI I have 3 buttons: one to login, one to logout, and one to register (for new users), and one label which is initially empty, that will display the user name, once logged in. For the login and register actions, I create a CustomComponent Class implementing the View interface, and I load them in a panel in the mainUI as needed. And then there’s another CustomComponent class which corresponds to the main application view.

The main UI:

[code]
public class MainUI extends UI{

Button bLogin;
Button bLogout;
Button bRegister;
Label lName;

@Override
protected void init(VaadinRequest request) {
    bLogin = new Button("Login");
    bLogout = new Button("Logout");
    bRegister = new Button("Register");
    lName = new Label();

    bLogout.setVisible(false);  //Logout button is not visible until user logs in.
    
    getNavigator().addView(MainView.VIEW_NAME, MainView.class);
    getNavigator().addView(Login.VIEW_NAME, Login.class);
    getNavigator().addView(Register.VIEW_NAME, Register.class);
}

}
[/code]Now, when the user logs in, I want to

  • Register the user name in a session property
  • Make the Logout and Register buttons invisible
  • Load the main view in mainUI

So in the Login class I have:

[code]
public class Login extends CustomComponent implements View {

Button bSubmmit; //Button to submit user and password

public Login(){ //Constructor
    bSubmmit.addClickListener(new ClickListener(){
        @Override
        public void buttonClick(ClickEvent event) {
            /*
              ...Do stuff to validate credentials, etc...
            */

         String userName = (...get user name from database...)

         getSession().setAttribute("user", userName);
         MainUI.bLogout.setVisible(true);
         MainUI.bLogin.setVisible(false);
         MainUI.bRegister.setVisible(false);
         MainUI.lName.setValue(userName);
         getUI().getNavigator().navigateTo(MainView.VIEW_NAME);
    });
}

}
[/code]In order for this to work, I need to declare the Button and Label variables as static, otherwise I would get the error "
non-static variable bLogout can not be referenced from a static context
". This is because I am referencing the variables directly in MainUI and not in an instance of MainUI. (Can I instantiate the main UI? Should I?).
So now, in the main class I need to have:

[code]
public class MainUI extends UI{

static static Button bLogin;
static Button bLogout;
static Button bRegister;
static Label lName;

(etc…)
[/code]Now, when a new user registers, I want him to be automatically logged in with the credentials he provides, so instead of re-writing the same logic (hide Logind and Register buttons, etc.) in the Register class, I would like to implement a method which does this, and then simply call the method from the Login class once loged in, and from the Register class once registered.
Since I’m going to call this method both from Login and Register classes, lets say I create the method in the MainUI class. Again, since I have no instance of MainUI, I need to declare the method as static:

[code]
public class MainUI extends UI{

static static Button bLogin;
static Button bLogout;
static Button bRegister;
static Label lName;

(...DO STUFF...)

public static void setRegistered(boolean registered){
    if (registered){
        bLogin.setVisible(false);
        bRegister.setVisible(false);
        bLogout.setVisible(true);
        lName.setText(getSession().getAttribute("user"));
        getUI().getNavigator().navigateTo(MainView.VIEW_NAME);
    }
}

(...DO STUFF...)

}
[/code]But now I get the error with the getSession() and the getUI() methods:

"
non-static method getSession() can not be referenced from a static context
".

Like I said, I usually instantiate the main class in desktop applications to deal with the static/non-static contexts. Should I instantiate the MainUI class? Otherwise, what is the best way around this in Vaadin?

Thanks.

A UI corresponds to a HTTP session, so sharing variables (using static) is a big no-no.
Otherwise your label would be the very same instance for all users using your service
at the same time, which would get you into trouble (last loggin-in user’s name shown
for all users after a screen update, for example).

You do not have to instantiate the UI class, as Vaadin is doing that for you.
Please refer to https://vaadin.com/book/-/page/application.architecture.html

If you want to access the package-private members (such as bLogin) directly,
you should be able to use ((MainUI) UI.getCurrent()).lName.setCaption(“foobarbaz”);

HTH

Best Regards,
Enver

Hi Enver,

That was clarifying, indeed.
Things are working now.

Thanks a lot!!