goal
I am trying to create a MessageDispatcher that converts messages from a third-party API into user messages and then sends them to a user registered as a user.
The user will expect:
- Define an interface for each type of user message.
- Register a listener with a message manager for each type of message.
- Transfer raw / third-party data to the message manager.
- Process messages sent to listeners.
Description of the problem
Unfortunately, I cannot avoid using a raw type to achieve my desired API. I read elsewhere that there are no exceptional cases of using Raw types, and they exist only in the language for backward compatibility.
Is there a way to change the code below to work or do I need to reverse engineer my API?
Interfaces
MessageDispatcher implements the following interface:
public interface MessageDispatcher {
The MessageListener interface is defined as:
public interface MessageListener<T> { public void onMessage(T message); }
An example user message might look like this:
public interface MyMessage { public String getName(); }
Register listeners
A user can register a listener as follows:
messageDispatcher.registerListener(MyMessage.class, new MessageListener<MyMessage.class>() { @Override public void onMessage(MyMessage message) { System.out.println("Hello " + message.getName()); } }
A standard message manager can implement this method:
private Map<Class<?>,MessageListener<?>> messageClassToListenerMap; public <T> void registerListener( Class<T> messageClass, MessageListener<T> listener) { messageClassToListenerMap.put(messageClass, listener);
Sending messages
When a new message receives a MessageDispatcher, it creates a dynamic proxy for the object and sends it to the appropriate listener. But this is my problem:
public void onData(Data data) {
If I try to use a type, I cannot send data:
This makes sense because I just can't figure out what types of data my listener accepts and what data types I pass to him.
But if I use raw types, it works fine: