Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic messages are delivered to all handlers of the class #83

Open
littledot opened this issue Oct 10, 2014 · 3 comments
Open

Generic messages are delivered to all handlers of the class #83

littledot opened this issue Oct 10, 2014 · 3 comments

Comments

@littledot
Copy link

Hi bennidi, first of all, thanks for all your hard work on the project.
I'm using MBassador 1.2 and I have a question regarding passing generic messages.

Suppose I have a class that supports generics

public class GenericEvent<T> {

    Class<T> mClass;

    public GenericEvent(Class<T> clazz) {
        mClass = clazz;
    }

    @Override
    public String toString() {
        return mClass.getCanonicalName();
    }
}

When I publish a GenericEvent, I notice that all handlers for GenericEvent gets called. For example, the following code:

    private void busTest() {
        Bus.publish(new GenericEvent<List>(List.class));
        Bus.publish(new GenericEvent<ArrayList>(ArrayList.class));
    }
    @Handler
    public void onGenEvent(GenericEvent e) {
        Leg.a("" + e);
    }

    @Handler
    public void onGenEventQuestion(GenericEvent<?> e) {
        Leg.a("" + e);
    }

    @Handler
    public void onGenEventList(GenericEvent<List> e) {
        Leg.a("" + e);
    }

    @Handler
    public void onGenEventMap(GenericEvent<Map> e) {
        Leg.a("" + e);
    }

    @Handler
    public void onGenEventArrayList(GenericEvent<ArrayList> e) {
        Leg.a("" + e);
    }

    @Handler
    public void onGenEventHashMap(GenericEvent<HashMap> e) {
        Leg.a("" + e);
    }

produces the following output:

10-10 22:25:28.384    1890-1890/com.sdchang.testbed A/BaseActivity#73 (onGenEventArrayList)﹕ java.util.List
10-10 22:25:28.384    1890-1890/com.sdchang.testbed A/BaseActivity#53 (onGenEvent)﹕ java.util.List
10-10 22:25:28.384    1890-1890/com.sdchang.testbed A/BaseActivity#78 (onGenEventHashMap)﹕ java.util.List
10-10 22:25:28.392    1890-1890/com.sdchang.testbed A/BaseActivity#63 (onGenEventList)﹕ java.util.List
10-10 22:25:28.392    1890-1890/com.sdchang.testbed A/BaseActivity#58 (onGenEventQuestion)﹕ java.util.List
10-10 22:25:28.392    1890-1890/com.sdchang.testbed A/BaseActivity#68 (onGenEventMap)﹕ java.util.List
10-10 22:25:28.396    1890-1890/com.sdchang.testbed A/BaseActivity#73 (onGenEventArrayList)﹕ java.util.ArrayList
10-10 22:25:28.396    1890-1890/com.sdchang.testbed A/BaseActivity#53 (onGenEvent)﹕ java.util.ArrayList
10-10 22:25:28.396    1890-1890/com.sdchang.testbed A/BaseActivity#78 (onGenEventHashMap)﹕ java.util.ArrayList
10-10 22:25:28.396    1890-1890/com.sdchang.testbed A/BaseActivity#63 (onGenEventList)﹕ java.util.ArrayList
10-10 22:25:28.396    1890-1890/com.sdchang.testbed A/BaseActivity#58 (onGenEventQuestion)﹕ java.util.ArrayList
10-10 22:25:28.400    1890-1890/com.sdchang.testbed A/BaseActivity#68 (onGenEventMap)﹕ java.util.ArrayList

Is this expected?
I hope that only handlers with classes that are compatible with the message are called.

Thank you.

@paulpdaniels
Copy link

I would imagine this is because of Java Type Erasure. Since mbassador uses reflection, the generic types are lost when the handlers are looked up.

@bennidi
Copy link
Owner

bennidi commented Oct 11, 2014

Hi Paul,
you assume correctly that the behaviour you describe is expected. The reason is, as you pointed out, the result of Java Type Erasure. However, it has nothing to do with the use of reflection because generic types of method signatures are preserved and available to the reflection API. What you can not do is get the actual generic type of an object at runtime when it is not part of its signature. Example:

class CustomEvent<T>{}

class SimpleEvent extends CustomEvent<Integer> {
// the generic type of instances of this class WILL be available at runtime
}

public void handle(CustomEvent event){}

// when you call
handle(new SimpleEvent()); // then inspecting the generic parameter will give you "Integer" because the generic type is part of the class signature
// but when you call
handle(new CustomEvent<Integer>()); // then the inspection will yield "T" --> the actual type has been erased

Check out this post to see how to get generic type parameters of methods.

But MBassador DOES NOT YET SUPPORT the inspection of generic types at all, so you have to use subclasses or the Java EL filtering mechanism.

@paulpdaniels
Copy link

Ah, very interesting! I stand corrected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants