Hi!
I'm experimenting with AsyncWeb trunk and MINA 2.0 M2 and I need some
help, because I get funny exceptions when trying to close the client
connector (see attached log).
I've created a small test case (see attachment). The IoHandler returns
the path of the request in the contents of the response -- nothing
special. The test runs fine, just as I expected. However, when
connector.dispose() is executed in line 102, I get the exceptions.
What am I doing wrong?
Thanks for your help,
Lóránt
06:55:16.625 [NioProcessor-1] DEBUG o.a.a.c.c.HttpRequestDecodingStateMachine -
Decoded header: {Connection=[Keep-Alive], Content-Length=[0],
Host=[example.com]}
06:55:16.625 [NioProcessor-1] DEBUG o.a.a.c.c.HttpRequestDecodingStateMachine -
Request is HTTP 1/1. Checking for transfer coding
06:55:16.625 [NioProcessor-1] DEBUG o.a.a.c.c.HttpRequestDecodingStateMachine -
No entity body for this request
06:55:16.640 [NioProcessor-4] DEBUG o.a.a.c.c.HttpResponseDecodingState -
Decoded header: {Connection=[Keep-Alive], Content-Length=[3], Date=[Sun, 10 Aug
2008 04:55:16 GMT]}
06:55:16.640 [NioProcessor-4] DEBUG o.a.a.c.c.HttpResponseDecodingState -
Request is HTTP 1/1. Checking for transfer coding
06:55:16.640 [NioProcessor-4] DEBUG o.a.a.c.c.HttpResponseDecodingState - Using
fixed length decoder for request with length 3
06:55:16.656 [NioProcessor-1] DEBUG o.a.a.c.c.HttpRequestDecodingStateMachine -
Decoded header: {Connection=[Keep-Alive], Content-Length=[0],
Host=[example.com]}
06:55:16.656 [NioProcessor-1] DEBUG o.a.a.c.c.HttpRequestDecodingStateMachine -
Request is HTTP 1/1. Checking for transfer coding
06:55:16.656 [NioProcessor-1] DEBUG o.a.a.c.c.HttpRequestDecodingStateMachine -
No entity body for this request
06:55:16.656 [NioProcessor-4] DEBUG o.a.a.c.c.HttpResponseDecodingState -
Decoded header: {Connection=[Keep-Alive], Content-Length=[1], Date=[Sun, 10 Aug
2008 04:55:16 GMT]}
06:55:16.656 [NioProcessor-4] DEBUG o.a.a.c.c.HttpResponseDecodingState -
Request is HTTP 1/1. Checking for transfer coding
06:55:16.656 [NioProcessor-4] DEBUG o.a.a.c.c.HttpResponseDecodingState - Using
fixed length decoder for request with length 1
06:55:16.656 [NioProcessor-1] DEBUG o.a.a.c.c.HttpRequestDecodingStateMachine -
Decoded header: {Connection=[Keep-Alive], Content-Length=[0],
Host=[example.com]}
06:55:16.656 [NioProcessor-1] DEBUG o.a.a.c.c.HttpRequestDecodingStateMachine -
Request is HTTP 1/1. Checking for transfer coding
06:55:16.656 [NioProcessor-1] DEBUG o.a.a.c.c.HttpRequestDecodingStateMachine -
No entity body for this request
06:55:16.656 [NioProcessor-4] DEBUG o.a.a.c.c.HttpResponseDecodingState -
Decoded header: {Connection=[Keep-Alive], Content-Length=[7], Date=[Sun, 10 Aug
2008 04:55:16 GMT]}
06:55:16.656 [NioProcessor-4] DEBUG o.a.a.c.c.HttpResponseDecodingState -
Request is HTTP 1/1. Checking for transfer coding
06:55:16.656 [NioProcessor-4] DEBUG o.a.a.c.c.HttpResponseDecodingState - Using
fixed length decoder for request with length 7
06:55:16.671 [NioProcessor-1] DEBUG o.a.m.f.c.s.DecodingStateMachine - Ignoring
the exception caused by a closed session.
java.lang.IllegalArgumentException: No enum const class
org.apache.asyncweb.common.HttpMethod.
at java.lang.Enum.valueOf(Enum.java:196)
at org.apache.asyncweb.common.HttpMethod.valueOf(HttpMethod.java:1)
at
org.apache.asyncweb.common.codec.HttpRequestLineDecodingState$1.finishDecode(HttpRequestLineDecodingState.java:66)
at
org.apache.mina.filter.codec.statemachine.ConsumeToDynamicTerminatorDecodingState.finishDecode(ConsumeToDynamicTerminatorDecodingState.java:103)
at
org.apache.mina.filter.codec.statemachine.DecodingStateMachine.finishDecode(DecodingStateMachine.java:151)
at
org.apache.mina.filter.codec.statemachine.DecodingStateMachine.finishDecode(DecodingStateMachine.java:151)
at
org.apache.mina.filter.codec.statemachine.DecodingStateProtocolDecoder.finishDecode(DecodingStateProtocolDecoder.java:100)
at
org.apache.mina.filter.codec.ProtocolCodecFilter.sessionClosed(ProtocolCodecFilter.java:258)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextSessionClosed(DefaultIoFilterChain.java:378)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.access$900(DefaultIoFilterChain.java:49)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.sessionClosed(DefaultIoFilterChain.java:817)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain$HeadFilter.sessionClosed(DefaultIoFilterChain.java:598)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextSessionClosed(DefaultIoFilterChain.java:378)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.fireSessionClosed(DefaultIoFilterChain.java:373)
at
org.apache.mina.core.service.IoServiceListenerSupport.fireSessionDestroyed(IoServiceListenerSupport.java:229)
at
org.apache.mina.core.polling.AbstractPollingIoProcessor.removeNow(AbstractPollingIoProcessor.java:405)
at
org.apache.mina.core.polling.AbstractPollingIoProcessor.remove(AbstractPollingIoProcessor.java:375)
at
org.apache.mina.core.polling.AbstractPollingIoProcessor.access$600(AbstractPollingIoProcessor.java:55)
at
org.apache.mina.core.polling.AbstractPollingIoProcessor$Worker.run(AbstractPollingIoProcessor.java:780)
at
org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:51)
at
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:619)
06:55:16.671 [NioProcessor-1] DEBUG o.a.m.f.c.s.DecodingStateMachine - Ignoring
the exception caused by a closed session.
java.lang.IndexOutOfBoundsException: Index: 1, Size: 0
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.get(ArrayList.java:322)
at
org.apache.asyncweb.common.codec.HttpRequestDecodingStateMachine$2.finishDecode(HttpRequestDecodingStateMachine.java:97)
at
org.apache.mina.filter.codec.statemachine.DecodingStateMachine.finishDecode(DecodingStateMachine.java:168)
at
org.apache.mina.filter.codec.statemachine.DecodingStateMachine.finishDecode(DecodingStateMachine.java:151)
at
org.apache.mina.filter.codec.statemachine.DecodingStateProtocolDecoder.finishDecode(DecodingStateProtocolDecoder.java:100)
at
org.apache.mina.filter.codec.ProtocolCodecFilter.sessionClosed(ProtocolCodecFilter.java:258)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextSessionClosed(DefaultIoFilterChain.java:378)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.access$900(DefaultIoFilterChain.java:49)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.sessionClosed(DefaultIoFilterChain.java:817)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain$HeadFilter.sessionClosed(DefaultIoFilterChain.java:598)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextSessionClosed(DefaultIoFilterChain.java:378)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.fireSessionClosed(DefaultIoFilterChain.java:373)
at
org.apache.mina.core.service.IoServiceListenerSupport.fireSessionDestroyed(IoServiceListenerSupport.java:229)
at
org.apache.mina.core.polling.AbstractPollingIoProcessor.removeNow(AbstractPollingIoProcessor.java:405)
at
org.apache.mina.core.polling.AbstractPollingIoProcessor.remove(AbstractPollingIoProcessor.java:375)
at
org.apache.mina.core.polling.AbstractPollingIoProcessor.access$600(AbstractPollingIoProcessor.java:55)
at
org.apache.mina.core.polling.AbstractPollingIoProcessor$Worker.run(AbstractPollingIoProcessor.java:780)
at
org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:51)
at
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:619)
06:55:16.671 [NioProcessor-4] DEBUG o.a.m.f.c.s.DecodingStateMachine - Ignoring
the exception caused by a closed session.
org.apache.mina.filter.codec.ProtocolDecoderException: Unexpected end of
session while waiting for a HTTP version field.
at
org.apache.asyncweb.common.codec.HttpVersionDecodingState.finishDecode(HttpVersionDecodingState.java:87)
at
org.apache.mina.filter.codec.statemachine.DecodingStateMachine.finishDecode(DecodingStateMachine.java:151)
at
org.apache.mina.filter.codec.statemachine.DecodingStateMachine.finishDecode(DecodingStateMachine.java:151)
at
org.apache.mina.filter.codec.statemachine.DecodingStateProtocolDecoder.finishDecode(DecodingStateProtocolDecoder.java:100)
at
org.apache.mina.filter.codec.ProtocolCodecFilter.sessionClosed(ProtocolCodecFilter.java:258)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextSessionClosed(DefaultIoFilterChain.java:378)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.access$900(DefaultIoFilterChain.java:49)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.sessionClosed(DefaultIoFilterChain.java:817)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain$HeadFilter.sessionClosed(DefaultIoFilterChain.java:598)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextSessionClosed(DefaultIoFilterChain.java:378)
at
org.apache.mina.core.filterchain.DefaultIoFilterChain.fireSessionClosed(DefaultIoFilterChain.java:373)
at
org.apache.mina.core.service.IoServiceListenerSupport.fireSessionDestroyed(IoServiceListenerSupport.java:229)
at
org.apache.mina.core.polling.AbstractPollingIoProcessor.removeNow(AbstractPollingIoProcessor.java:405)
at
org.apache.mina.core.polling.AbstractPollingIoProcessor.remove(AbstractPollingIoProcessor.java:375)
at
org.apache.mina.core.polling.AbstractPollingIoProcessor.access$600(AbstractPollingIoProcessor.java:55)
at
org.apache.mina.core.polling.AbstractPollingIoProcessor$Worker.run(AbstractPollingIoProcessor.java:780)
at
org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:51)
at
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:619)
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import org.apache.asyncweb.common.DefaultHttpRequest;
import org.apache.asyncweb.common.DefaultHttpResponse;
import org.apache.asyncweb.common.HttpMethod;
import org.apache.asyncweb.common.HttpRequest;
import org.apache.asyncweb.common.HttpResponse;
import org.apache.asyncweb.common.HttpResponseStatus;
import org.apache.asyncweb.common.HttpVersion;
import org.apache.asyncweb.common.codec.HttpCodecFactory;
import org.apache.mina.core.buffer.IoBufferWrapper;
import org.apache.mina.core.future.ConnectFuture;
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.transport.socket.nio.NioSocketAcceptor;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class ConnectionTest {
class ServerHandler extends IoHandlerAdapter {
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
HttpRequest request = (HttpRequest) message;
URI uri = request.getRequestUri();
DefaultHttpResponse response = new
DefaultHttpResponse();
String requestMessage = uri.toString();
response.setStatus(HttpResponseStatus.OK);
response.setContent(IoBufferWrapper.wrap(requestMessage.getBytes()));
response.normalize(request);
session.write(response);
}
}
class ClientHandler extends IoHandlerAdapter {
BlockingQueue<Object> received = new
LinkedBlockingQueue<Object>();
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
received.put(message);
}
}
private NioSocketAcceptor acceptor;
private int port;
@Before
public void init() throws IOException {
acceptor = new NioSocketAcceptor();
acceptor.getFilterChain().addLast("httpCodec", new
ProtocolCodecFilter(new HttpCodecFactory()));
acceptor.setHandler(new ServerHandler());
acceptor.setDefaultLocalAddress(new InetSocketAddress(0));
acceptor.bind();
port = acceptor.getLocalAddress().getPort();
}
@After
public void destroy() {
acceptor.unbind();
acceptor.dispose();
}
@Test
public void testConnection() throws InterruptedException,
URISyntaxException, CharacterCodingException {
NioSocketConnector connector = new NioSocketConnector();
try {
connector.getFilterChain().addLast("httpCodec", new
ProtocolCodecFilter(new HttpCodecFactory()));
ClientHandler handler = new ClientHandler();
connector.setHandler(handler);
ConnectFuture connectFuture = connector.connect(new
InetSocketAddress("127.0.0.1", port))
.awaitUninterruptibly();
IoSession session = connectFuture.getSession();
assertNotNull(session);
try {
doGetRequest(session, "hi");
doGetRequest(session, "");
doGetRequest(session, "logout");
} finally {
}
} finally {
connector.dispose();
}
}
private void doGetRequest(IoSession session, String uri) throws
URISyntaxException, InterruptedException,
CharacterCodingException {
DefaultHttpRequest request = new DefaultHttpRequest();
request.setRequestUri(new URI("http://example.com/" + uri));
request.setMethod(HttpMethod.GET);
request.setProtocolVersion(HttpVersion.HTTP_1_1);
request.setKeepAlive(true);
session.write(request);
HttpResponse response = (HttpResponse) ((ClientHandler)
session.getHandler()).received.poll(5,
TimeUnit.SECONDS);
assertNotNull(response);
String responseString =
response.getContent().getString(Charset.forName("UTF-8").newDecoder());
assertThat(responseString, equalTo("/" + uri));
}
}