Hello all,
I am using Mina 0.9.5 in a client/server app and experience a strange
problem with my implementation of the IoHandler: whenever I send a
message, it passes my encoder just fine and log statements indicate that
the message is properly written out. After that I put a log statement in
the messageSent() method of my IoHandler implementation - but this method
gets called several times for one single message. The reverse is true for
the receiver. The message decoder reads the data correctly and logs
whenever a message was received in its entirety. After that
messageReceived is invoked several times for the same message. I don't
have a clue if that is correct but I do not think so.
My server starts like this:
SSLFilter sslFilter = new
SSLFilter(this.sslContextFactory.getServerContext());
sslFilter.setNeedClientAuth(true);
sslFilter.setWantClientAuth(true);
IoAcceptorConfig config = new
SocketAcceptorConfig();
DefaultIoFilterChainBuilder chain =
config.getFilterChain();
SocketAcceptor acceptor = new
SocketAcceptor();
ThreadPoolFilter ioThreadPoolFilter = new
ThreadPoolFilter();
ThreadPoolFilter protocolThreadPoolFilter
= new ThreadPoolFilter();
chain.addFirst("ioThreadPool",
ioThreadPoolFilter);
chain.addLast("protocolThreadPool",
protocolThreadPoolFilter);
chain.addLast("sslFilter", sslFilter);
acceptor.bind(<socketAddress>, new
GenericSessionHandler(this), config);
My clients connect to the server like this:
ThreadPoolFilter ioThreadPoolFilter = new
ThreadPoolFilter();
ThreadPoolFilter protocolThreadPoolFilter = new
ThreadPoolFilter();
// get an SSL client context
SSLFilter sslFilter = new
SSLFilter(this.sslContext.getClientContext());
sslFilter.setUseClientMode(true);
// create the session (the connector gets reused
after sessions are closed)
this.connector = new SocketConnector();
// set the timeout
((IoConnectorConfig)
connector.getDefaultConfig()).setConnectTimeout(60);
connector.getFilterChain().addFirst("ioThreadPool", ioThreadPoolFilter);
connector.getFilterChain().addLast("protocolThreadPool",
protocolThreadPoolFilter);
connector.getFilterChain().addLast("sslFilter",
sslFilter);
ConnectFuture future = connector.connect(new
InetSocketAddress(address, port, new GenericSessionHandler(this));
// wait until the connection is established
future.join();
// the connection should be established by now...
if (!future.isConnected())
throw new
CommunicationServiceException("...");
// use this session
this.session = future.getSession();
The generic session handler is the same for client and server and looks
like this:
public class GenericSessionHandler implements IoHandler {
private final Log logger =
LogFactory.getLog(GenericSessionHandler.class);
private final SessionStateListener listener;
public GenericSessionHandler(SessionStateListener ssl) {
this.listener = ssl;
}
public void sessionCreated(IoSession session) throws Exception {
ProtocolCodecFactory codec = new SimpleFactory();
session.getFilterChain().addLast("protocolFilter",
new ProtocolCodecFilter(codec));
if (logger.isDebugEnabled()) {
logger
.debug(MessageFormat
.format(
"a
new communication session was created with peer at address {0}",
session.getRemoteAddress()));
}
}
public void sessionOpened(IoSession session) throws Exception {
if (logger.isDebugEnabled()) {
logger
.debug(MessageFormat
.format(
"a
communication session was opened with peer at address {0}",
session.getRemoteAddress()));
}
this.listener.sessionCreated(session);
}
public void sessionClosed(IoSession session) throws Exception {
if (logger.isDebugEnabled()) {
logger
.debug(MessageFormat
.format(
"communication session was closed with peer at address {0} - amount of
data transferred was {1} byte(s)",
session.getRemoteAddress(), session
.getWrittenBytes()));
}
this.listener.sessionClosed(session);
}
public void sessionIdle(IoSession session, IdleStatus status)
throws Exception {
this.listener.sessionIdle(session, status);
}
private void closeSession(IoSession session) {
try {
session.close();
} catch (Exception e) {
logger.error("exception while closing session",
e);
this.listener.sessionClosed(session);
}
}
public void exceptionCaught(IoSession session, Throwable e)
throws Exception {
if (logger.isDebugEnabled()) {
logger.debug("caught exception while processing
session", e);
}
this.listener.sessionException(session, e);
closeSession(session);
}
public void messageReceived(IoSession session, Object message)
throws Exception {
if (!(message instanceof Envelope)) {
if (logger.isDebugEnabled()) {
logger.debug(MessageFormat.format(
"received unknown object
from peer: {0}", message));
}
return;
}
if (logger.isDebugEnabled()) {
logger.debug(MessageFormat.format("message
received with UID = {0} and type = {1}", ((Envelope)
message).getRequestUid(), ((Envelope) message).getType()));
}
this.listener.objectReceived(session, message);
}
public void messageSent(IoSession session, Object message) throws
Exception {
if (logger.isDebugEnabled()) {
logger.debug(MessageFormat.format("message sent
with UID = {0} and type = {1}", ((Envelope) message).getRequestUid(),
((Envelope) message).getType()));
}
}
}
(note that Envelope is the base class of all my messages and contains a
UID)
I would never have bothered to post this here because the system worked
fine for more than 4 month. But recently I upgraded to Mina 0.9.5 and
experienced another strange problem: sometimes the last message of a
communication session is received by the client when it tries to send
another message to the server. This occurs only randomly and always
affects the last message. My client is only able to receive that last
message when it sends another message - is this behaviour intended?
Sorry for the long post, but I am stuck here...
Thanks in advance,
Sven
Information contained in this message is confidential and may be legally
privileged. If you are not the addressee indicated in this message (or
responsible for the delivery of the message to such person), you may not copy,
disclose or deliver this message or any part of it to anyone, in any form. In
such case, you should delete this message and kindly notify the sender by reply
Email. Opinions, conclusions and other information in this message that do not
relate to the official business of Proximity shall be understood as neither
given nor endorsed by it.