2017-04-06 81 views
0

我使用Retrofit連接到我的REST API。請檢查下面的代碼發生`RequestDispatcher`時的NullPointerException

import com.google.gson.Gson; 
    import com.google.gson.GsonBuilder; 
    import java.io.IOException; 
    import java.io.PrintWriter; 
    import java.util.Date; 
    import java.util.List; 
    import java.util.logging.Level; 
    import java.util.logging.Logger; 
    import javax.servlet.RequestDispatcher; 
    import javax.servlet.ServletException; 
    import javax.servlet.http.HttpServlet; 
    import javax.servlet.http.HttpServletRequest; 
    import javax.servlet.http.HttpServletResponse; 
    import retrofit2.Call; 
    import retrofit2.Callback; 
    import retrofit2.Response; 
    import retrofit2.Retrofit; 
    import retrofit2.converter.gson.GsonConverterFactory; 

    /** 
    * 
    * @author The Ace 
    */ 
    public class SignUpLoaderServlet extends HttpServlet { 

     /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> 
     * methods. 
     * 
     * @param request servlet request 
     * @param response servlet response 
     * @throws ServletException if a servlet-specific error occurs 
     * @throws IOException if an I/O error occurs 
     */ 
     protected void processRequest(final HttpServletRequest request, final HttpServletResponse response) 
       throws ServletException, IOException { 
      response.setContentType("text/html;charset=UTF-8"); 
      PrintWriter out = response.getWriter(); 
      System.out.println("RUNNING!!!!!!!!!!!"); 

      try { 
       GsonBuilder gsonBuilder = new GsonBuilder(); 
       gsonBuilder.registerTypeAdapter(Date.class, new DateTypeDeserializer()); 
       Gson gson = gsonBuilder.create(); 

       Retrofit retrofit = new Retrofit.Builder() 
         .baseUrl(BaseURLs.MESSAGING_URL) 
         .addConverterFactory(GsonConverterFactory.create(gson)) 
         .build(); 

       RestEndPointsInterface endPoint = retrofit.create(RestEndPointsInterface.class); 
       Call<List<ProfesionalBodyList>> call = endPoint.getAllProfesionalBodyLists(); 
       call.enqueue(new Callback<List<ProfesionalBodyList>>() { 

        @Override 
        public void onResponse(Call<List<ProfesionalBodyList>> call, Response<List<ProfesionalBodyList>> rspn) 
        { 
         try { 
          List<ProfesionalBodyList> body = rspn.body(); 


          for(int i=0;i<body.size();i++) 
          { 
           System.out.println(body.get(i).getProfessionalBody()); 
          } 

RequestDispatcher requestDispatcher = request.getRequestDispatcher("/create-account.jsp"); 
          requestDispatcher.forward(request, response); 


         } catch (Exception ex) { 
          ex.printStackTrace(); 
         } 
        } 

        @Override 
        public void onFailure(Call<List<ProfesionalBodyList>> call, Throwable ex) { 
         ex.printStackTrace(); 
        } 
       }); 



      } finally { 


      } 
     } 

     // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code."> 
     /** 
     * Handles the HTTP <code>GET</code> method. 
     * 
     * @param request servlet request 
     * @param response servlet response 
     * @throws ServletException if a servlet-specific error occurs 
     * @throws IOException if an I/O error occurs 
     */ 
     @Override 
     protected void doGet(HttpServletRequest request, HttpServletResponse response) 
       throws ServletException, IOException { 
      processRequest(request, response); 
     } 

     /** 
     * Handles the HTTP <code>POST</code> method. 
     * 
     * @param request servlet request 
     * @param response servlet response 
     * @throws ServletException if a servlet-specific error occurs 
     * @throws IOException if an I/O error occurs 
     */ 
     @Override 
     protected void doPost(HttpServletRequest request, HttpServletResponse response) 
       throws ServletException, IOException { 
      processRequest(request, response); 
     } 

    } 

此代碼觸發以下異常

java.lang.NullPointerException 
    at com.tekhinno.xxx.signup.SignUpLoaderServlet$1.onResponse(SignUpLoaderServlet.java:80) 
    at retrofit2.OkHttpCall$1.callSuccess(OkHttpCall.java:132) 
    at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:111) 
    at okhttp3.RealCall$AsyncCall.execute(RealCall.java:135) 
    at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at java.lang.Thread.run(Thread.java:745) 

但是如果我更換下面的代碼行到finally()塊,這個問題也沒有了。

RequestDispatcher requestDispatcher = request.getRequestDispatcher("/create-account.jsp"); 
requestDispatcher.forward(request, response); 

我不知道爲什麼它不在onResponse()內部工作。在那裏運行是非常重要的,因爲在轉發行爲發生之前我從REST API加載項目。

有什麼想法?

+1

您正在使用異步API,它在後臺線程中發送請求,然後在響應可用時再回叫,並且不會阻止請求處理線程。因此,在執行onResponse回調時已經處理了該請求。 –

+0

@JBNizet:謝謝。那麼,我該如何處理這種情況呢? –

回答

0

這個問題主要是因爲電話是Asynchronous而且requestDispatcher對象已經執行。那麼答案就是保持到REST調用完成其工作負載。這意味着,做到這一點Synchronous

也可以使用Synchronous方式完成改造。以下是代碼。

protected void processRequest(final HttpServletRequest request, final HttpServletResponse response) 
      throws ServletException, IOException { 
     response.setContentType("text/html;charset=UTF-8"); 
     PrintWriter out = response.getWriter(); 
     System.out.println("RUNNING!!!!!!!!!!!"); 

     try { 
      GsonBuilder gsonBuilder = new GsonBuilder(); 
      gsonBuilder.registerTypeAdapter(Date.class, new DateTypeDeserializer()); 
      Gson gson = gsonBuilder.create(); 

      Retrofit retrofit = new Retrofit.Builder() 
        .baseUrl(BaseURLs.MESSAGING_URL) 
        .addConverterFactory(GsonConverterFactory.create(gson)) 
        .build(); 

      RestEndPointsInterface endPoint = retrofit.create(RestEndPointsInterface.class); 
      Call<List<ProfesionalBodyList>> call = endPoint.getAllProfesionalBodyLists(); 
      body = call.execute().body(); 

      for (int i = 0; i < body.size(); i++) { 
       System.out.println(body.get(i).getProfessionalBody()); 
      } 

     } finally { 
      RequestDispatcher requestDispatcher = request.getRequestDispatcher("/create-account.jsp"); 
      request.setAttribute("ProfesionalBodyList", body); 
      requestDispatcher.forward(request, response); 
     } 
    } 

Simpy注意它所說的地方call.execute().body();。這是Synchronous呼叫。

相關問題