[英]NullPointerException when write to Socket from a webapp running in Tomcat
写入套接字时出现了这个奇怪的问题。 该应用程序是在Tomcat 5.5下运行的webapp。 有问题的功能是从Servlet接收请求,进行一些处理,然后通过SSLSocket将请求发送到外部系统。
这是我的MessageProcessor类:
public class MessageProcessor {
private final int socketTimeout;
private final int threadTimeout;
private final ExecutorService executor = Executors.newCachedThreadPool();
private static class Holder {
static MessageProcessor instance = new MessageProcessor();
}
public static MessageProcessor instance() {
return Holder.instance;
}
static {
instance();
}
private MessageProcessor() {
socketTimeout = /*get from property*/
threadTimeout = /*get from property*/
//Setting Java SSL details
System.setProperty("javax.net.ssl.trustStore") /*from property*/;
System.setProperty("javax.net.ssl.trustStorePassword") /*from property*/;
socketFactory = SSLSocketFactory.getDefault();
}
public String submit(String msg) {
Worker worker = new Worker(msg);
try {
return executor.submit(worker).get(threadTimeout,
TimeUnit.MILLISECONDS);
} catch (Exception e) {
e.printStackTrade();
}
return "";
}
public String submitDirect(String msg) throws Exception {
Worker worker = new Worker(msg);
return worker.call();
}
class Worker implements Callable<String> {
private String message;
public Worker(String requestMsg) {
this.message = requestMsg;
}
public String call() throws Exception {
socket = socketFactory.createSocket();
StringBuilder responseSb = new StringBuilder();
StringBuilder frameMarkerSb = new StringBuilder();
BufferedWriter socketWriter = null;
BufferedReader socketReader = null;
try {
socketWriter =
new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
socketWriter.write(message);
socketWriter.flush();
socketReader =
new BufferedReader(new InputStreamReader(socket.getInputStream(),
"UTF-8"));
/* do something else */
/* receive response */
} catch (InterruptedIOException e) {
//Error handling
} catch (Exception e) {
//Error handling
} finally {
socketWriter.close();
socketReader.close();
socket.close();
}
return response;
}
}
}
我以这种方式向Servlet中的MessageProcessor提交了消息:
protected void doPost(HttpServletRequest req,
HttpServletResponse resp) throws ServletException,
IOException {
String requestStr = req.getParameter("data");
String responseStr = "";
try {
responseStr =
MessageProcessor.instance().submit(requestStr.trim());
responseStr =
MessageProcessor.instance().submitDirect(requestStr.trim());
} catch (Exception e) {
//Error handling
}
resp.setContentType("text/HTML");
resp.getWriter().write(responseStr);
}
问题在于submit()。 在submit()中,任务被提交到缓存的线程池,并且抛出此异常。 在socketWriter.flush()处引发异常。
2012-09-06 13:17:36,007 [http-8080-1] ERROR processor.MessageProcessor - Error submitting new task
java.util.concurrent.ExecutionException: java.lang.NullPointerException
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:232)
at java.util.concurrent.FutureTask.get(FutureTask.java:91)
at com.scb.race.bridge.processor.MessageProcessor.submit(MessageProcessor.java:70)
at com.scb.race.bridge.servlet.CheckServlet.doPost(CreditCheckServlet.java:31)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:172)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:843)
at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:679)
at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1303)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.NullPointerException
at com.scb.race.bridge.processor.MessageProcessor$MessageWorker.call(MessageProcessor.java:140)
at com.scb.race.bridge.processor.MessageProcessor$MessageWorker.call(MessageProcessor.java:78)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
如果我使用SubmitDirect(),则直接调用call()方法,而无需提交到线程池,并且它可以正常工作。
当我在JUnit中测试该类时没有问题。 它仅在Tomcat中发生。
如果有人能对此有所启发,我将非常感激。 抱歉,如果我在这里放很多代码。 这让我发疯。
public String submitDirect(String pdcRequestStr) throws Exception {
Worker worker = new Worker(msg);
return worker.call();
}
将新的Worker(msg)更改为新的Worker(pdcRequestStr)
我想我已经找到了问题的原因,看起来像是从这行来的:
socketFactory = SSLSocketFactory.getDefault();
将SocketFactory放入线程局部变量后,它可以正常工作。
socketFactory = new ThreadLocal<SocketFactory>(){;
protected SocketFactory initialValue() {
return SSLSocketFactory.getDefault();
}
};
所以我的结论是SSLSocketFactory不是线程安全的。 我还没有找到任何官方文档来对此进行支持。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.