Nested View is null when trying to use multiple view for single presenter

37 views
Skip to first unread message

the.wizard

unread,
Jul 2, 2018, 3:54:55 AM7/2/18
to Mvp4g
I was trying to inject a nested view inside two different view that belongs to single presenter. So the presenter is only one, but the view class will be created depends on device detector, whenever the device detected as mobile, it will use MobileView instead the DesktopView. Inside those 2 views, I inject a nested view, but whenever I tried to use it, it was always null. Here is my code: 

/*** IMultiViewModule.java ***/
@HistoryName("multiview")
public interface IMultiViewModule extends Mvp4gModule {


}


/*** IMultiViewEventBus.java ***/
@Events(startPresenter = MultiViewPresenter.class, module = IMultiViewModule.class)
public interface IMultiViewEventBus extends EventBus {
 
 
@Event(forwardToParent = true)
 
void changeBody(IsWidget body);
 
 
@Event(handlers = MultiViewPresenter.class, navigationEvent = true, bind = { LookupDummyPresenter.class })
 
void goToMultiView();
 
}


/*** ILookupDummyView.java ***/
public interface ILookupDummyView extends IChameleonWidget, ReverseViewInterface<ILookupDummyView.ILookupDummyPresenter> {
 
public interface ILookupDummyPresenter {
 
 
}
}


/*** LookupDummyPresenter.java ***/
@Presenter( view = LookupDummyView.class )
public class LookupDummyPresenter extends BasePresenter<ILookupDummyView, EventBus> implements ILookupDummyPresenter {
 
}


/*** LookupDummyView.java ***/
@Singleton
public class LookupDummyView extends ChameleonDialog implements ILookupDummyView {
 
 
private ILookupDummyPresenter presenter;
 
 
public LookupDummyView() {
 
// empty constructor
 
}


 
@Override
 
public void setPresenter(ILookupDummyPresenter presenter) {
 
this.presenter = presenter;
 
}


 
@Override
 
public ILookupDummyPresenter getPresenter() {
 
return this.presenter;
 
}
 
}


/*** IMultiViewView.java ***/
public interface IMultiViewView extends IsWidget, LazyView, ReverseViewInterface<IMultiViewView.IMultiViewPresenter> {
 
public interface IMultiViewPresenter {
 
public Integer getSecretNumber();
 
}
}


/*** MultiViewPresenter.java ***/
@Presenter(view = IMultiViewView.class)
public class MultiViewPresenter extends LazyPresenter<IMultiViewView, IMultiViewEventBus> implements IMultiViewPresenter {
 
 
private Integer secretNumber = 88;
 
 
public void onGoToMultiView() {
 eventBus
.changeBody(view);
 
}
 
 
@Override
 
public Integer getSecretNumber() {
 
return secretNumber;
 
}
 
}


/*** MultiViewView.java ***/
public class MultiViewView extends Composite implements IMultiViewView {


 
private IMultiViewPresenter presenter;
 
 
@Inject
 
protected LookupDummyView lookupDummyView;
 
 
public MultiViewView() {
 GWT
.log("empty...");
 
}
 
 
@Inject
 
public MultiViewView(LookupDummyView lookupDummyView) {
 
this.lookupDummyView = lookupDummyView;
 GWT
.log("lookup="+lookupDummyView);
 
}
 
 
@Override
 
public void createView() {
 
FlowLayoutContainer fContainer = new FlowLayoutContainer();
 
TextButton btn = new TextButton("Desktop Web Button");
 btn
.addSelectHandler(new SelectHandler() {
 
@Override
 
public void onSelect(SelectEvent event) {
 
Window.alert("Greetings from desktop web! Here is our secret number: "+presenter.getSecretNumber());
 
}
 
});
 fContainer
.add(btn);
 initWidget
(fContainer);
 
 GWT
.log("lookupDummyView="+lookupDummyView);
 
}


 
@Override
 
public void setPresenter(IMultiViewPresenter presenter) {
 
this.presenter = presenter;
 
}


 
@Override
 
public IMultiViewPresenter getPresenter() {
 
return this.presenter;
 
}


}


/*** MultiViewViewMobile.java ***/
public class MultiViewViewMobile extends Composite implements IMultiViewView {


 
private IMultiViewPresenter presenter;
 
 
@Inject
 
protected LookupDummyView lookupDummyView;
 
 
@Override
 
public void createView() {
 
FlowLayoutContainer fContainer = new FlowLayoutContainer();
 
TextButton btn = new TextButton("Mobile Web Button");
 btn
.addSelectHandler(new SelectHandler() {
 
@Override
 
public void onSelect(SelectEvent event) {
 
Window.alert("Greetings from mobile web! Here is our secret number: "+presenter.getSecretNumber());
 
}
 
});
 fContainer
.add(btn);
 initWidget
(fContainer);
 
 GWT
.log("lookupDummyView="+lookupDummyView);
 
}


 
@Override
 
public void setPresenter(IMultiViewPresenter presenter) {
 
this.presenter = presenter;
 
}


 
@Override
 
public IMultiViewPresenter getPresenter() {
 
return this.presenter;
 
}


}


/*** Sample.gwt.xml ***/
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='mysample'>
 
<!-- Inherit the core Web Toolkit stuff. -->
 
<inherits name='com.google.gwt.user.User' />


 
<!-- Other module inherits -->
 ...
 
<inherits name='app.chameleon.sample.DeviceDetector' />
 
 
<!-- Specify the app entry point class. -->
 
<entry-point class='app.research.sample.client.MySample' />


 
<replace-with class="app.chameleon.sample.client.module.multiview.view.MultiViewView">
       
<when-type-is class="app.chameleon.sample.client.module.multiview.presenter.view.interfaces.IMultiViewView"/>
 
</replace-with>


 
<replace-with class="app.chameleon.sample.client.module.multiview.view.MultiViewViewMobile">
       
<when-type-is class="app.chameleon.sample.client.module.multiview.presenter.view.interfaces.IMultiViewView"/>
       
<when-property-is name="deviceDetector" value="mobile"/>
 
</replace-with>


 
<replace-with class="app.chameleon.sample.client.module.multiview.view.MultiViewViewMobile">
       
<when-type-is class="app.chameleon.sample.client.module.multiview.presenter.view.interfaces.IMultiViewView"/>
       
<when-property-is name="deviceDetector" value="tablet"/>
 
</replace-with>
</module>


Everytime I tried to use the lookupDummyView instance, I will always got a null pointer exception. Please help me solve this problem, I have tried to figured it out myself, but face an end road. Thanks and regards.

Frank Hossfeld

unread,
Jul 2, 2018, 9:09:03 AM7/2/18
to Mvp4g
Can you set up a small sample project, that shows the error?

That would help much.

the.wizard

unread,
Jul 3, 2018, 12:04:06 AM7/3/18
to Mvp4g
Hello Frank, 
I attached my sample project contains the code that I was working for. When you try to run it, press the button and you will get 2 alert, the second alert will tell you that the nested view that injected was null. 
Please kindly help me solve this problem. Thanks and regards.
MyPlayground.zip

Frank Hossfeld

unread,
Jul 3, 2018, 4:26:56 AM7/3/18
to Mvp4g
Hi,

thanks for the example project.

I had to change the module to >>app.chameleon.research.playground.MyPlayground<< to solve an issue which happens when I start the the application. 

I use SDM and use >>http://127.0.0.1:8888/myplayground.html<< as url. But I only get a blank screen. I can see, that the application is running, but does not see any view.

Am I doing something wrong?

the.wizard

unread,
Jul 3, 2018, 5:09:09 AM7/3/18
to Mvp4g
Hi Frank, 
Sorry I forgot to tell you to use this url : http://127.0.0.1:8888/myplayground.html#seesaw and you will the the UI consist of one button.

the.wizard

unread,
Jul 4, 2018, 11:44:54 PM7/4/18
to Mvp4g
Hi Frank, 
Have you already see the application running?.. Any update or good news for this problem?.. Thanks and regards.

Frank Hossfeld

unread,
Jul 5, 2018, 5:08:49 AM7/5/18
to Mvp4g
Hi,
sorry for the delay.

Yes, I looked into it and I am pretty sure, your solution will not work.
It is not possible to use:

  

  @Inject

  protected LookupDummyView lookupDummyView;


to get an instance of a view with mvp4g.


View and presenter creation is handled by the framework. Trying to create or using views without a presenter may lead to unexpected results.  Although, mvp4g respects replacements rules. 


Depending on the requirements, there are several solutions.


For example: if you want to show a dialog box, you can inform the MultiViewPresenter, fire an event which will be catch by the LookupDummyPresenter, which shows your dialog box.


We can try to set up a project, that fit your requirements.


Btw, the current GWT version is 2.8.2, I suggest using this version with Java 1.8. Personally I prefer Thomas Broyers Maven plugin, which is in my opinion the better one. 


Frank


the.wizard

unread,
Jul 6, 2018, 3:21:37 AM7/6/18
to Mvp4g
Hi Frank, 
Thank you for your response. 

Trying to create or using views without a presenter may lead to unexpected results.
I'm pretty sure my way work good if I only have one view (and I don't write any rule replacement in gwt.xml). The presenter was binded from event bus (you can check my ISeesawEventBus at goToSeesaw method, there was a property added to @Event like this : 
@Event(handlers = SeesawPresenter.class, navigationEvent = true, bind = { LookupDummyPresenter.class })
void goToSeesaw();
Why it's not working now when I write a custom replacement rule for my view?
If I really can't inject a nested view, then what workaround / solution that I can try to use a nested view inside a main view? My nested view actually a view that have it's own presenter, and can retrieve data from presenter (via gwt rpc). 

Btw, the current GWT version is 2.8.2, I suggest using this version with Java 1.8. Personally I prefer Thomas Broyers Maven plugin, which is in my opinion the better one. 
Yup I know, but in my development, I still use 2.7.0 till now because some several reason (mostly because dependency conflict with other library). 

Thanks and regards.

the.wizard

unread,
Jul 9, 2018, 12:55:53 AM7/9/18
to Mvp4g
Hi Frank,
Any news on this workaround? I really need a solution for my requirement : 
  1. Switch view based on device detector (if desktop then desktopView, if mobile then mobileView). All view will be using the same presenter (only one presenter).
  2. Each view contains a nested view which is injected by mvp4g.
Please give me a solution for those requirements. Thanks and regards.

On Thursday, 5 July 2018 16:08:49 UTC+7, Frank Hossfeld wrote:

Frank Hossfeld

unread,
Jul 9, 2018, 4:28:55 AM7/9/18
to Mvp4g


Am Montag, 9. Juli 2018 06:55:53 UTC+2 schrieb the.wizard:
Hi Frank,
Any news on this workaround? I really need a solution for my requirement : 
  1. Switch view based on device detector (if desktop then desktopView, if mobile then mobileView). All view will be using the same presenter (only one presenter).
IIRC this should work automatically by using a replacement rule inside the module descriptor.   

  1. Each view contains a nested view which is injected by mvp4g.
you can try to use the multi presenter feature.  

* Define the LookupPresenter as multiple=true 
* add the IsWidet interface to the LookUpPresenter
* implement the asWidget method which looks like this:
public Widget asWidget() {
  view.asWidget();
}

* inside the view which contains the nested view, do the following:
call a method inside the presenter and inside this method call: this.presenter = eventBus.addHandler(LookUpPresenter.class);

Now you have an instance of the LookUpPresenter.

* next call another method in your presenter from the view:

getPresenter().addNestedView();

inside you presenter implement that method and call:

view.addNestedView(this.lookUpPresenter.asWidget);

Something like that should work. (We do similar in our projects.)
Hope that helps.

the.wizard

unread,
Jul 9, 2018, 9:03:48 PM7/9/18
to Mvp4g
Hi Frank, 
Could you please update my sample project with the workaround you mention above? Thanks and regards.

Frank Hossfeld

unread,
Jul 12, 2018, 4:56:37 AM7/12/18
to Mvp4g
I can do this, but this will take some time. 
Reply all
Reply to author
Forward
0 new messages