Apache Mina and Spring Framework integration

In red corner we have:

Apache MINA is a network application framework which helps users develop high performance and high scalability network applications easily. It provides an abstract · event-driven · asynchronous API over various transports such as TCP/IP and UDP/IP via Java NIO.

and in blue corner:

Spring is an open source framework created to address the complexity of enterprise application development. One of the chief advantages of the Spring framework is its layered architecture, which allows you to be selective about which of its components you use while also providing a cohesive framework for J2EE application development.

Lets try to put them together. This is part of appliaction context used in project I am involved in:

  1.  
  2. ...
  3. <import resource="protocol-context.xml"/>
  4.  
  5. <bean id="minaHandler"
  6. class="pl.burningice.server.net.minaExtensions.ExtendedDemuxingIoHandler">
  7. <property name="messageHandlers" ref="handlersMapping" />
  8. </bean>
  9.  
  10. <bean id="codecFactory"
  11. class="pl.burningice.server.net.minaExtensions.ExtendedDemuxingProtocolCodecFactory">
  12. <property name="decoders" ref="decodersList" />
  13. <property name="encoders" ref="encodersList" />
  14. </bean>
  15.  
  16. <bean id="codecFilter"
  17. class="org.apache.mina.filter.codec.ProtocolCodecFilter">
  18. <constructor-arg>
  19. <ref local="codecFactory"/>
  20. </constructor-arg>
  21. </bean>
  22.  
  23. <bean id="loggingFilter"
  24. class="org.apache.mina.filter.LoggingFilter" />
  25.  
  26. <bean id="filterChainBuilder"
  27. class="org.apache.mina.integration.spring.DefaultIoFilterChainBuilderFactoryBean">
  28. <property name="filters">
  29. <list>
  30. <ref local="loggingFilter"/>
  31. <ref local="codecFilter"/>
  32. </list>
  33. </property>
  34. </bean>
  35.  
  36. <bean id="serverSocket"
  37. class="java.net.InetSocketAddress">
  38. <constructor-arg type="int" value="${server.port}" />
  39. </bean>
  40.  
  41. <bean id="minaConfig"
  42. class="org.apache.mina.transport.socket.nio.SocketAcceptorConfig">
  43. <property name="reuseAddress" value="true"/>
  44. <property name="filterChainBuilder" ref="filterChainBuilder" />
  45. </bean>
  46.  
  47. <bean id="ioAcceptor"
  48. class="org.apache.mina.transport.socket.nio.SocketAcceptor" />
  49.  
  50. <bean id="ioAcceptorDecorator"
  51. class="pl.burningice.server.net.minaExtensions.SocketAcceptorDecorator"
  52. init-method="bind"
  53. destroy-method="unbind">
  54. <constructor-arg>
  55. <ref bean="ioAcceptor"/>
  56. </constructor-arg>
  57. <property name="socketAddres" ref="serverSocket" />
  58. <property name="ioHandler" ref="minaHandler" />
  59. <property name="ioServiceConfig" ref="minaConfig" />
  60. </bean>
  61. ...
  62.  

Class SocketAcceptorDecorator is simple decorator. I used it, becouse orginal bind method require parameters, and Spring not allow to set parameters in init-method:

  1.  
  2. package pl.burningice.server.net.minaExtensions;
  3.  
  4. import java.io.IOException;
  5. import java.net.SocketAddress;
  6.  
  7. import org.apache.mina.common.IoAcceptor;
  8. import org.apache.mina.common.IoHandler;
  9. import org.apache.mina.common.IoServiceConfig;
  10.  
  11.  
  12. public class SocketAcceptorDecorator {
  13.  
  14. private SocketAddress socketAddres;
  15.  
  16. private IoHandler ioHandler;
  17.  
  18. private IoServiceConfig ioServiceConfig;
  19.  
  20. private IoAcceptor socketAcceptor;
  21.  
  22. public SocketAcceptorDecorator(IoAcceptor socketAcceptor){
  23. this.socketAcceptor = socketAcceptor;
  24. }
  25.  
  26. public void setSocketAddres(SocketAddress socketAddres) {
  27. this.socketAddres = socketAddres;
  28. }
  29.  
  30. public SocketAddress getSocketAddres() {
  31. return socketAddres;
  32. }
  33.  
  34. public void setIoHandler(IoHandler ioHandler) {
  35. this.ioHandler = ioHandler;
  36. }
  37.  
  38. public IoHandler getIoHandler() {
  39. return ioHandler;
  40. }
  41.  
  42. public void setIoServiceConfig(IoServiceConfig ioServiceConfig) {
  43. this.ioServiceConfig = ioServiceConfig;
  44. }
  45.  
  46. public IoServiceConfig getIoServiceConfig() {
  47. return ioServiceConfig;
  48. }
  49.  
  50. public void bind() throws IOException{
  51. socketAcceptor.bind(getSocketAddres(), getIoHandler(), getIoServiceConfig());
  52. }
  53.  
  54. public void unbind(){
  55. socketAcceptor.unbind(getSocketAddres());
  56. }
  57. }
  58.  
  59.  

Class ExtendedDemuxingProtocolCodecFactory extendeds class DemuxingProtocolCodecFactory and define methods that allow us to set encoders and decoders from list:

  1.  
  2. package pl.burningice.server.net.minaExtensions;
  3.  
  4. import java.util.List;
  5.  
  6. import org.apache.mina.filter.codec.demux.DemuxingProtocolCodecFactory;
  7. import org.apache.mina.filter.codec.demux.MessageDecoder;
  8. import org.apache.mina.filter.codec.demux.MessageEncoder;
  9.  
  10. public class ExtendedDemuxingProtocolCodecFactory extends DemuxingProtocolCodecFactory {
  11.  
  12. public void setEncoders(List<messageEncoder> encoders){
  13. for (MessageEncoder messageEncoder : encoders) {
  14. register(messageEncoder);
  15. }
  16. }
  17.  
  18. public void setDecoders(List<messageDecoder> decoders){
  19. for (MessageDecoder messageDecoder : decoders) {
  20. register(messageDecoder);
  21. }
  22. }
  23. }
  24.  

Similar situation with ExtendedDemuxingIoHandler class where I extended DemuxingIoHandler class add defined method to set message handlers from map:

  1.  
  2. package pl.burningice.server.net.minaExtensions;
  3.  
  4. import java.util.Map;
  5. import java.util.Map.Entry;
  6.  
  7. import org.apache.mina.handler.demux.DemuxingIoHandler;
  8. import org.apache.mina.handler.demux.MessageHandler;
  9.  
  10. public class ExtendedDemuxingIoHandler extends DemuxingIoHandler {
  11.  
  12. @SuppressWarnings("unchecked")
  13. public void setMessageHandlers(Map<class, MessageHandler> messageHandlers){
  14. for (Entry<class, MessageHandler> element : messageHandlers.entrySet()) {
  15. addMessageHandler(element.getKey(), element.getValue());
  16. }
  17. }
  18. }
  19.  

In protocol-context.xml file I stored handlersMapping, decodersList and encodersList beans:

  1.  
  2. ...
  3. <bean id="handlersMapping" class="java.util.HashMap">
  4. <constructor-arg>
  5. <map>
  6. <entry key="pl.burningice.server.net.protocol.request.LoginRequest">
  7. <bean class="pl.burningice.server.net.protocol.handler.LoginRequestHandler"></bean>
  8. </entry>
  9. </map>
  10. </constructor-arg>
  11. </bean>
  12.  
  13. <bean id="decodersList" class="java.util.ArrayList">
  14. <constructor-arg>
  15. <list>
  16. <bean class="pl.burningice.server.net.protocol.decoder.LoginRequestDecoder" />
  17. </list>
  18. </constructor-arg>
  19. </bean>
  20.  
  21. <bean id="encodersList" class="java.util.ArrayList">
  22. <constructor-arg>
  23. <list>
  24. <bean class="pl.burningice.server.net.protocol.encoder.LoginRequestEncoder" />
  25. </list>
  26. </constructor-arg>
  27. </bean>
  28.  

I used separate xml file, becouse only protocol-context.xml will be upadated - xml containing integration data will be const.
If there is better way to integrate both frameworks, please let me know.

Powered by WordPress with GimpStyle Theme design by Horacio Bella.
Entries and comments feeds. Valid XHTML and CSS.