简体   繁体   English

触发`RequestDispatcher`时发生NullPointerException

[英]NullPointerException when `RequestDispatcher` is fired

I am using Retrofit to connect to my REST API. 我正在使用Retrofit连接到我的REST API。 Please check the below code 请检查以下代码

   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);
        }

    }

This code fires the below exception 此代码引发以下异常

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)

However if I replace the below code line into the finally() block, the issue is gone. 但是,如果将下面的代码行替换为finally()块,则问题就消失了。

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

I am not sure why it is not working inside the onResponse() . 我不确定为什么它在onResponse()内部onResponse() It is imporant to run there because I load items from the REST API before the forward action take place. 在此处运行很重要,因为在进行前向操作之前,我已从REST API加载项目。

Any idea? 任何想法?

The issue is mainly because the call was Asynchronous and the requestDispatcher object was already executed. 问题主要是因为调用是Asynchronous ,并且requestDispatcher对象已经执行。 Then the answer is to stay until the REST call complete its work load. 答案是一直坚持到REST调用完成其工作负载为止。 That means, do it Synchronous . 也就是说,执行Synchronous

Retrofit can be done in Synchronous manner as well. 改造也可以以Synchronous方式完成。 Below is the code. 下面是代码。

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 pay attention to the place where it says call.execute().body(); Simpy注意它说call.execute().body(); . This is the Synchronous call. 这是Synchronous调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM