http forward and redirect in servlet with Intellij dynamic code classes reload to Jetty

1. Create simplest project with HttpServlet and JSP.

me@MacBook:~/dev/my-servlet$ find . -type f | grep -v .idea | grep -v target | grep -v *.iml
./pom.xml
./src/main/webapp/index.html
./src/main/webapp/redirected.jsp
./src/main/webapp/forwarded.jsp
./src/main/java/com/bawi/servlet/MyServlet.java

./pom.xml:

<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.bawi</groupId>
    <artifactId>my-servlet</artifactId>
    <packaging>war</packaging>
    <version>0.1-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.1</version>
            </plugin>

            <plugin>
                <groupId>org.eclipse.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>9.4.35.v20201120</version>
            </plugin>

        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

</project>

./src/main/java/com/bawi/servlet/MyServlet.java:

package com.bawi.servlet;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

@WebServlet(urlPatterns = {"/do"})
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String action = req.getParameter("action");
        if (action == null) {
            resp.setContentType("text/plain;charset=UTF-8");
            ServletOutputStream out = resp.getOutputStream();
            out.print("Hello from MyServlet!" +  new Date());
            return;
        }

        switch (action) {
            case "forward": {
                ServletContext servletContext = getServletContext();
                RequestDispatcher dispatcher = servletContext.getRequestDispatcher("/forwarded.jsp");
                dispatcher.forward(req, resp);
                break;
            }
            case "redirect": {
                resp.sendRedirect(req.getContextPath() + "/redirected.jsp");
                break;
            }
        }
    }
}

./src/main/webapp/index.html:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Home page</title>
    </head>
    <body>
        <p>This is home page.</p>
        <p>Call <a href="/do?action=forward">forward</a></p>
        <p>Call <a href="/do?action=redirect">redirect</a></p>
    </body>
</html>

./src/main/webapp/forwarded.jsp:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Forwarded page</title>
    </head>
    <body>
        <p>Action parameter: <%= request.getParameter("action") %>. This is forwarded page. Go to <a href="/">home</a></p>
    </body>
</html>

./src/main/webapp/redirected.jsp:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Redirected page</title>
    </head>
    <body>
        <p>Action parameter: <%= request.getParameter("action") %>. This is redirected page. Go to <a href="/">home</a></p>
    </body>
</html>
me@MacBook:~/dev/my-servlet$ mvn jetty:run
[INFO] webAppSourceDirectory not set. Trying src/main/webapp
[INFO] Reload Mechanic: automatic
[INFO] nonBlocking:false
[INFO] Classes = /Users/me/dev/my-servlet/target/classes
[INFO] Configuring Jetty for project: my-servlet
[INFO] Logging initialized @3943ms to org.eclipse.jetty.util.log.Slf4jLog
[INFO] Context path = /
[INFO] Tmp directory = /Users/me/dev/my-servlet/target/tmp
[INFO] Web defaults = org/eclipse/jetty/webapp/webdefault.xml
[INFO] Web overrides =  none
[INFO] web.xml file = null
[INFO] Webapp directory = /Users/me/dev/my-servlet/src/main/webapp
[INFO] jetty-9.4.35.v20201120; built: 2020-11-20T21:17:03.964Z; git: bdc54f03a5e0a7e280fab27f55c3c75ee8da89fb; jvm 1.8.0_241-b07
[INFO] Scanning elapsed time=26ms
[INFO] DefaultSessionIdManager workerName=node0
[INFO] No SessionScavenger set, using defaults
[INFO] node0 Scavenging every 660000ms
[INFO] Started o.e.j.m.p.JettyWebAppContext@760cf594{/,file:///Users/me/dev/my-servlet/src/main/webapp/,AVAILABLE}{file:///Users/me/dev/my-servlet/src/main/webapp/}
[INFO] Started ServerConnector@254f906e{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
[INFO] Started @4422ms
[INFO] Started Jetty Server

2. Testing

curl http://localhost:8080/do
Hello from MyServlet!Wed Dec 02 15:09:17 CET 2020

forward
Note action parameter is passed automatically

me@MacBook:~$ curl -vv http://localhost:8080/do?action=forward
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /do?action=forward HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Wed, 02 Dec 2020 14:11:26 GMT
< Content-Type: text/html;charset=utf-8
< Set-Cookie: JSESSIONID=node0vruwimbjjsy5uwywzhy51gy81.node0; Path=/
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< Content-Length: 248
< Server: Jetty(9.4.35.v20201120)
< 
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Forwarded page</title>
    </head>
    <body>
        <p>Action parameter: forward. This is forwarded page. Go to <a href="/">home</a></p>
    </body>
* Connection #0 to host localhost left intact
</html>* Closing connection 0

redirect
Note response code is 302 and redirect location is returned.

me@MacBook:~$ curl -vv http://localhost:8080/do?action=redirect
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /do?action=redirect HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
> 
< HTTP/1.1 302 Found
< Date: Wed, 02 Dec 2020 14:11:39 GMT
< Location: http://localhost:8080/redirected.jsp
< Content-Length: 0
< Server: Jetty(9.4.35.v20201120)
< 
* Connection #0 to host localhost left intact
* Closing connection 0

With option to follow redirect location:
Note action parameter is NOT passed to second request.

me@MacBook:~$ curl -v -L http://localhost:8080/do?action=redirect
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /do?action=redirect HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
> 
< HTTP/1.1 302 Found
< Date: Wed, 02 Dec 2020 17:14:59 GMT
< Location: http://localhost:8080/redirected.jsp
< Content-Length: 0
< Server: Jetty(9.4.35.v20201120)
< 
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost:8080/redirected.jsp'
* Found bundle for host localhost: 0x7fe33a818310 [can pipeline]
* Could pipeline, but not asked to!
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (::1) port 8080 (#0)
> GET /redirected.jsp HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Wed, 02 Dec 2020 17:14:59 GMT
< Content-Type: text/html;charset=utf-8
< Set-Cookie: JSESSIONID=node0gd5vxmsu6xgkh3ltwabj2jh810.node0; Path=/
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< Content-Length: 247
< Server: Jetty(9.4.35.v20201120)
< 
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Redirected page</title>
    </head>
    <body>
        <p>Action parameter: null. This is redirected page. Go to <a href="/">home</a></p>
    </body>
* Connection #0 to host localhost left intact
</html>* Closing connection 0
browser automatically makes second request to redirected page

3. Automatically reload classes and resources when debugging (change is seen after first request)

jetty server with update classes and resources
add exploded war
overwrite root context to / instead of default artifact name and version
me@MacBook:~$ curl  http://localhost:8080/do
Hello from MyServlet!Wed Dec 02 18:47:14 CET 2020

Now modify servlet java code

first request to trigger reloading

me@MacBook:~$ curl  http://localhost:8080/do
Hello from MyServlet!Wed Dec 02 18:48:03 CET 2020

second request returns modified response

me@MacBook:~$ curl  http://localhost:8080/do
Hello from MyServlet! - modifiedWed Dec 02 18:48:07 CET 2020

Leave a comment