0

I have a configuration page in my app. When user changes configuration and submits it, I would like to reload my application with new configuration properties and then redirect to some page. I was able to reload my application using some suggestions I found here Start / stop a web application from itself?

but I am not able to redirect to new page after the application has reloaded.

More details.

public class ConfigurationServlet extends HttpServlet implements ContainerServlet{

    private static final long serialVersionUID = 1L;
    private SalsaEnvironment salsaEnv;
    protected Host host = null;
    protected Wrapper wrapper = null;
    protected Context context = null;

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // update configuration properties
        .
        .
        . 

        // reload app once configuration is changed
        restartWebApp(resp.getWriter(), "/salsadb");

        // simple redirect/forward - does not work - gives following exception
        // java.lang.NullPointerException org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:610)
        //resp.sendRedirect("/salsadb/account");
        //req.getRequestDispatcher("/account");

        // invalid old session, create a new one and try to redirect - does not work
        req.getSession(false).invalidate();
        req.getSession(true);
        req.getRequestDispatcher("/account");
    }

    @Override
    public Wrapper getWrapper() {
        // TODO Auto-generated method stub
        return this.wrapper;
    }

    @Override
    public void setWrapper(Wrapper wrapper) {
        this.wrapper = wrapper;
        if (wrapper == null) {
            context = null;
            host = null;
        } else {
            context = (Context) wrapper.getParent();
            host = (Host) context.getParent();
            Engine engine = (Engine) host.getParent();
            try {
            } catch (Exception e) {
                // ?
            }
        }
    }

    private void restartWebApp(PrintWriter writer, String path){
        if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
            System.out.println("invalid path");
            return;
        }
        String displayPath = path;
        if( path.equals("/") )
            path = "";

        try {
            Context context = (Context) host.findChild(path);
            if (context == null) {
                /*writer.println(sm.getString
                               ("managerServlet.noContext",
                                   RequestUtil.filter(displayPath)));*/
                System.out.println("no context");
                return;
            }

            context.reload();
            //writer.println(sm.getString("managerServlet.reloaded", displayPath));
            System.out.println("reloaded webapp");
        } catch (Throwable t) {
            log("ManagerServlet.reload[" + displayPath + "]", t);
            /*writer.println(sm.getString("managerServlet.exception",
                                        t.toString()));*/
            System.out.println("excpetion during reloading the webapp");
        }
    }
Community
  • 1
  • 1
Pratik Patel
  • 1,305
  • 1
  • 17
  • 44
  • Are you reloading the webapp just for properties change ? If so, you can change properties at runtime without reloading the webapp. (EDIT : it's not OOTB and need a bit of work but might be more efficient). – Gaël J Jan 06 '16 at 10:44

1 Answers1

1

You'll probably not be able to do that as your server-side code has just been restarted.

I'd recommend an AJAX based client-side approach, where you constantly ping some servlet of yours until app is "back up" and then move to the new page via JavaScript.

For this to work, you'd first send the redirect to the reload-checking page and then (say after 1s to allow the browser fetch the redirected page) initiate the restart:

    req.getSession(false).invalidate();
    req.getSession(true);
    resp.sendRedirect("check_restart_status.jsp");
    //Use a timer or whatever
    new Thread(() -> {
        try{
          Thread.sleep(5000);
        } catch(InterruptedException ie) {
          return;
        }
        restartWebApp("/salsadb");
    }).start();
Jan
  • 13,738
  • 3
  • 30
  • 55
  • Problem is that the browser immediately shows an error page after request is handled in my servlet. I don't want to show an error page to the user. – Pratik Patel Jan 06 '16 at 10:45
  • See my edit: You give the browser time to load the "wait for restart" page and THEN initiate the actual restart. – Jan Jan 06 '16 at 10:50