How to implement MVP using Vaadin CDI and Navigator?

十年热恋 提交于 2019-12-10 18:35:00

问题


I would like to implement the MVP pattern in my web application using Vaadin. I am using the Vaadin Navigator and the CDIViewProvider, something like so:

//MyUI.java
public class MyUI extends UI {
    @Inject
    CDIViewProvider viewProvider;

    Navigator navigator;

    @Override
    protected void init(VaadinRequest vaadinRequest) {

        //UI setup
        navigator = new Navigator(this, someContainer);
        navigator.addProvider(viewProvider);
        getNavigator().navigateTo("myView");
    }
}

//MyViewImpl.java
@CDIView("myView")
public class MyViewImpl extends VerticalLayout implements com.vaadin.navigator.View, MyView {
    // ...

To my understanding the view provider instantiates an object of MyViewImpl which is ViewScoped, i.e. it gets created/destroyed as the user navigates to/out of this view. Next I need to think about where to instantiate the presenter of this view. I thought about making it SessionScoped and inject it to the view:

// ... continue MyViewImpl.java

@Inject 
private MyViewListener presenter;

// in some of the MyViewImpl methods we can do stuff like presenter.buttonClicked();
}

//MyViewPresenter.java
@SessionScoped
public class MyViewPresenter implements MyView.MyViewListener {

    MyView view; //how can the presenter obtain the view here ?

    @PostConstruct
    public void init() 
    @Override
    public void buttonClicked() {
        view.displaySomething();
    }
}

//MyView.java
public interface MyView {
    public interface MyViewListener {     
        public void buttonClicked();
    }

    public void displaySomething();
}

As I already pointed out in the comment behind the presenters reference to the view I do not know how the presenter can get a hold of the view instance (which is created by the view provider). Does it even make sense to have the presenter be SessionScoped, while the views get created/destroyed whenever the view changes ? An alternative way would be that the view does not have a reference to the presenter, but that the presenter adds itself as the listener to the view. However in this case I again do not know where to instantiate the presenter and how to get a reference to the current view.


回答1:


Don't try to inject the view, use a view setter in presenter instead and call it from view's @PostConstruct:

@Dependent
class MyPresenter {

    private MyView view;

    public void setView(MyView view) {
        this.view = view;
    }
}

public interface MyView {
}

@CDIView("my-view")
public class MyViewImpl extends VerticalLayout implements View, MyView {

    @Inject
    private MyPresenter presenter;

    @PostConstruct
    private void init() {
        presenter.setView(this);
    }
}

I think that creation order is the confusing issue here. In a way views have higher priority as they are created by Vaadin when you call getNavigator().navigateTo("my-view"). Presenter is instantiated by the view by CDI (even though it supervises the view) and should have @Dependent scope.




回答2:


I think the point is that a view gets the presenter injected and vice versa. So one strategy for the approach you have above is making the Presenter @Dependent scoped and put @Inject MyViewPresenter presenter in the view and @Inject MyView view into the presenter. @Dependent makes them reside in the same scope which is quite probably what you want to achieve



来源:https://stackoverflow.com/questions/32184406/how-to-implement-mvp-using-vaadin-cdi-and-navigator

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!