Close BufferedReader.readLine() in SSLSocket? - java

I have this one:
while(SD.SessionAlive)
{
timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
try
{
SD.closeSession();
}
catch(Exception e)
{
}
}
}, timeToRun);
String InputData = SD.ClientSocketReader.readLine();
timer.cancel();
if(InputData!=null)
{
commandHandler(InputData);
}
}
In this case, I need listen input data from BufferedReader.
If client dont send anything, after 30 seconds, session must be closed.
When I use no SSL conenction, I close session using shutdownInput and shutdownOutput.
But when I use SSL connection, I can use shutdownInput and shutdownOutput: "The method shutdownInput() is not supported in SSLSocket".
And when I use BufferedReader.close(), session wait closing....
Name: smie
State: RUNNABLE
Total blocked: 0 Total waited: 0
Stack trace:
java.net.SocketInputStream.socketRead0(Native Method)
java.net.SocketInputStream.read(SocketInputStream.java:129)
com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:293)
com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:331)
com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:798)
- locked java.lang.Object#37f8d244
com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:755)
com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:75)
- locked com.sun.net.ssl.internal.ssl.AppInputStream#30b48b11
sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
- locked java.io.InputStreamReader#2fa6a1a7
java.io.InputStreamReader.read(InputStreamReader.java:167)
java.io.BufferedReader.fill(BufferedReader.java:136)
java.io.BufferedReader.readLine(BufferedReader.java:299)
- locked java.io.InputStreamReader#2fa6a1a7
java.io.BufferedReader.readLine(BufferedReader.java:362)
org.smie.ftpex.SessionHandler.run(SessionHandler.java:71)
where SessionHandler.java:71 is:
String InputData = SD.ClientSocketReader.readLine();
How I can close in and out streams?

Related

Java/Android: Socket closed when offloading work to a thread pool

I'm experiencing a very puzzling error writing a thread-pooled TCP server on Android. Basically, my code is structured as follows:
Standard server loop (blocking call to socket.accept() in a loop within its own thread), calling a handler upon an incoming connection:
socket = mServerSocket.accept();
myHandler.onIncomingConnection(socket);
The handler offloads all further processing of the incoming connection(s) to a thread pool:
public class X {
private final ExecutorService receiveThreadPool = Executors.newSingleThreadExecutor();
[...]
private final ConnectionHandler mHandler = new MyServer.ServerHandler() {
#Override
public void onIncomingConnection(final Socket socket) {
MLog.vv(TAG, "Socket status: " + (socket.isBound() ? "bound" : "unbound") + ", "
+ (socket.isConnected() ? "connected" : "unconnected") + ", "
+ (socket.isClosed() ? "closed" : "not closed") + ", "
+ (socket.isInputShutdown() ? "input shutdown" : "input not shut down") + ".");
// Process result
receiveThreadPool.execute(new Runnable() {
#Override
public void run() {
MLog.vv(TAG, "Socket status: " +
(socket.isBound() ? "bound" : "unbound") + ... ); // same code as above
BufferedOutputStream out = null;
try {
out = new BufferedOutputStream(socket.getOutputStream());
out.write(HELLO_MESSAGE);
out.flush();
[rest omitted...]
} catch (IOException e) {
[...]
} finally {
[close resources...]
}
}
Note, that the socket is defined as final in the handler method's signature, making it accessible from within the anonymous inner Runnable class. However, the first write out.write(HELLO_MESSAGE); to the output stream fails due to a closed socket exception. logcat output:
02-16 17:49:26.383 14000-14057/mypackage:remote V/ManagementServer﹕ Incoming connection from /192.168.8.33:47764
02-16 17:49:26.383 14000-14057/mypackage:remote V/ManagementServer﹕ Socket status: bound, connected, not closed, input not shut down.
02-16 17:49:26.393 14000-14077/mypackage:remote V/ManagementServer﹕ Socket status: bound, unconnected, closed, input not shut down.
02-16 17:49:26.398 14000-14077/mypackage:remote E/ManagementServer﹕ Error communicating with client:
java.net.SocketException: Socket is closed
at java.net.Socket.checkOpenAndCreate(Socket.java:665)
at java.net.Socket.getInputStream(Socket.java:359)
at net.semeion.tusynctest.network.ManagementServer$1$1.run(ManagementServer.java:79)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
As shown in the log output, somehow the socket changes its status from connected to unconnected/closed right after offloading the Runnable into the thread pool. If I just remove the ThreadPool.execute lines, everything works as expected. I have also tried to create my own static Runnable class within the outer class X, passing the socket as a parameter to the Runnable's constructor. However, this triggers the same problem.
Am I missing something here? In theory, this should work like a charm; but somehow it seems, that upon starting the thread and terminating the handler's incomingConnection method, something happens to the socket instance.
Further facts:
It's not the client's fault either - to the client, it looks like the server closed the socket. And as said, commenting out the thread pool on the server side fixes the problem.)
You may notice the ":remote" in the logcat output - the server thread is created from within a background service that itself runs in a separate process.
At the moment, I'm employing a SingleThreadExecutor for the pool, just for testing. The type of executor should make no difference IMHO.
I tried to use the socket's OutputStream directly (unbuffered), which has not made a difference. The log statements show that the socket itself changes its status.
If I initialise the BufferedOutputstream in the handler right before executing the thread, this yields a strange "bad file number" SocketException at the out.flush(); line (possibly this is an IPC problem?!):
java.net.SocketException: sendto failed: EBADF (Bad file number)
at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:546)
at libcore.io.IoBridge.sendto(IoBridge.java:515)
at java.net.PlainSocketImpl.write(PlainSocketImpl.java:504)
at java.net.PlainSocketImpl.access$100(PlainSocketImpl.java:37)
at java.net.PlainSocketImpl$PlainSocketOutputStream.write(PlainSocketImpl.java:266)
at java.io.BufferedOutputStream.flushInternal(BufferedOutputStream.java:185)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:85)
at net.semeion.tusynctest.network.ManagementServer$1$1.run(ManagementServer.java:88)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: android.system.ErrnoException: sendto failed: EBADF (Bad file number)
at libcore.io.Posix.sendtoBytes(Native Method)
at libcore.io.Posix.sendto(Posix.java:206)
at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:278)
at libcore.io.IoBridge.sendto(IoBridge.java:513)
Thanks for any hints :)
I've found the problem now. Embarrassingly, I've overlooked the most obvious source for trouble, the server loop in my Server class:
new Thread(new Runnable() {
#Override
public void run() {
while (mReceiving) {
Socket recSocket = null;
try {
recSocket = mServerSocket.accept();
// Process connection
mTcpServerHandler.onIncomingConnection(recSocket);
} catch (IOException e) {
// ...
} finally {
if (recSocket != null) {
try {
recSocket.close();
} catch (IOException e) {
// log, ignore...
}
}
}
}
}
}).start();
So, in case the handler offloads the processing to a new thread, the method returns immediately, and the finally block of the server loop closes the socket (which was intended originally, but doesn't fit the thread pool approach). Too obvious, sorry for bothering :)

Commons Net FTPClient hangs indefinitely with Mule

I encountered an issue with the Mule ESB FTP Transport: when polling, the thread running the client would hang indefinitely without throwing an error. This causes FTP poll to stop completely. Mule uses Apache Commons Net FTPClient.
Looking further into the code, I think it is caused by the SocketTimeout of the FTPClient not being set, sometime causing infinite hanging when reading lines from the FTPClient's socket.
We can clearly see the problem in these stacks retrieved with jstack when the problem occured. The __getReply() function seems to be the more direct link to the problem.
This one hanging on connect() call when creating a new FTPClient:
receiver.172 prio=10 tid=0x00007f23e43c8800 nid=0x2d5 runnable [0x00007f24c32f1000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
- locked <0x00000007817a9578> (a java.io.InputStreamReader)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:154)
at java.io.BufferedReader.readLine(BufferedReader.java:317)
- locked <0x00000007817a9578> (a java.io.InputStreamReader)
at java.io.BufferedReader.readLine(BufferedReader.java:382)
at org.apache.commons.net.ftp.FTP.__getReply(FTP.java:294)
at org.apache.commons.net.ftp.FTP._connectAction_(FTP.java:364)
at org.apache.commons.net.ftp.FTPClient._connectAction_(FTPClient.java:540)
at org.apache.commons.net.SocketClient.connect(SocketClient.java:178)
at org.mule.transport.ftp.FtpConnectionFactory.makeObject(FtpConnectionFactory.java:33)
at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1188)
at org.mule.transport.ftp.FtpConnector.getFtp(FtpConnector.java:172)
at org.mule.transport.ftp.FtpConnector.createFtpClient(FtpConnector.java:637)
at org.mule.transport.ftp.FtpMessageReceiver.listFiles(FtpMessageReceiver.java:134)
at org.mule.transport.ftp.FtpMessageReceiver.poll(FtpMessageReceiver.java:94)
at org.mule.transport.AbstractPollingMessageReceiver.performPoll(AbstractPollingMessageReceiver.java:216)
at org.mule.transport.PollingReceiverWorker.poll(PollingReceiverWorker.java:80)
at org.mule.transport.PollingReceiverWorker.run(PollingReceiverWorker.java:49)
at org.mule.transport.TrackingWorkManager$TrackeableWork.run(TrackingWorkManager.java:267)
at org.mule.work.WorkerContext.run(WorkerContext.java:286)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- <0x00000007817a3540> (a java.util.concurrent.ThreadPoolExecutor$Worker)
And the other hanging on pasv() call when using listFiles():
receiver.137" prio=10 tid=0x00007f23e433b000 nid=0x7c06 runnable [0x00007f24c2fee000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
- locked <0x0000000788847ed0> (a java.io.InputStreamReader)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:154)
at java.io.BufferedReader.readLine(BufferedReader.java:317)
- locked <0x0000000788847ed0> (a java.io.InputStreamReader)
at java.io.BufferedReader.readLine(BufferedReader.java:382)
at org.apache.commons.net.ftp.FTP.__getReply(FTP.java:294)
at org.apache.commons.net.ftp.FTP.sendCommand(FTP.java:490)
at org.apache.commons.net.ftp.FTP.sendCommand(FTP.java:534)
at org.apache.commons.net.ftp.FTP.sendCommand(FTP.java:583)
at org.apache.commons.net.ftp.FTP.pasv(FTP.java:882)
at org.apache.commons.net.ftp.FTPClient._openDataConnection_(FTPClient.java:497)
at org.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:2296)
at org.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:2269)
at org.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:2189)
at org.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:2132)
at org.mule.transport.ftp.FtpMessageReceiver.listFiles(FtpMessageReceiver.java:135)
at org.mule.transport.ftp.FtpMessageReceiver.poll(FtpMessageReceiver.java:94)
at org.mule.transport.AbstractPollingMessageReceiver.performPoll(AbstractPollingMessageReceiver.java:216)
at org.mule.transport.PollingReceiverWorker.poll(PollingReceiverWorker.java:80)
at org.mule.transport.PollingReceiverWorker.run(PollingReceiverWorker.java:49)
at org.mule.transport.TrackingWorkManager$TrackeableWork.run(TrackingWorkManager.java:267)
at org.mule.work.WorkerContext.run(WorkerContext.java:286)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- <0x0000000788832180> (a java.util.concurrent.ThreadPoolExecutor$Worker)
I think the problem is caused by the use of the default FTPClient constructor (extending SocketClient) in Mule default FtpConnectionFactory.
Note the setConnectTimeout() values seems to be used only when calling socket.connect(), but ignored on other operations using the same socket:
protected FTPClient createFtpClient()
{
FTPClient ftpClient = new FTPClient();
ftpClient.setConnectTimeout(connectionTimeout);
return ftpClient;
}
It uses the FTPClient() constructor, itself using SocketClient with a 0 timeout, defined when creating the socket.
public SocketClient()
{
...
_timeout_ = 0;
...
}
And then we call connec(), which calls _ connectAction()_.
In SocketClient:
protected void _connectAction_() throws IOException
{
...
_socket_.setSoTimeout(_timeout_);
...
}
In FTP, a new Reader is instanciated with our everlasting socket:
protected _connectAction_(){
...
_controlInput_ =
new BufferedReader(new InputStreamReader(_socket_.getInputStream(),
getControlEncoding()));
...
}
Then, when calling __getReply() function, we use this Reader-with-everlasting-socket:
private void __getReply() throws IOException
{
...
String line = _controlInput_.readLine();
...
}
Sorry for the long post, but I think this required correct explanations. A solution may be to call setSoTimeout() just after connect(), to define a Socket Timeout.
Having a default timeout does not seem an acceptable solution, as each users may have different needs and a default is not suitable in any case. https://issues.apache.org/jira/browse/NET-35
Finally, this raises 2 questions:
It seems like a bug to me, as it will completely stops FTP polling without giving error. What do you think?
What could be an easy way to avoid such situation? Calling setSoTimeout() with a custom FtpConnectionFactory? Am I missing a configuration or parameter somewhere?
Thanks by advance.
EDIT: I am using Mule CE Standalone 3.5.0, which seems to use Apache Commons Net 2.0. But looking in the code, Mule CE Standalone 3.7 with Commons Net 2.2 does not seem different. Here are the source codes involved:
https://github.com/mulesoft/mule/blob/mule-3.5.x/transports/ftp/src/main/java/org/mule/transport/ftp/FtpConnectionFactory.java
http://grepcode.com/file/repo1.maven.org/maven2/commons-net/commons-net/2.0/org/apache/commons/net/SocketClient.java
http://grepcode.com/file/repo1.maven.org/maven2/commons-net/commons-net/2.0/org/apache/commons/net/ftp/FTP.java
http://grepcode.com/file/repo1.maven.org/maven2/commons-net/commons-net/2.0/org/apache/commons/net/ftp/FTPClient.java
In an ideal world the timeout should not be necessary, but it looks like in your case it is.
Your description is very comprehensive, have you considered to raise a bug?
To workaround I would suggest first to use "Response Timeout" in the advanced tab. If that doesnt work I would use a service override, from there you should be able to override the receiver.
I reproduced the error in both my previous cases using MockFtpServer, and I was able to use a FtpConnectionFactory which seems to solve the issue.
public class SafeFtpConnectionFactory extends FtpConnectionFactory{
//define a default timeout
public static int defaultTimeout = 60000;
public static synchronized int getDefaultTimeout() {
return defaultTimeout;
}
public static synchronized void setDefaultTimeout(int defaultTimeout) {
SafeFtpConnectionFactory.defaultTimeout = defaultTimeout;
}
public SafeFtpConnectionFactory(EndpointURI uri) {
super(uri);
}
#Override
protected FTPClient createFtpClient() {
FTPClient client = super.createFtpClient();
//Define the default timeout here, which will be used by the socket by default,
//instead of the 0 timeout hanging indefinitely
client.setDefaultTimeout(getDefaultTimeout());
return client;
}
}
And then attaching it to my connector:
<ftp:connector name="archivingFtpConnector" doc:name="FTP"
pollingFrequency="${frequency}"
validateConnections="true"
connectionFactoryClass="my.comp.SafeFtpConnectionFactory">
<reconnect frequency="${reconnection.frequency}" count="${reconnection.attempt}"/>
</ftp:connector>
Using this configuration, a java.net.SocketTimeoutException will be thrown after the specified timeout, such as:
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:154)
at java.io.BufferedReader.readLine(BufferedReader.java:317)
at java.io.BufferedReader.readLine(BufferedReader.java:382)
at org.apache.commons.net.ftp.FTP.__getReply(FTP.java:294)
at org.apache.commons.net.ftp.FTP._connectAction_(FTP.java:364)
at org.apache.commons.net.ftp.FTPClient._connectAction_(FTPClient.java:540)
at org.apache.commons.net.SocketClient.connect(SocketClient.java:178)
at org.mule.transport.ftp.FtpConnectionFactory.makeObject(FtpConnectionFactory.java:33)
at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1188)
at org.mule.transport.ftp.FtpConnector.getFtp(FtpConnector.java:172)
at org.mule.transport.ftp.FtpConnector.createFtpClient(FtpConnector.java:637)
...
Otherwise, an attempt at connect() or pasv() would hang indefinitely without server response. I reproduced this exact behavior using mock FTP.
Note: I used setDefaultTimeout() as it seems to be the variable used with connect() and connectAction() (from SocketClient source):
public abstract class SocketClient
{
...
protected void _connectAction_() throws IOException
{
...
_socket_.setSoTimeout(_timeout_);
...
}
...
public void setDefaultTimeout(int timeout)
{
_timeout_ = timeout;
}
...
}
EDIT: For those who are interested, here is the test code for mock FTP used to reproduce the never answering server. The infinite loop is far from good practice though. It should be replaced with something like sleep with an enclosing Test class expecting a SocketTimeout exception and ensuring failure after a given timeout.
private static final int CONTROL_PORT = 2121;
public void startStubFtpServer(){
FakeFtpServer fakeFtpServer = new FakeFtpServer();
//define the command which should never be answered
fakeFtpServer.setCommandHandler(CommandNames.PASV, new EverlastingCommandHandler());
//fakeFtpServer.setCommandHandler(CommandNames.CONNECT, new EverlastingConnectCommandHandler());
//or any other command...
//server config
...
//start server
fakeFtpServer.setServerControlPort(CONTROL_PORT);
fakeFtpServer.start();
...
}
//will cause any command received to never have an answer
public class EverlastingConnectCommandHandler extends org.mockftpserver.core.command.AbstractStaticReplyCommandHandler{
#Override
protected void handleCommand(Command cmd, Session session, InvocationRecord rec) throws Exception {
while(true){
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
//TODO
}
}
}
}
public class EverlastingCommandHandler extends AbstractFakeCommandHandler {
#Override
protected void handle(Command cmd, Session session) {
while(true){
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
//TODO
}
}
}
};

IllegalStateException when HTTP Streaming using ResponseBodyEmitter in Spring-MVC

I'm using the newly added HTTP Streaming feature with ResponseBodyEmitter in Spring 4.2.0.BUILD-SNAPSHOT.
I would like to implement a long running persistent TCP connection on an undending stream of data between a (possibly java) client and server until the client breaks the connection. I would like to avoid using the websocket protocol.
If a client breaks the connection while streaming, a runtime IllegalStateException is thrown. I would like to handle this gracefully and cleanup the emitter. Short of catching a runtime exception, is there any way to gracefully handle this?
I have to specify an artifically high timeout value on the emitter for a "persistent" connection. Can I set no timeout?
The webapp is deployed on apache-tomcat-7.0.62.
Relevant code as follows:
#RequestMapping(value = "stream", method = RequestMethod.GET)
public ResponseBodyEmitter handleStreaming() {
ResponseBodyEmitter emitter = new ResponseBodyEmitter(timeout);
emitters.add(emitter);
emitter.onCompletion(new Runnable() {
#Override
public void run() {
emitters.remove(emitter);
}
});
emitter.onTimeout(new Runnable() {
#Override
public void run() {
emitters.remove(emitter);
}
});
return emitter;
}
.
while (true) {
for (Iterator<ResponseBodyEmitter> iterator = emitters.iterator(); iterator.hasNext();) {
ResponseBodyEmitter emitter = iterator.next();
try {
emitter.send("data...", MediaType.TEXT_PLAIN);
} catch (IOException | IllegalStateException e) {
LOGGER.error(e);
iterator.remove();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
LOGGER.error(e);
}
}
Logs:
INFO: An error occurred in processing while on a non-container thread. The connection will be closed immediately
java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)
at java.net.SocketOutputStream.write(SocketOutputStream.java:153)
at org.apache.coyote.http11.InternalOutputBuffer.realWriteBytes(InternalOutputBuffer.java:215)
at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:480)
at org.apache.coyote.http11.InternalOutputBuffer.flush(InternalOutputBuffer.java:119)
at org.apache.coyote.http11.AbstractHttp11Processor.action(AbstractHttp11Processor.java:801)
at org.apache.coyote.Response.action(Response.java:172)
at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:363)
at org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:331)
at org.apache.catalina.connector.CoyoteOutputStream.flush(CoyoteOutputStream.java:101)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:297)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
at org.springframework.util.StreamUtils.copy(StreamUtils.java:106)
at org.springframework.http.converter.StringHttpMessageConverter.writeInternal(StringHttpMessageConverter.java:109)
at org.springframework.http.converter.StringHttpMessageConverter.writeInternal(StringHttpMessageConverter.java:40)
at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:193)
at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitterReturnValueHandler$HttpMessageConvertingHandler.sendInternal(ResponseBodyEmitterReturnValueHandler.java:157)
at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitterReturnValueHandler$HttpMessageConvertingHandler.send(ResponseBodyEmitterReturnValueHandler.java:150)
at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter.sendInternal(ResponseBodyEmitter.java:180)
at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter.send(ResponseBodyEmitter.java:164)
....
[ERROR] [02/07/15 18:11 PM] [Controller$TestResponseBodyEmitter:74] - java.lang.IllegalStateException: The request associated with the AsyncContext has already completed processing.
Command:
curl http://localhost:8080/myapp/stream -v -N
data...data...
Ctrl-C
According to the Javadoc of the ResponseBodyEmitter's constructor (found here).
Create a ResponseBodyEmitter with a custom timeout value. By default
not set in which case the default configured in the MVC Java Config or
the MVC namespace is used, or if that's not set, then the timeout
depends on the default of the underlying server.
Therefore do give a timeout when you create the c instance.
PS: In my environment ResponseBodyEmitter#getTimeout() returned null; this does not mean that there is an infinite timeout. On the contrary after 5-10 sec the connection timed out.

How to use one single Bootstrap to connect to multiple servers in Netty

I don't know if there is a performance issue if I create(new) a bootstrap every time I connect to a remote server. So I want to use one single bootstrap instance to connect to multiple servers. My code below:
Bootstrap b = new Bootstrap();
b.group(new NioEventLoopGroup()).handler(new TestHandler()).channel(NioSocketChannel.class)
.option(ChannelOption.AUTO_READ, false);
ChannelFutureListener listener = new ChannelFutureListener() {
#Override
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
// connection complete start to read first data
System.out.println("connection established + channel: " + future.channel());
} else {
// Close the connection if the connection attempt has failed.
System.out.println("connection failed");
}
}
};
String[] urls = { "www.google.com", "www.stackoverflow.com", "www.yahoo.com" };
for (String s : urls) {
b = b.clone();
b.remoteAddress(s, 80);
b.connect().addListener(listener);
}
System.in.read();
Unfortunately, it crashed with :
connection established + channel: [id: 0x5df86eec, /192.168.126.136:60414 => www.google.com/173.194.127.209:80]
Exception in thread "main" java.lang.IllegalStateException: channel not registered to an event loop
at io.netty.channel.AbstractChannel.eventLoop(AbstractChannel.java:107)
at io.netty.channel.nio.AbstractNioChannel.eventLoop(AbstractNioChannel.java:102)
at io.netty.channel.nio.AbstractNioChannel.eventLoop(AbstractNioChannel.java:41)
at io.netty.channel.CompleteChannelFuture.executor(CompleteChannelFuture.java:48)
at io.netty.util.concurrent.CompleteFuture.addListener(CompleteFuture.java:49)
at io.netty.channel.CompleteChannelFuture.addListener(CompleteChannelFuture.java:56)
at Test3.main(Test3.java:41)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
I think I am using bootstrap in a wrong way. If so, should I create a brand new bootstrap every time?
At least, I should use the same NioEventLoopGroup, right?
Alright, it's my fault, I forget to add a ChannelInitializer. Change it to code below:
b.group(new NioEventLoopGroup()).handler(new ChannelInitializer<NioSocketChannel>() {
#Override
protected void initChannel(NioSocketChannel ch) throws Exception {
ch.pipeline().addLast(new TestHandler());
}
})

How to deal with SocketTimeoutException inside Java Code / Webservices

This is my Method code shown below
Actually this serves as a Webservices Method .
public Response getData(ServiceRequest request)
{
try
{
final boolean toProceedorNot = validate(legdata);
if (!toProceedorNot) {
status.setErrorText(errorText);
return response;
}
else {
// Some Processing is done here
response.setMessage(result);
}
}
catch(Exception e)
{
errorText = e.getMessage().toString();
status.setErrorText(errorText);
response.setStatus(status);
}
return response;
}
If the execution of the Method takes longer time , an SocketTimeoutException will be thrown by the Apache CXF Framework
at java.lang.Thread.run(Thread.java:662)
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:258)
at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:695)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:640)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1195)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:379)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:2034)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:2013)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1938)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:66)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:626)
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
My Question is that, even though an SocketTimeoutException is thrown, it is not coming inside the Exception block.
I am not sure whether this Exception , should be handled by whom ( The client or inside the Webservices Implementation method )
But as a Webservice provider , please tell me how to deal with this Exception ??

Categories