getApplication().close() and MVP

Hi vaadin-users,

i’m encoutering a problem with closing the application when using MVP-Pattern.

The application has an user-management (vaadin). After the Login, the View is changed to a new one as followed:


public class AMApplication extends Application	implements UserChangeListener{
	
	@Override
	public void init() {
		
		/* initialize main Vaadin window */
		Window mainWindow = new Window("AirportManagement Application");
		System.out.println("Main Application!");
		
		/* Add User Change Event Listener */
		this.addListener(this);
		
		buildLogin();
		
	}

	private void buildLogin() {
		/* Protect Resources */
		if (getUser() != null){
			setMainWindow(new ComponentView());
		} else {
			//Create vaadin view & model
			LoginView view = new LoginView();
			UserModel model = new UserModel();
			//bind view & model in presenter
			new LoginPresenter(view, model);

			setMainWindow(view);
		}
	}
	/**
	 * Method to load user protected Resources - any authenticated user is allowed to open 
	 * @param window - vaadin window
	 */
	public void loadProtectedResources(MainView window) {
	        if (((User) this.getUser()) != null) {
	            removeWindow(getMainWindow());
	            setMainWindow(window);      
	            new MainPresenter(window);
	        }else{
	        	buildLogin();
	        }
	   }
	/**
	 * This method is invoked when the current user has changed. 
	 * If a User is logs in, the window redirects to protected resources. 
	 * => e.g. everything except the login screen :) 
	 */
	@Override
	public void applicationUserChanged(UserChangeEvent event) {
		loadProtectedResources(new MainView());
	}
}

This works fine. The MainPresenter now is handling the incoming clicks in the MainView. Please ignore the view-design-code. I’m new to vaadin and still trying.:rolleyes:


/**
 * This MainView stays always active and is used for navigation and main-Tasks. 
 * @author Thorben
 *
 */
public class MainView extends Window implements ViewInterface, ClickListener {

	//constants
	private static final float HEIGHT_PIXEL = 80; 
	public static final String BUTTONTEXT_LOGOUT = "logout";
	//variables
	
	private VerticalSplitPanel verticalSplit;

	
	List<ViewListener> listeners = new ArrayList<ViewListener>();
	
	public MainView() {
		setName("Main Page");
		buildMainLayout();
	
	}

	private void buildMainLayout() {
		VerticalLayout layout = new VerticalLayout();
	    layout.setSizeFull();
	    verticalSplit = new VerticalSplitPanel();
	    verticalSplit.setFirstComponent(createToolbar());
	    layout.addComponent(verticalSplit);
	    layout.setExpandRatio(verticalSplit, 1);
	    setContent(layout);
	    verticalSplit.setLocked(true);
	    //Headergröße
	    verticalSplit.setSplitPosition(HEIGHT_PIXEL, Sizeable.UNITS_PIXELS);
	}

	private Component createToolbar() {
        Button logoutButton = new Button(BUTTONTEXT_LOGOUT,this);
		 
		 Panel panel = new Panel();
		 panel.setWidth("100%");
		 panel.setHeight(HEIGHT_PIXEL, UNITS_PIXELS);
		 HorizontalLayout panelLayout = new HorizontalLayout();
		 
		 panelLayout.setMargin(true);
		 panelLayout.setSpacing(true);
		 panelLayout.addComponent(logoutButton);
		 panelLayout.setComponentAlignment(logoutButton, Alignment.MIDDLE_RIGHT);
		 panelLayout.setExpandRatio(logoutButton, 1);

		 panel.setContent(panelLayout);
		 
        return panel;
        
	}
	
	public void setActiveView(Component c){
		this.verticalSplit.setSecondComponent(c);
	}

	/* The presenter registers one listener */
    
	@Override
	public void addListener(ViewListener listener) {
		listeners.add(listener);
		
	}

	/* One ClickListener for all Buttons */
	@Override
	public void buttonClick(ClickEvent event) {
		
		for(ViewListener listener : listeners){
			try {
				listener.buttonClick(event.getButton().getCaption());
			}catch (Exception e){
				showNotification(e.toString());
			}
			
		}
		
	}

	public void closeApplication() {
		try {
        	getWindow().getApplication().close();
        } catch (Exception e) {
            showNotification(e.toString());
        }
	}

}

And the Presenter:

/**
 * Presenter for the MainView with Navigation.
 * @author Thorben
 *
 */
public class MainPresenter implements ViewInterface.ViewListener{

	private MainView view;
	private MainModel model;
	
	public MainPresenter(MainView view) {
		super();
		this.view = new MainView();
		this.model = new MainModel();
		
		// add view listener
		view.addListener(this);
	}

	@Override
	public void buttonClick(String caption) {
		switch (caption) {
		case MainView.BUTTONTEXT_LOGOUT:
			
			this.view.closeApplication();
		default:
			//do nothing
		}
	}

}

When i don’t use the presenter for the click-handling but close the application directly in the view, it works like it should - the user is removed and the main view is exchanged by the loginview.

But when i try to do this in the presenter (even if i just call a method of the view which closes the application, like in the code), i get a nullpointer exception, but no stacktrace and no further information.
i really don’t understand, what’s wrong here.:frowning:
could you please help me and explain it?

In your presenter, you have MainView as constructor parameter but you never set it to any variable in your presenter but create new instance. Still, you assign the presenter as listener for the view you give as parameter. Might this be the problem? Try debugging where the NPE comes from.

Well, that’s embarassing. Thank You, this was correct! I was blind :vader: