Thrown exception AS-WEB-CORE-00089 while forwarding to a different servlet path

I tried to redirect from doPost to doGet from ControllerServlet urlPattern = "/ remove_person" so I can re-update the findAll request inside my doGet method of ControllerServlet class and then forward remove_person.jsp from doGet method, but AS-WEB-CORE-00089 is thrown

WARNING:   StandardWrapperValve[ControllerServlet]: Servlet.service() for servlet ControllerServlet threw exception
javax.servlet.ServletException: AS-WEB-CORE-00089
    at org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:863)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:739)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:575)
    at org.apache.catalina.core.ApplicationDispatcher.doDispatch(ApplicationDispatcher.java:546)
    at org.apache.catalina.core.ApplicationDispatcher.dispatch(ApplicationDispatcher.java:428)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:378)
    at server.ControllerServlet.doPost(ControllerServlet.java:130)

      

where the line ControllerServlet.java:130 is in the doPost () method:

request.getRequestDispatcher(url).forward(request, response);

      

Here is the code for the servlet class:

@WebServlet(
    name = "ControllerServlet", 
    loadOnStartup = 1,
    urlPatterns = {
        "/index", 
        "/search_person", 
        "/add_person",
        "/remove_person"})
public class ControllerServlet extends HttpServlet {

    @PersistenceUnit
    private EntityManagerFactory emf;
    @Resource
    private UserTransaction utx;
    private EntityManager em;

    @Override
    public void init() throws ServletException {
        assert emf != null;
        em = emf.createEntityManager();
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String servletPath = request.getServletPath();

        if (servletPath.equals("/index")) {
        }
        else if (servletPath.equals("/search_person")) {
            List persons = em.createNamedQuery("Person.findAll").getResultList();
            request.setAttribute("findByNameAndYearBirth", persons);
        }
        else if (servletPath.equals("/add_person")) {
        }
        else if (servletPath.equals("/remove_person")) {
            List persons = em.createNamedQuery("Person.findAll").getResultList();
            request.setAttribute("findAll", persons);
        }
        String url = servletPath + ".jsp";
        request.getRequestDispatcher(url).forward(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String servletPath = request.getServletPath();

        if (servletPath.equals("/index")) {
        }
        else if (servletPath.equals("/search_person")) {
            String name = request.getParameter("name");
            String yearBirth = request.getParameter("yearBirth");

            Query query = em.createNamedQuery("Person.findAll");
            if (!name.isEmpty() && !yearBirth.isEmpty()) {
                query = em.createNamedQuery("Person.findByNameAndYearBirth");
                query.setParameter("name", name);
                query.setParameter("yearBirth", Short.parseShort(yearBirth));
            }
            else if (!name.isEmpty()) {
                query = em.createNamedQuery("Person.findByModel");
                query.setParameter("name", name);
            }
            else if (!yearBirth.isEmpty()) {
                try  {
                    Short sYearBirth = Short.parseShort(yearBirth);
                    query = em.createNamedQuery("Person.findByYearBirth");
                    query.setParameter("yearBirth", sYearBirth);
                } catch (NumberFormatException nfe) {}
            }
            List persons = query.getResultList();
            request.setAttribute("findByNameAndYearBirth", persons);
        }
        else if (servletPath.equals("/add_person")) {
            String name = request.getParameter("name");
            String hobby = request.getParameter("hobby");
            String yearBirth = request.getParameter("yearBirth");

            int personsLen = em.createNamedQuery("Person.findAll").getResultList().size();
            Person newPerson = new Person(
                ++personsLen, name, hobby, Short.parseShort(yearBirth)
            );
            try {
                utx.begin();
                em = emf.createEntityManager();
                em.persist(newPerson);
                utx.commit();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        else if (servletPath.equals("/remove_person")) {
            String id = request.getParameter("id");

            Person person = null;  
            try {
                utx.begin();
                person = em.find(Person.class, Integer.parseInt(id));
                em.remove(person);
                utx.commit();
            } catch (Exception e) {
                e.printStackTrace();
            }
            servletPath = "/remove_person";
        }
        String url = servletPath;
        request.getRequestDispatcher(url).forward(request, response);
    }

}

      

The problem is my line inside the doPost method

String url = path; 

      

does not contain the .jsp part.

But if I add the ".jsp" part to the string url, how would I update the findAll request data inside remove_person.jsp, unless I go to the doGet servlet to collect new data first after adding or removing objects?

remove_person.jsp

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body>
        <h1>Remove Person</h1>
        <form action="remove_person" method="post">
            <table border="3">
                <tr>
                    <th>ID</th>
                    <th>Name</th>
                </tr>
                <c:forEach var="person" begin="0" items="${findAll}"> 
                    <tr>
                        <td>${person.id}</td> 
                        <td>${person.name}</td> 
                    </tr> 
                </c:forEach>
            </table>
            <strong>Remove person: </strong>
            <select name="id">
            <c:forEach var="person" items="${findAll}">
                <option value="${person.id}">${person.id}. ${person.name} </option>
            </c:forEach>
            </select>
            <input type="submit" id="remove_person" value="Remove" />
        </form>
        <br>
        <a href="index">Home page</a>
    </body>
</html>

      

Actually, is it possible to forward from doPost the doGet method of the same servlet? The reason I was trying to do this is because inside doGet I am already using this code:

List persons = em.createNamedQuery("Person.findAll").getResultList();
request.setAttribute("findAll", persons);

      

So why should I duplicate this code inside the doPost method, when I can forward the doGet method from doPost and call this code?

UPDATE:

Bad approach:

String url = servletPath;
request.getRequestDispatcher(url).forward(request, response);

      

The right approach:

String url = request.getContextPath() + servletPath;
response.sendRedirect(url);

      

+3


source to share


1 answer


Use a redirect instead of a redirect. Template (called Post / Redirect / Get ):

1) client calls url which does your update

2) the servlet sends a redirect to the client with the url to get.

3) the client calls the url from the redirect.



When a response from GET is returned, the browser has a GET URL, so the browser receives a URL that can be bookmarked. Also, this way the user cannot repeat the same data by pressing f5 or by pressing several times.

For using forward vs redirect see this tip :

forward

  • the forwarding is done inside the servlet
  • the browser is completely unaware that it happened, so its original URL remains intact.
  • any browser reload on the resulting page will simply repeat the original request with the original url

Redirecting

  • redirection is a two step process where the web app instructs the browser to get a second url that is different from the original
  • reloading the browser of the second url will not redo the original request, but rather get the second url
  • a redirect is marginally slower than a redirect as it requires two browser requests instead of one
  • objects placed in the scope of the original request are not available for the second request

Generally, you should use a forward if the operation can be safely repeated when you restart your browser on the resulting web page; otherwise, a redirect must be used. Typically, if an operation is doing an edit on the datastore, a redirect is required, not a redirect. This is just to avoid the possibility of unintentional duplicate edits in the database.

+4


source







All Articles