2012-09-06 75 views
0

寫入套接字時出現這個奇怪的問題。該應用程序是在Tomcat 5.5下運行的webapp。 有問題的功能是從servlet獲取請求,執行一些處理並通過SSLSocket將該請求發送到外部系統。當在Tomcat中運行的webapp中寫入Socket時出現NullPointerException

這是我的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; 
     } 
    } 
} 

我提交郵件到該MessageProcessor的在servlet中這樣說:

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()中,任務被提交給一個緩存的線程池,並且它拋出了這個異常。 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中。

如果有人能夠說明這一點,我將非常感激。對不起,如果我在這裏放了很多代碼。這讓我發瘋。

+0

「socketWriter.flush()拋出異常」。不是根據你發佈的堆棧跟蹤。還有更多嗎? – EJP

+0

發佈完整的堆棧跟蹤。當我用調試器遍歷代碼時,它在socketWriter.flush()失敗。但是,堆棧跟蹤就像只有 – TommyQ

回答

0

我想我已經找到了,它看起來像從該行未來的問題的原因:

socketFactory = SSLSocketFactory.getDefault(); 

把後將SocketFactory轉換成線程局部變量它工作正常。

socketFactory = new ThreadLocal<SocketFactory>(){; 
    protected SocketFactory initialValue() { 
     return SSLSocketFactory.getDefault(); 
    } 
}; 

所以我的結論是SSLSocketFactory不是線程安全的。我還沒有找到任何官方文件來支持這一點。

0
public String submitDirect(String pdcRequestStr) throws Exception { 
    Worker worker = new Worker(msg); 
    return worker.call(); 
} 

變化的新工人(MSG)到新的工作(pdcRequestStr)

+0

這是我的一個錯字。由於業務敏感性,變量在發佈之前已更名。 – TommyQ

相關問題