如何更改Vaadin 7应用程序的主视图?

4

我希望写一个Vaadin 7应用程序(见下面的MyVaadinUI),要求用户输入用户名和密码。

如果它们正确,另一个视图(见下面的MainUI)应该出现并占据整个区域(替换登录视图)。

我尝试在方法MyVaadinUI.goToMainWindow中实现此转换,但是我收到错误提示。

java.lang.RuntimeException: Component must be attached to a session when getConnectorId() is called for the first time
    at com.vaadin.server.AbstractClientConnector.getConnectorId(AbstractClientConnector.java:417)
    at com.vaadin.server.communication.ConnectorHierarchyWriter.write(ConnectorHierarchyWriter.java:67)
    at com.vaadin.server.communication.UidlWriter.write(UidlWriter.java:143)
    at com.vaadin.server.communication.UidlRequestHandler.writeUidl(UidlRequestHandler.java:149)
    at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:97)
    at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:37)
    at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1371)
    at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:238)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)

当我运行应用程序并按下按钮时,我该如何解决它?
@Theme("mytheme")
@SuppressWarnings("serial")
public class MyVaadinUI extends UI
{
    private TextField userNameTextField;
    private PasswordField passwordTextField;

    @WebServlet(value = "/*", asyncSupported = true)
    @VaadinServletConfiguration(productionMode = false, ui = MyVaadinUI.class, widgetset = "ru.mycompany.vaadin.demo.AppWidgetSet")
    public static class Servlet extends VaadinServlet {
    }

    @Override
    protected void init(VaadinRequest request) {
        final VerticalLayout layout = new VerticalLayout();
        layout.setMargin(true);
        setContent(layout);

        addUserNameTextField(layout);
        addPasswordTextField(layout);

        addButton(layout, request);
    }

    private void addPasswordTextField(Layout aLayout) {
        passwordTextField = new PasswordField("Пароль:");

        aLayout.addComponent(passwordTextField);

    }

    private void addUserNameTextField(final Layout aLayout) {
        userNameTextField = new TextField("Пользователь:");

        aLayout.addComponent(userNameTextField);
    }


    private void addButton(final Layout aParent, final VaadinRequest request) {
        final Button button = new Button("Войти");
        button.addClickListener(new Button.ClickListener() {
            public void buttonClick(Button.ClickEvent event) {
                final boolean credentialsCorrect = checkCredentials();

                if (credentialsCorrect) {
                    goToMainWindow(request);
                } else {
                    [...]
                }
            }
        });
        aParent.addComponent(button);
    }

    private void goToMainWindow(final VaadinRequest aRequest) {

        final MainUI mainUI = new MainUI();
        mainUI.init(aRequest);
        setContent(mainUI);
    }

}

@Theme("mytheme")
@SuppressWarnings("serial")
public class MainUI extends UI {
    @Override
    protected void init(final VaadinRequest vaadinRequest) {
        final HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();

        setContent(splitPanel);

        splitPanel.setSizeFull();
        splitPanel.setSplitPosition(200, Unit.PIXELS);

        final String[] tabLabels = new String[] {
                "Tree item 1",
                "Tree item 2"};

        final Tree tree = new Tree();

        for (int i=0; i < tabLabels.length; i++)
        {
            addTreeItem(tree, tabLabels[i]);
        }

        splitPanel.setFirstComponent(tree);
        splitPanel.setSecondComponent(new Label("Test"));
    }

    private void addTreeItem(final Tree aTree, final String aLabel) {
        aTree.addItem(aLabel);
    }
}
3个回答

7
在Vaadin论坛上,有人建议使用导航器(navigator),这解决了我的问题。请查看此处

3
你能在这里分享一些代码,以便更好地回答你自己的问题,为后人留下记录吗? - Basil Bourque

2
我认为MainUI应该扩展HorizontalSplitPanel而不是UI。将一个UI插入另一个UI对我来说是一个奇怪的概念。

1
你可以使用 @SpringUI 作为扩展 UI 的主类:
@SpringUI
@Theme("mytheme")
@Widgetset("com.MyAppWidgetset")
@PreserveOnRefresh
public class MainUI extends UI {

  private static final long serialVersionUID = -8247521108438815011L;

  private static Locale locale = VaadinSession.getCurrent().getLocale();
  @Autowired
  private ToolBoxMessageSource messageSource;

  @Autowired
  private SpringViewProvider springViewProvider;

  public MainUI() {

  }

 //Initializes navigator with SpringViewProvider and add all existing 
 //and ui specific assigned views to navigator.

  @Override
  protected void init(VaadinRequest vaadinRequest) {
    Navigator navigator = new Navigator(this, this);
    // Adding springViewProvider for spring autowiring
    navigator.addProvider(springViewProvider);
    // Adding all views for navigation
    navigator.addView(LoginView.NAME, LoginView.class);
    navigator.addView(MainView.NAME, MainView.class);
    navigator.addView(MailToolView.NAME, MailToolView.class);
    navigator.addView(AdminView.NAME, AdminView.class);
    navigator.addView(EditRecipientView.NAME, EditRecipientView.class);
    navigator.addView(EditRecipientsView.NAME, EditRecipientsView.class);
    navigator.addView(ServerView.NAME, ServerView.class);
    navigator.addView(TestJobView.NAME, TestJobView.class);
    navigator.addView("", new LoginView());
    navigator.navigateTo(LoginView.NAME);
    navigator.setErrorView(LoginView.class);

  // security: if user changes view check if the user has the required rights
  navigator.addViewChangeListener(new ViewChangeListener() {
  private static final long serialVersionUID = 7330051193056583546L;

  @Override
  public boolean beforeViewChange(ViewChangeEvent event) {
    Toolbox toolbox = getSession().getAttribute(Toolbox.class);
    if (TbRightManagement.checkAccess(event.getNewView().getClass(), toolbox)) {
      return true;
    } else {
      if (toolbox != null) {
        TBNotification.show(messageSource.getMessage("access.denied.title", locale),
            messageSource.getMessage("access.denied.no_permissions.msg", locale),
            Type.ERROR_MESSAGE);
        navigator.navigateTo(MainView.NAME);
        return false;
      } else {
        TBNotification.show(messageSource.getMessage("access.denied.title", locale),
            messageSource.getMessage("access.denied.not_loggedin.msg", locale),
            Type.ERROR_MESSAGE);
        navigator.navigateTo(LoginView.NAME);
        return false;
      }
    }
  }

  @Override
  public void afterViewChange(ViewChangeEvent event) {}
});
}
}

对于其他视图,例如EditRecipientsView应该是一个扩展Vaadin Designer并实现Vaadin View的@SpringView。

@SpringView(name = EditRecipientsView.NAME)
@Theme("mytheme")
@TbRight(loggedIn = true, mailTool = true)
public class EditRecipientsView extends RecipientsDesign implements View {

private static final long serialVersionUID = 1L;
public static final String NAME = "editRecipients";

private static Locale locale = VaadinSession.getCurrent().getLocale();

private BeanItemContainer<Recipient> recipientContainer;

private Uploader uploader;

@Autowired
private ToolBoxMessageSource messageSource;

  public EditRecipientsView() {
  super();
  }
   //Initializes the ui components of the recipient view.
  @PostConstruct
  public void init() {
  btn_addRecipient.addClickListener(e ->   {   MainUI.getCurrent().getNavigator().navigateTo(EditRecipientView.NAME);});
  }
   //Handling data when entering this view.
   @Override
   public void enter(ViewChangeEvent event) {
   if (getSession().getAttribute(UIMailing.class) != null) {
    List<Recipient> recipientList =   getSession().getAttribute(UIMailing.class).getRecipients();
    if (recipientList != null) {
      recipientContainer.removeAllItems();
    } else {
      recipientList = new ArrayList<Recipient>();
    }
    recipientContainer.addAll(recipientList);
    recipient_table.sort(new Object[] {"foreName", "lastName"}, new boolean[]    {true, true});
  }
  }
 }

您能否详细阐述一下您的答案,并对您提供的解决方案进行更多描述? - abarisone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接