MINA(3)Understand MINA2 and Calculate Spring Example
1. Process
read in data --------> IoAcceptor
write out data IoConnector ----------> Thread Pool(IoProcessor) --------> IoFilter IoFilter ExecutorFilter ---> IoHandler
Read in Data
IO ---> IoProcessor ----> logging, decode, thread pool (IoFilter) -----> IoHandler(business logic)
Write out Data
IoHandler(business logic) ----> logging, encode, thread pool (IoFilter) -----> IO (IoProcessor)
2. Threads
IoAcceptor/IoConnector
IoProcessor
IoHandler
IoAcceptor/IoConnector
IoAcceptor will accept the connection from client, it will create one thread per one port. IoConnector will use for create connection to server side.
IoProcessor
IoProcessor will handle the IO things for IoAcceptor and IoConnector.
IoConnector connector = new NioSocketConnector(9);
IoAcceptor acceptor = new NioSocketAcceptor(9);
IoHandler
Event of creating Thread and running Thread
IoAcceptor/IoConnector Pool ------> IoProcessor Pool
IoAcceptor/IoConnector create socket connection (IoAcceptor bind(), IoConnector.connect()), system will get a thread from pool, binding or connecting the socket channal.
IoAcceptor/IoConnector received the socket request, system create IoSession object, get one thread from IoProccessor, handle the IO task.
Handle the IoHandler from thread pool if the system configured one.
2. Make it works with Spring with a Simple Example
Using the Calculate Example
pom.xml as follow:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.6</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-integration-spring</artifactId>
<version>1.1.7</version>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-integration-beans</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
...snip...
<build>
<finalName>easynio</finalName>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
</plugin>
</plugins>
</build>
The spring Configuration file is as follow:
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer" >
<property name="customEditors" >
<map>
<entry key="java.net.SocketAddress" >
<bean class="org.apache.mina.integration.beans.InetSocketAddressEditor" />
</entry>
</map>
</property>
</bean>
<!-- The IoHandler implementation -->
<bean id="calculateHandler" class="com.sillycat.easynio.plugins.mina.businesshandlers.CalculateHandler" />
<!-- the IoFilters -->
<bean id="executorFilter" class="org.apache.mina.filter.executor.ExecutorFilter" />
<bean id="mdcInjectionFilter" class="org.apache.mina.filter.logging.MdcInjectionFilter" >
<constructor-arg value="remoteAddress" />
</bean>
<bean id="codecFilter" class="org.apache.mina.filter.codec.ProtocolCodecFilter" >
<constructor-arg>
<bean class="org.apache.mina.filter.codec.textline.TextLineCodecFactory" />
</constructor-arg>
</bean>
<bean id="loggingFilter" class="org.apache.mina.filter.logging.LoggingFilter" />
<!-- The non-SSL filter chain. -->
<bean id="filterChainBuilder" class="org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder" >
<property name="filters" >
<map>
<entry key="executor" value-ref="executorFilter" />
<entry key="mdcInjectionFilter" value-ref="mdcInjectionFilter" />
<entry key="codecFilter" value-ref="codecFilter" />
<entry key="loggingFilter" value-ref="loggingFilter" />
</map>
</property>
</bean>
<!-- The IoAcceptor which binds to port 1235 server side -->
<bean id="minaAcceptor" class="org.apache.mina.transport.socket.nio.NioSocketAcceptor"
destroy-method="unbind" init-method="bind" >
<property name="defaultLocalAddress" value=":12345" />
<property name="handler" ref="calculateHandler" />
<property name="reuseAddress" value="true" />
<property name="filterChainBuilder" ref="filterChainBuilder" />
</bean>
The business logic handler class is as follow:
package com.sillycat.easynio.plugins.mina.businesshandlers;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CalculateHandler extends IoHandlerAdapter {
private final Logger logger = LoggerFactory.getLogger(getClass());
private ScriptEngine jsEngine = null;
public CalculateHandler() {
ScriptEngineManager sfm = new ScriptEngineManager();
jsEngine = sfm.getEngineByName("JavaScript");
if (jsEngine == null) {
throw new RuntimeException("No Java Script Engine.");
}
}
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
logger.warn(cause.getMessage(), cause);
}
public void messageReceived(IoSession session, Object message)
throws Exception {
String expression = message.toString();
if ("quit".equalsIgnoreCase(expression.trim())) {
session.write("Closing the session!".toString());
session.close(true);
return;
}
try {
Object result = jsEngine.eval(expression);
if(result != null){
session.write(result.toString());
}else{
session.write("No result!");
}
} catch (ScriptException e) {
logger.warn(e.getMessage(), e);
session.write("Wrong expression, try again.");
}
}
}
error message
Missing artifact org.apache.mina:mina-core:bundle:2.0.4
solution
<build>
<finalName>easynio</finalName>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
</plugin>
</plugins>
</build>
We can use the telnet tool on win7 to verify the 3 + 3 = 6 or some other calculating things.
Or we can use client class as follow:
package com.sillycat.easynio.plugins.mina.businesshandlers;
import org.apache.mina.core.filterchain.IoFilter;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
public class CalculateClientHandler extends IoHandlerAdapter {
private static final IoFilter LOGGING_FILTER = new LoggingFilter();
private static final IoFilter CODEC_FILTER = new ProtocolCodecFilter(
new TextLineCodecFactory());
public void sessionCreated(IoSession session) throws Exception {
session.getFilterChain().addLast("codec", CODEC_FILTER);
session.getFilterChain().addLast("logger", LOGGING_FILTER);
}
public void messageReceived(IoSession session, Object message)
throws Exception {
String msg = (String) message;
System.out.println("Client Received: " + msg);
}
}
package com.sillycat.easynio.plugins.mina.client;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.logging.MdcInjectionFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import com.sillycat.easynio.plugins.mina.businesshandlers.CalculateClientHandler;
public class MinaClientSupport {
private IoHandler handler = null;
private String host;
private IoSession session = null;
private int port;
public boolean send(Object message) {
SocketAddress address = new InetSocketAddress(host, port);
NioSocketConnector connector = new NioSocketConnector();
try {
if (session == null) {
connector.getFilterChain().addLast("mdc",
new MdcInjectionFilter());
connector.setHandler(handler);
ConnectFuture future1 = connector.connect(address);
future1.awaitUninterruptibly();
if (!future1.isConnected()) {
return false;
}
session = future1.getSession();
}
session.write(message);
return true;
} catch (Exception e) {
return false;
}
}
public void close() {
if (session != null) {
if (session.isConnected()) {
// Wait until the chat ends.
session.getCloseFuture().awaitUninterruptibly();
}
session.close(true);
}
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public void setHandler(IoHandler handler) {
this.handler = handler;
}
public static void main(String[] args) throws InterruptedException {
System.out.println("Application Test:");
MinaClientSupport client = new MinaClientSupport();
CalculateClientHandler handler = new CalculateClientHandler();
client.setHandler(handler);
client.setHost("localhost");
client.setPort(12345);
String msg = "1+3*6";
client.send(msg);
System.out.println("Client Send: " + msg);
client.send("quit");
client.close();
}
}
references:
http://www.blogjava.net/mikechen/archive/2012/03/15/371938.html
http://www.iteye.com/topic/1112123
http://sillycat.iteye.com/blog/563765
http://www.ibm.com/developerworks/cn/java/j-lo-mina2/index.html
http://svn.apache.org/viewvc/mina/branches/1.0/example/src/main/java/org/apache/mina/example/chat/
http://mina.apache.org/user-guide.html
http://blog.csdn.net/jialechan/article/details/6821389
1. Process
read in data --------> IoAcceptor
write out data IoConnector ----------> Thread Pool(IoProcessor) --------> IoFilter IoFilter ExecutorFilter ---> IoHandler
Read in Data
IO ---> IoProcessor ----> logging, decode, thread pool (IoFilter) -----> IoHandler(business logic)
Write out Data
IoHandler(business logic) ----> logging, encode, thread pool (IoFilter) -----> IO (IoProcessor)
2. Threads
IoAcceptor/IoConnector
IoProcessor
IoHandler
IoAcceptor/IoConnector
IoAcceptor will accept the connection from client, it will create one thread per one port. IoConnector will use for create connection to server side.
IoProcessor
IoProcessor will handle the IO things for IoAcceptor and IoConnector.
IoConnector connector = new NioSocketConnector(9);
IoAcceptor acceptor = new NioSocketAcceptor(9);
IoHandler
Event of creating Thread and running Thread
IoAcceptor/IoConnector Pool ------> IoProcessor Pool
IoAcceptor/IoConnector create socket connection (IoAcceptor bind(), IoConnector.connect()), system will get a thread from pool, binding or connecting the socket channal.
IoAcceptor/IoConnector received the socket request, system create IoSession object, get one thread from IoProccessor, handle the IO task.
Handle the IoHandler from thread pool if the system configured one.
2. Make it works with Spring with a Simple Example
Using the Calculate Example
pom.xml as follow:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.6</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-integration-spring</artifactId>
<version>1.1.7</version>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-integration-beans</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.1.2.RELEASE</version>
</dependency>
...snip...
<build>
<finalName>easynio</finalName>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
</plugin>
</plugins>
</build>
The spring Configuration file is as follow:
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer" >
<property name="customEditors" >
<map>
<entry key="java.net.SocketAddress" >
<bean class="org.apache.mina.integration.beans.InetSocketAddressEditor" />
</entry>
</map>
</property>
</bean>
<!-- The IoHandler implementation -->
<bean id="calculateHandler" class="com.sillycat.easynio.plugins.mina.businesshandlers.CalculateHandler" />
<!-- the IoFilters -->
<bean id="executorFilter" class="org.apache.mina.filter.executor.ExecutorFilter" />
<bean id="mdcInjectionFilter" class="org.apache.mina.filter.logging.MdcInjectionFilter" >
<constructor-arg value="remoteAddress" />
</bean>
<bean id="codecFilter" class="org.apache.mina.filter.codec.ProtocolCodecFilter" >
<constructor-arg>
<bean class="org.apache.mina.filter.codec.textline.TextLineCodecFactory" />
</constructor-arg>
</bean>
<bean id="loggingFilter" class="org.apache.mina.filter.logging.LoggingFilter" />
<!-- The non-SSL filter chain. -->
<bean id="filterChainBuilder" class="org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder" >
<property name="filters" >
<map>
<entry key="executor" value-ref="executorFilter" />
<entry key="mdcInjectionFilter" value-ref="mdcInjectionFilter" />
<entry key="codecFilter" value-ref="codecFilter" />
<entry key="loggingFilter" value-ref="loggingFilter" />
</map>
</property>
</bean>
<!-- The IoAcceptor which binds to port 1235 server side -->
<bean id="minaAcceptor" class="org.apache.mina.transport.socket.nio.NioSocketAcceptor"
destroy-method="unbind" init-method="bind" >
<property name="defaultLocalAddress" value=":12345" />
<property name="handler" ref="calculateHandler" />
<property name="reuseAddress" value="true" />
<property name="filterChainBuilder" ref="filterChainBuilder" />
</bean>
The business logic handler class is as follow:
package com.sillycat.easynio.plugins.mina.businesshandlers;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CalculateHandler extends IoHandlerAdapter {
private final Logger logger = LoggerFactory.getLogger(getClass());
private ScriptEngine jsEngine = null;
public CalculateHandler() {
ScriptEngineManager sfm = new ScriptEngineManager();
jsEngine = sfm.getEngineByName("JavaScript");
if (jsEngine == null) {
throw new RuntimeException("No Java Script Engine.");
}
}
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
logger.warn(cause.getMessage(), cause);
}
public void messageReceived(IoSession session, Object message)
throws Exception {
String expression = message.toString();
if ("quit".equalsIgnoreCase(expression.trim())) {
session.write("Closing the session!".toString());
session.close(true);
return;
}
try {
Object result = jsEngine.eval(expression);
if(result != null){
session.write(result.toString());
}else{
session.write("No result!");
}
} catch (ScriptException e) {
logger.warn(e.getMessage(), e);
session.write("Wrong expression, try again.");
}
}
}
error message
Missing artifact org.apache.mina:mina-core:bundle:2.0.4
solution
<build>
<finalName>easynio</finalName>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
</plugin>
</plugins>
</build>
We can use the telnet tool on win7 to verify the 3 + 3 = 6 or some other calculating things.
Or we can use client class as follow:
package com.sillycat.easynio.plugins.mina.businesshandlers;
import org.apache.mina.core.filterchain.IoFilter;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.logging.LoggingFilter;
public class CalculateClientHandler extends IoHandlerAdapter {
private static final IoFilter LOGGING_FILTER = new LoggingFilter();
private static final IoFilter CODEC_FILTER = new ProtocolCodecFilter(
new TextLineCodecFactory());
public void sessionCreated(IoSession session) throws Exception {
session.getFilterChain().addLast("codec", CODEC_FILTER);
session.getFilterChain().addLast("logger", LOGGING_FILTER);
}
public void messageReceived(IoSession session, Object message)
throws Exception {
String msg = (String) message;
System.out.println("Client Received: " + msg);
}
}
package com.sillycat.easynio.plugins.mina.client;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.logging.MdcInjectionFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import com.sillycat.easynio.plugins.mina.businesshandlers.CalculateClientHandler;
public class MinaClientSupport {
private IoHandler handler = null;
private String host;
private IoSession session = null;
private int port;
public boolean send(Object message) {
SocketAddress address = new InetSocketAddress(host, port);
NioSocketConnector connector = new NioSocketConnector();
try {
if (session == null) {
connector.getFilterChain().addLast("mdc",
new MdcInjectionFilter());
connector.setHandler(handler);
ConnectFuture future1 = connector.connect(address);
future1.awaitUninterruptibly();
if (!future1.isConnected()) {
return false;
}
session = future1.getSession();
}
session.write(message);
return true;
} catch (Exception e) {
return false;
}
}
public void close() {
if (session != null) {
if (session.isConnected()) {
// Wait until the chat ends.
session.getCloseFuture().awaitUninterruptibly();
}
session.close(true);
}
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public void setHandler(IoHandler handler) {
this.handler = handler;
}
public static void main(String[] args) throws InterruptedException {
System.out.println("Application Test:");
MinaClientSupport client = new MinaClientSupport();
CalculateClientHandler handler = new CalculateClientHandler();
client.setHandler(handler);
client.setHost("localhost");
client.setPort(12345);
String msg = "1+3*6";
client.send(msg);
System.out.println("Client Send: " + msg);
client.send("quit");
client.close();
}
}
references:
http://www.blogjava.net/mikechen/archive/2012/03/15/371938.html
http://www.iteye.com/topic/1112123
http://sillycat.iteye.com/blog/563765
http://www.ibm.com/developerworks/cn/java/j-lo-mina2/index.html
http://svn.apache.org/viewvc/mina/branches/1.0/example/src/main/java/org/apache/mina/example/chat/
http://mina.apache.org/user-guide.html
http://blog.csdn.net/jialechan/article/details/6821389