Search code examples
javaexceptionvaadinvaadin7

NPE in Vaadin7 Navigation with my own ViewProvider implementation.


I tried to create a vaadin7 application with the use of Navigator. I have my own ViewProvider implementation.

here is the relevant part of the UI class:

 @Override
protected void init(VaadinRequest request) {
    layout = new VerticalLayout();
    layout.setSizeFull();

    setContent(layout);

    navigator = new Navigator(this, layout);
    mainView = new MainView(navigator);
    navigator.addView("", mainView);

    ViewProviderImpl viewProviderImpl = new ViewProviderImpl(mainView);
    navigator.addProvider(viewProviderImpl);
}

here is MainView:(this is the one that should be displayed by default. Currently it contains two buttons only. Should one hit the buttons, the navigator should take him to one of the other Views)

 public MainView(Navigator navigator) {

    this.setSizeFull();

    this.addComponent(new Label("This is the main view 1"));

    int i = 1;
    createSubViewButtons(i++ , Constants.DASHBOARD, new DashboardView());
    createSubViewButtons(i++ , Constants.SCHEDULE, new ScheduleView());

}

private void createSubViewButtons(int exNum, String caption, View view) {
    navigator.addView(caption, view);

    Button button = new Button(caption, new ClickListener() {
        private static final long serialVersionUID = 1L;

        @Override
        public void buttonClick(ClickEvent event) {

            navigator.navigateTo(event.getButton().getData().toString());

        }
    });

    button.setData(caption);
    button.setStyleName(Reindeer.BUTTON_DEFAULT);

    this.addComponent(button);
}

and I have a class that implements ViewProvider. This basically should map URLs to views. The getViewName() methods removes the unnecessary parts of the url, and the getView() should return the View instance based on the return value of getViewName(). (Anyway, I have the strong feeling that the code execution never gets here, as the exception happens earlier)

public class ViewProviderImpl implements ViewProvider {

private static final long serialVersionUID = 1L;

private static Map<String, View> mapping;

static {
    mapping =  new HashMap<String, View>();
    ScheduleView scheduleView = new ScheduleView();
    DashboardView dashboardView = new DashboardView();
    mapping.put("CORE/maintain/schedule", scheduleView);
    mapping.put("CORE/maintain/dashboard", dashboardView);
    mapping.put(Constants.DASHBOARD, dashboardView);
    mapping.put(Constants.SCHEDULE, scheduleView);
}

public ViewProviderImpl(MainView mv) {
    mapping.put("", mv);
}

@Override
public String getViewName(String viewAndParameters) {

    // to do --if it is non empty than take it otherwise use Page 

    StringBuilder sb = new StringBuilder();
    String fullURL = Page.getCurrent().getLocation().toString();
    String fullURL = viewAndParameters;

    String arr[] = fullURL.split(Constants.ARRANGER_WITH_SLASH);
    if (arr.length > 1) {

        String shortURL = arr[1];

        if (shortURL.contains(Constants.QUESTION_MARK)) {
            shortURL = shortURL.split("\\?")[0];
        }
        if (shortURL.contains(Constants.SLASH)) {
            // always remove the two first and keep the rest of it.
            String split[] = shortURL.split(Constants.SLASH);
            for (int i = 0; i < split.length; i++ ) {
                if (i <= 1) {
                    continue;
                }
                sb.append(split[i]);
                if (i >= 2 && i != split.length - 1) {
                    sb.append(Constants.SLASH);
                }
            }
        }
    }
    return sb.toString();
}

For me, it seems logical. In reality, however it throws NPE. Why? Probably I abuse the way how navigation should be used in Vaadin7, but I can't figure out what should I do...

java.lang.NullPointerException
    vaadinacrys.MainView.createSubViewButtons(MainView.java:39)
    vaadinacrys.MainView.<init>(MainView.java:33)
    vaadinacrys.PoolarrangerUI.init(PoolarrangerUI.java:36)
    com.vaadin.ui.UI.doInit(UI.java:641)
    com.vaadin.server.communication.UIInitHandler.getBrowserDetailsUI(UIInitHandler.java:222)
    com.vaadin.server.communication.UIInitHandler.synchronizedHandleRequest(UIInitHandler.java:74)
    com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41)
    com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1402)
    com.vaadin.server.VaadinServlet.service(VaadinServlet.java:295)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

Solution

  • Following up my original comment, you have not posted your MainView class fully but in it's constructor you're not assigning the Navigator navigator variable to a field nor passing it as a parameter to the createSubViewButtons method so you can use it there. If you have indeed a field called navigator, by the time navigator.addView(caption, view); gets executed it will be null, hence you get a NPE. Quick fix, this.navigator = navigator in your constructor & enjoy.