-
1. Re: Listen to @Observes only when started in a mvp presenter
csa Nov 28, 2013 11:32 AM (in response to marius.gerwinn)1 of 1 people found this helpfulHi Marius,
The only way you can currently unsubscribe from @Observes is by destroying the bean instance (as Mike described in the post you linked to). I am wondering though, couldn't that be the solution to your problem? Basically, you'd look up (create) a new instance of the presenter when it's "started" (instead of setting the boolean flag) and you destroy it when you no longer need it.
CDI event qualifiers don't seem to be the right solution there because they are not designed to make event routing decisions based on observer state at run time. Their purpose is to be able to differentiate between different events of the same type.
Cheers,
Christian
-
2. Re: Listen to @Observes only when started in a mvp presenter
mbarkley Nov 28, 2013 11:58 AM (in response to marius.gerwinn)1 of 1 people found this helpfulHi Marius,
For the sake of brainstorming, here's an idea I have about how what I will call "Conditional Event Observation" that you are describing could work.
We could have a new annotation which marks a method returning a boolean in the sending or receiving class like so. I'll illustrate my idea with a receiving example.
First we could create a new annotation Condition, that takes a qualifier. This annotation would be placed on a method returning a boolean in a class with an Observes method like so:
public interface Receiver extends { @Condition(MyConditionQualifier.class) public boolean conditionLogic() { return true; } public void businessLogic(@Observes @MyConditionQualifier SomeEventType) { //... } }
Now suppose another class fires a @Default Event<SomeEventType>. This is what would happen:
- The CDI container finds each Receiver instance.
- For each Receiver instance, the container invokes conditionLogic.
- For each instance, if conditionLogic returned true, the container will pass a copy of the fired event with the @MyConditionQualifier (and probably without @Default).
A few things that could follow from this approach:
- A similar concept could be applied to sending an event (i.e. a qualifier is added based on a condition in the sending bean).
- You could have multiple conditions per @Observes method just by using several qualfiers.
I'd love to get feedback on this. Does this seem like it would fit your usage, Marius?
-
3. Re: Listen to @Observes only when started in a mvp presenter
mbarkley Nov 28, 2013 1:32 PM (in response to mbarkley)To follow up, there are some drawbacks to this approach I didn't think of earlier:
- It significantly changes the semantics of qualifiers.
- It would introduce different code between the client and server.
- It adds an extra complexity to the routing logic of events, which is perhaps not ideal.
Marius, would it not be possible to make your presenter @Dependent scoped and simply destroy it while a presentation isn't being used? If there's a reason why that doesn't work for you I would be interested in hearing about it.
-
4. Re: Listen to @Observes only when started in a mvp presenter
jblinick Nov 28, 2013 2:25 PM (in response to mbarkley)FWIW I agree with Christian. I don't think straying too far from the CDI spec is a good idea. For this particular requirement, it seems pretty easy to achieve the desired functionality without adding anything to the framework. You could just create a CdiObserver for the presenter, and create and destroy it as needed.
-
5. Re: Listen to @Observes only when started in a mvp presenter
jblinick Nov 28, 2013 2:53 PM (in response to marius.gerwinn)Marius,
Just as a word of caution, when we first discoved Errai CDI, we were also tempted to go a little CDI crazy. I would strongly consider looking at your use of CDI events, and perhaps reconsider bringin in Errai RPC to handle more traditional communication. CDI events are great, but trying to bend the functionality to do everything is probably not the best idea. Just my two cents...
-
6. Re: Listen to @Observes only when started in a mvp presenter
marius.gerwinn Nov 29, 2013 9:06 AM (in response to marius.gerwinn)First of all thank you very much for all that helpful input. I really appreciate that!
As I do understand so far the requested extension to cdi would be somehow possible but somehow mess up general idea of cdi and can make things complicated.
I agree with that.
Regarding the proposed solution from mike, christian and max:
Marius, would it not be possible to make your presenter @Dependent scoped and simply destroy it while a presentation isn't being used? If there's a reason why that doesn't work for you I would be interested in hearing about it.
Unfortunately this is not so easy in our case with MVP. Let me explain:
We have a big application with a lot of presenters in there. To speed up navigation (user experience) we do some prefetching and precreating of instances wherever we can.
This works pretty well since we create a presenter (the linked view and some more subpresenters) when the browser is idle. When the actually navigates to a view we call our start method and only have to do
the really necessary current context specific stuff.
We furthermore reuse a lot of views/presenters and do not fully recreate them.
For that reasons we are currently dependent on our presenter logic with start & stop.
But i think with your hints came of with a good solution for that specific problem:
I externalised all @Observes annotated methods to some inner static class. So this class is a CDIObserver class.
When i start my presenter i do create an instance of that cdi observer using the bean manager.
On stop i call destroy on that CDIObserver instance.
public class MyConcretePresenter extends MyPresenter{ @Inject AsyncBeanManager bm; MyCDIObserver myCDIObserver; @Dependent public static class MyCDIObserver extends CDIObserver<MyConcretePresenter> { void onSomeUpdate(@Observes SomeUpdateEvent event){ //DO something presenter.someVariable++; presenter.doFoo(); } } void onStart(){ bm.lookupBeans(MyCDIObserver.class).getInstance(new CreationalCallback<MyCDIObserver>(){ @Override public void callback(MyCDIObserver beanInstance) { myCDIObserver= beanInstance; myCDIObserver.setPresenter(MyConcretePresenter.this); //now listening to cdi events } }); } void onStop(){ if(myCDIObserver!=null) bm.destroyBean(myCDIObserver); //not listening to cdi events anymore } int someVariable; void doFoo(){ } }
I also wrote some helper classes and put common functionality in our custom abstract base presenter, so the concrete presenters are much cleaner than in the example.
-
7. Re: Listen to @Observes only when started in a mvp presenter
marius.gerwinn Nov 29, 2013 9:19 AM (in response to jblinick)Josh,
Thanks for your comments regarding the correct usage of CDI events. Actually we do not use CDI events for Client/Server communication at all. We basically just use them as a neat replacement for the gwt event bus. We do so since there is absolutely no boilerplate. You simple can "use any class and just fire them".
-
8. Re: Listen to @Observes only when started in a mvp presenter
jblinick Nov 29, 2013 10:12 AM (in response to marius.gerwinn)Marius,
I misread your original post. I thought you said you were replacing the errai messagebus, not the GWT Event Bus. Adding GWT events is a real pain. Depending on the design of the UI, I could see how this would be very useful.