Note that there are some explanatory texts on larger screens.

plurals
  1. POMessage routing/handling with custom annotations and CDI injection
    text
    copied!<p>I have a Java EE 6 web application and use the WebSocket protocol to communicate with browsers. The browser can send various types of messages and in the servers <i>onMessage</i> method I would like to route (or dispatch) the message to a specific message handler class depending on the message type. I would like to configure or register these message handlers via annotations, similar to the mechanism of servlets (@WebServlet("/there")). And like in servlets, I would like to be able to use CDI injection in the message handlers.</p> <p>For now I have a <i>MessageType</i> annotation, a <i>MessageHandler</i> interface and 3 implementations.</p> <pre><code>@Documented @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface MessageType { String value(); } public interface MessageHandler { public void processMessage(String inputMesssage); } @MessageType("first") public class FirstMessageHandler implements MessageHandler { @Inject ResourceBundleProvider resourceBundleProvider; @Override public void processMessage(String inputMesssage) { System.out.println("FirstMessageHandler#processMessage: " + inputMesssage); System.out.println("InjectionTest: " + resourceBundleProvider.getValue("label.language")); } } @MessageType("second") public class SecondMessageHandler implements MessageHandler { @Override public void processMessage(String inputMesssage) { System.out.println("SecondMessageHandler#processMessage: " + inputMesssage); } } public class DefaultMessageHandler implements MessageHandler { @Override public void processMessage(String inputMesssage) { System.out.println("DefaultMessageHandler#processMessage: " + inputMesssage); } } </code></pre> <p>I also have a class <i>MessageDispatcher</i> which uses <a href="http://code.google.com/p/reflections/" rel="nofollow">reflections</a> to scan the classpath for the annotated message handlers, instantiates them and puts them into a map:</p> <pre><code>@ApplicationScoped public class MessageDispatcher { private Map&lt;String, MessageHandler&gt; messageHandlerMap = new HashMap&lt;String, MessageHandler&gt;(); @Inject DefaultMessageHandler defaultMessageHandler; public MessageDispatcher() { registerAnnotatedHandlers(); } private void registerAnnotatedHandlers() { Reflections reflections = new Reflections("namespace"); try { for (Class&lt;?&gt; annotatedClass : reflections.getTypesAnnotatedWith(MessageType.class)) { String annotationValue = annotatedClass.getAnnotation(MessageType.class).value(); for (Class&lt;?&gt; interfaceClass : annotatedClass.getInterfaces()) if (!annotationValue.isEmpty() &amp;&amp; interfaceClass.equals(MessageHandler.class)) messageHandlerMap.put(annotationValue, (MessageHandler) annotatedClass.newInstance()); } } catch (Exception e) { e.printStackTrace(); } } public MessageHandler getMessageHandler(String key) { MessageHandler messageHandler = messageHandlerMap.get(key); return messageHandler != null ? messageHandler : defaultMessageHandler; } } </code></pre> <p>And finally in my websocket servlet's <i>onMessage</i> method I extract the key from the inbound message and use it for the message routing:</p> <pre><code>public synchronized void onMessage(String data) { String[] message = data.split(":"); // Choose the message handler from the message MessageHandler messageHandler = messageDispatcher.getMessageHandler(message[0]); // Process the message by the message handler messageHandler.processMessage(message[1]); } </code></pre> <p>My 3 incoming sample messages are:</p> <pre><code>"first:Message to handle with FirstMessageHandler" "second:Message to handle with SecondMessageHandler" "third:Message to handle with DefaultMessageHandler" </code></pre> <p>This works fine, The first and second messages are processed by FirstMessageHandler and SecondMessageHandler respectively. The third message is processed by the default message handler since there is no other handler registered for handling the key "third".</p> <p><b>My Problem:</b> I cannot use injection in the message handlers because they are created using Java reflection. Does anybody know how to get annotation processing and CDI injection 'married'? Or does anybody think this approach is bullshit and has another solution for that?</p> <p>Best Regards<br /> Sebastian</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload