如何在 Vaadin 的 CDIView 中获取 UI 实例?

How to get UI instance in CDIView in Vaadin?

我有我的UIclass

@Theme("mytheme")
@CDIUI("")
public class MyUI extends UI {

@Inject
LoginView loginView;

@Override
protected void init(VaadinRequest vaadinRequest) {
    setContent(loginView);
}

...

我有一个带有 init 方法注释的视图 @PostConstruct

@UIScoped
@CDIView(LoginView.VIEWNAME)
public class LoginView extends VerticalLayout implements CustomView {

    @PostConstruct
    public void initView() {

        //initializations elements 
        Component loginForm = buildLoginForm();
        addComponent(loginForm);
        setComponentAlignment(loginForm, Alignment.MIDDLE_CENTER);

        Notification notification = new Notification("Demo");
        notification.setDescription("<span>DEMO</span>");
        notification.setHtmlContentAllowed(true);
        notification.setStyleName("tray dark small closable login-help");
        notification.setPosition(Position.BOTTOM_CENTER);
        notification.setDelayMsec(20000);
        notification.show(Page.getCurrent()); // NullPointerException

    }
}

The stacktrace is:

Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.jboss.weld.injection.producer.DefaultLifecycleCallbackInvoker.invokeMethods(DefaultLifecycleCallbackInvoker.java:98)
    ... 72 more

Caused by: java.lang.NullPointerException
    at com.vaadin.ui.Notification.show(Notification.java:378)
    at com.test.claspina.view.LoginView.initView(LoginView.java:103)
    ... 77 more

我的问题是如何获取 UI 实例以在渲染我的视图元素期间使用。

我找到了一个部分解决方案,将元素的所有定义放入配置方法中,这样:

public void configure() {
    //initializations elements
    Component loginForm = buildLoginForm();
    addComponent(loginForm);
    setComponentAlignment(loginForm, Alignment.MIDDLE_CENTER);

    Notification notification = new Notification("Demo");
    notification.setDescription("<span>DEMO</span>");
    notification.setHtmlContentAllowed(true);
    notification.setStyleName("tray dark small closable login-help");
    notification.setPosition(Position.BOTTOM_CENTER);
    notification.setDelayMsec(20000);
    notification.show(Page.getCurrent());
}

并在我的 UI

中的 setContent 之前调用
loginView.configure();
setContent(loginView);

最后在同事的帮助下,找到了解决办法:

这样用CDIViewProvider很有必要

@Theme("mytheme")
@CDIUI("")
public class MyUI extends UI {

@Inject
LoginView loginView;

@Inject
private CDIViewProvider viewProvider;

@Override
protected void init(VaadinRequest vaadinRequest) {
    Navigator navigator = new Navigator(this, this);
    navigator.addProvider(viewProvider);
    navigator.navigateTo("login");
}

并进入class,定义视图的名称,将视图元素的所有定义放在进入方法

@UIScoped
@CDIView(LoginView.VIEWNAME)
public class LoginView extends VerticalLayout implements CustomView {

    public static final String VIEWNAME = "login";

   //...
   //other methods
   //... 

   @Override
   public void enter(ViewChangeListener.ViewChangeEvent event) {
      //initializations elements
      Component loginForm = buildLoginForm();
      addComponent(loginForm);
      setComponentAlignment(loginForm, Alignment.MIDDLE_CENTER);

      Notification notification = new Notification("Demo");
      notification.setDescription("<span>DEMO</span>");
      notification.setHtmlContentAllowed(true);
      notification.setStyleName("tray dark small closable login-help");
      notification.setPosition(Position.BOTTOM_CENTER);
      notification.setDelayMsec(20000);
      notification.show(Page.getCurrent());
    }
}