Search code examples
jakarta-eecdivaadin8

How to get UI instance in CDIView in Vaadin?


I have MyUI class

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

@Inject
LoginView loginView;

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

...

I have a View with a init method annotated with @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

My question is how to get the UI instance to use during the render the elements of my view.

I found a partial solution putting all definitions of elements into a configure method, this way:

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());
}

And calling before setContent in my UI

loginView.configure();
setContent(loginView);

Solution

  • Finally, with the help of my co-worker, I found a solution:

    It's necessary to use CDIViewProvider this way

    @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");
    }
    

    And into the class, define the name of the view, and put all definitions of the elements of the view in entering method

    @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());
        }
    }