I'm creating a Java web application using JSP and Servlets, TomCat 9 and IntelliJ. The tutorial I'm following uses Eclipse, where the instructor just runs the project as Run As > Run On Server and everything works seamlessly.
In IntelliJ, things seem all messed up.
This is my project structure -
This is the Run Configuration -
I have the web.xml setup as -
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Archetype Created Web Application</display-name>
<welcome-file-list>
<welcome-file>login.do</welcome-file>
</welcome-file-list>
</web-app>
So, any requests to localhost:8080, or in the case of IntelliJ, http://localhost:8080/jspservlet_war_exploded/ should be redirected to login.do, which is handled by LoginServlet -
package app;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
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.io.PrintWriter;
#WebServlet(urlPatterns = "/login.do")
public class LoginServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
String pass = req.getParameter("password");
req.setAttribute("name", name);
req.setAttribute("password", pass);
RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/login.jsp");
requestDispatcher.forward(req, resp);
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
req.setAttribute("name", name);
RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/welcome.jsp");
requestDispatcher.forward(req, resp);
}
}
At first, I was testing the doGet() method in LoginServlet, by just manually adding the ?name=xxx&password=xxx query string in the start page - http://localhost:8080/jspservlet_war_exploded/. These attributes were set in the request and then forwarded to login.jsp, which would just display the attribute values using ${name} and ${password}. Things worked fine until this step.
Then, I changed the login.jsp page to include a simple form that has an input field to enter the user's name, and have it sent to /login.do via the action attribute, using the POST method. This is where things blew up.
Here is login.jsp -
<%# page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Login Page</title>
</head>
<body>
<h1>Welcome</h1>
<p>Time on server is <%= new Date()%></p>
<%--<p>Your name is ${name} and password is ${password}</p>--%>
<p>pageContext.request.contextPath: ${pageContext.request.contextPath}</p>
<form action="/login.do" method="post">
<label for="inp">Enter your name </label>
<input id="inp" type="text" name="name"/>
<button>Submit</button>
</form>
</body>
</html>
which results in this page -
Now, as soon as I hit "submit", the request seems to go to localhost:8080/login.do (because that's what the action attribute's value is), and that throws an error -
Based on the other questions I've read here, it looks like that happens because the context path (ie. root of the application) is http://localhost:8080/jspservlet_war_exploded/, and all locations are relative to this path(?). So, the recommended way seems to be ${pageContext.request.contextPath}.
Based on that, if I change the action attribute to action="${pageContext.request.contextPath}/login.do", then things work again.
However, now I'm trying to redirect from the doPost() method in LoginServlet to TodoServlet, like so -
resp.sendRedirect("/todo.do");
This again causes a 404, because the URL becomes http://localhost:8080/todo.do, whereas it should be http://localhost:8080/jspservlet_war_exploded/todo.do.
How do I fix things so that all resources are deployed relative to http://localhost:8080/jspservlet_war_exploded/ by default, and I can just specify the URL pattern directly in action or resp.sendRedirect()?
Change the deployment context in the Run/Debug configuration:
If you want the app to work with any context you should use the relative paths instead like described here.
Instead of resp.sendRedirect("/todo.do"); use resp.sendRedirect("todo.do"); or resp.sendRedirect(req.getContextPath() + "/todo.do");
did you try this :
resp.sendRedirect("todo.do");
Related
This question already has answers here:
How to install JSTL? The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved [duplicate]
(5 answers)
Closed 2 years ago.
So ${} did work. But the JSTL jar files that I'm using made to where the ${} doesn't work anymore. These are my JSTL jar files. jstl-1.2 (1).jar, jstl-impl-1.2.jar, jstl-standard.jar. I am following Navin tutorial on Servlet & JSP Tutorial | Full Course on youtube. He skipped JSTL jar files. I'm a junior developer trying to understand why my ${} isn't working anymore.
Question: Why did my ${} tag not work anymore?
Please be gentle. :D
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html >
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<c:forEach items="${students}" var="s" >
${s} <br>
</c:forEach>
</body>
</html>
package com.Demo;
public class Student {
int rollno;
String name;
#Override
public String toString() {
return "Student [rollno=" + rollno + ", name=" + name + "]";
}
public int getRollno() {
return rollno;
}
public void setRollno(int rollno) {
this.rollno = rollno;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(int rollno, String name) {
super();
this.rollno = rollno;
this.name = name;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0">
<display-name>JSTLexample</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
package com.Demo;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet("/DemoServlet")
public class DemoServlet extends HttpServlet{
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
//String name = "Navin";
List <Student> studs = Arrays.asList(new Student(1, "brandon"), new Student(2, "Micheal"), new Student (3, "Charles"));
request.setAttribute("students", studs);
RequestDispatcher rd = request.getRequestDispatcher("display.jsp");
rd.forward(request, response);
}
}
That "${}" is EL expression language syntax. You require to configure your "web application" web.xml or variant to use the JSTL (Java Standard Tag Library) .jar file in either the servers /commons/lib folder with server.xml (obviously not) or /WEB-INF/lib of your application.
Then call in the names of each tag prefix you wish to use declared at the top of your JSP page.
Tomcat has a few ways of achieving it.
Also your doctype should be
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
Yout .tld tag library descriptor should be in the WEB-INF folder.
define the taglib location in your web.xml file
<jsp-config>
<taglib>
<taglib-uri>http://java.sun.com/jstl/core</taglib-uri>
<taglib-location>/WEB-INF/c.tld</taglib-location>
</taglib>
</jsp-config>
Also, your bean class should be declared in the web.xml and the page declarations to call it in the page at the top too.
Not a bad point to recheck the above if things go wrong.
The servlet you have made is a GET request servlet , they pass parameters on the URL by
?name=**valuOFthisPart&anid=**somethinHere&terminus=
if you use ${Param.student} added as student past the "?" on the url that may be usable to the EL something like this
**?students=name=**valuOFthisPart&next1=somethinHere&next2=somethinHere&terminus=
A POST servlet cannot carry parameters on the URL and is what you are trying to do by the code so is what the request.setAttribute is setting doing is for a POST request (POST requests do carry tokens).
Too, the setAttribute on request object is available by the interface of its class of which it can be done at class level by a wrapper sub class too as next
javax.servlet.ServletRequestWrapper requestWrpp = new javax.servlet.ServletRequestWrapper(request);
requestWrpp.setAttribute("students", studs);
HOWEVER, while more modern versions of web container recognise complex types such as List and Map (but probably not Student class) you may be able to use the code there by what i vaguely think i remember the clause of use of complex objects in JSP processing is and that being it is understood to be convertible to string.
Student is unrecognizable to the web app parser rules, however if you wrote Student to extend ( Map int,String ) then the runtime and compiler may be able to use that set up inside as a ( Map K,V )
Actually, this cannot work because you try to do this in the servlet before JSP processing by the response [ ! unless the Student class is only a servlet support class in the classes folder. (not bean syntax class)
see next paragraph ].
You are trying to use a class the way a bean operates , and a bean must be declared both in the web.xml and the page and the servlet notified too with a Student object reference from either classes or /classes/beans folder !!!
If it is a bean it should be in a bean folder (if it is not a bean and only a support processing class should be in classes with the servlet packaged or not) and called by the response in the JSP parser , but properly loaded, correctly updated current instance of it in the web app user session should be used (something JSF does more easily).
You can obtain current session and beans for servlet instance use by acquiring the web app context and initial instance thread to find the bean you want, its current instance and current state (requires to be a session bean unless the values are constant or it only outputs by set get processing instantly) to get its' current values. Bean classes must be declared throughout the app configuration not dissimilar to servlets but are different with rigid rules of declaration for runtime and syntax.
Final note
// the first argument should be a string NOT an int
req.setAttribute("String Object",(java.lang.Object)anObject);
//NOTE: That object must be convertible to a String from a recognizable java language core class !!!
Just a quick note about post requests, actually it can carry a query string but is considered a bizzarre action inside a Java framework.
I'm building an application and currently working on my login page. When I launch Tomcat it starts up fine and opens a browser which displays my index.jsp page to log in. However on successful log in I am not forwarded to the next jsp page as instructed in the login servlet, instead I get a 404 "The origin server did not find a current representation for the target resource or is not willing to disclose that one exists."
I have checked the web.xml I which looks fine, I'm using annotations to map servlets. I dont know what else to try. Even if I deliberately enter incorrect log in details I receive the same error rather than the output contained in the "else" statement.
#WebServlet("/Login")
public class Login extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String uname = request.getParameter("username");
String pwd = request.getParameter("password");
if (uname.equals("MyUsername") && pwd.equals("MyPassword")){
RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/welcome.jsp");
dispatcher.forward(request, response);
}else {
PrintWriter writer = response.getWriter();
writer.write("User details not recognised");
}
}
}
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>welcome.jsp</welcome-file>
</welcome-file-list>
</web-app>
If you forward to /WEB-INF/welcome.jsp, the server looks for a file welcome.jsp inside a directory WEB-INF in your context root, that is the WEB-INF directory.
So, you should not forward to /WEB-INF/welcome.jsp, but to /welcome.jsp.
Anyway, WEB-INF is reserved and does not work, no matter where you redirect.
I've enough knowledge to develop in Java SE/JavaFX (Desktop), but it's my 1st time with Java EE (WEB). I'd like to build a basic app only getting Login and Password in a HTML/JSP, calling a Servlet (in Java) and returning a single message to the HTML/JSP. This time I want to do that the "hard way", without any IDE. So, I've installed Tomcat 7.0 and I have those modules:
Java (this example only receive from HTML/JSP)
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class loginServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String userName = request.getParameter("userName");
String password = request.getParameter("password");
out.println("<html>");
out.println("<body>");
out.println("Hello " + " " + userName + "welcome to my blog");
out.println("Your password is : " + " " + password + "<br>");
out.println("</body></html>");
}
}
HTML/JSP
<!DOCTYPE html>
<html lang ="pt-br">
<head>
<title> loginServlet </title>
<meta http-equiv = ”Content-Type” content=”text/html; charset=UTF-8”>
<link rel="stylesheet" type="text/css"
href="c:/java/html/css/estilo.css"/>
</head>
<body>
<h2> Login Page </h2>
<p>Please enter your username and password</p>
<form method="GET" action="loginServlet">
<p> Username <input type="text" name="userName" size="50"> </p>
<p> Password <input type="text" name="password" size="20"> </p>
<p> <input type="submit" value="Submit" name="B1"> </p>
</form>
</body>
</html>
WEB.XML
<?xml version="1.0" encoding="ISO-8859-1" ?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>loginServlet</display-name>
<description>
This is a simple web application with a source code organization
based on the recommendations of the Application Developer's Guide.
</description>
<servlet>
<servlet-name>loginServlet</servlet-name>
<servlet-class>java.loginServlet.WebContaint.WEB-
INF.classes.loginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>loginServlet</servlet-name>
<url-pattern>/loginServlet</url-pattern>
</servlet-mapping>
</web-app>
Paths and folders
loginServlet.class is in C://java/loginServlet/WebContaint/WEB-INF/classes/
loginServlet.jsp is in C://java/loginServlet/WebContaint/
web.xml is in C://java/loginServlet/WebContaint/WEB-INF/
loginServlet.war is in C:\Program Files\Apache Software Foundation\
Tomcat 7.0\webapps
When I try to call in my Chrome, using a localhost (http://localhost:8080/loginServlet), I receive a 404 Error.
Your Servlet class name looks wrong:
<servlet-class>java.loginServlet.WebContaint.WEB-
INF.classes.loginServlet</servlet-class>
I'm not even sure it is possible to place user code in the java namespace (it might be protected), regardless I wouldn't recommend it. Also having WEB-INF.classes in the package name is not right. Splitting the name over multiple lines is also not right.
In fact, in your code, you don't even have a package name, so you should be able to write:
<servlet-class>loginServlet</servlet-class>
Read this tutorial on creating servlets, which addresses naming of servlet classes and cross-referencing them from a web.xml file.
Note, you don't even need a web.xml file for a simple example like this, you can just use an #WebServlet annotation.
Aside:
Current version of Tomcat is 9.x, I wouldn't recommend using old versions like 7.x.
Stick to Java naming conventions (e.g. call your class LoginServlet, not loginServlet).
To learn JEE, I recommend using the official JEE tutorial.
A stranger thing happaned: it's seem that only (directly) servlet (loginServlet.class) was called. The HTML (loginServlet.jsp) didn't show the page where Login and Password can be informed. And i saw the msg "Hello userName welcome to my blog" that is generate by Servlet (loginServlet.class). With Login and Password null, of course.
From your earlier question, you say that you are invoking the app like this:
http://localhost:8080/loginServlet
That isn't going to tell the app to use the jsp file you have created, which you have named loginServlet.jsp. The breakdown of the call you made is that you are using the http protocol over port 8080 to access your tomcat server. You provide the path /loginServlet, which is identifying your web application (by default, it gets its name from the war file which you deployed, which you called loginServlet.war). Once in the app it will try to open a welcome file if there is one. But you haven't provided a welcome file or an empty name mapping for the servlet, so, normally, I would just expect a 404 not found error for that url.
The url of your servlet would be
http://localhost:8080/loginServlet/loginServlet
The first loginServlet identifies your app, the second loginServlet identifies the servlet itself. So, accessing that url will directly access the servlet processing.
But, you don't want your user to directly invoke that. Instead, you want your jsp file to show, and then for it to send data to server http://localhost:8080/loginServlet/loginServlet to trigger the servlet processing.
Your two options to access the jsp are either to provide a welcome file or to provide the fully qualified name in your request string.
A fully qualified name request would be:
http://localhost:8080/loginServlet/loginServlet.jsp
If, instead you want to assign a welcome file, you could add the following section to your web.xml:
<welcome-file-list>
<welcome-file>loginServlet.jsp</welcome-file>
</welcome-file-list>
Then the following access string should bring up the loginServlet.jsp page:
http://localhost:8080/loginServlet
This question already has answers here:
Change default homepage in root path to servlet with doGet
(2 answers)
Closed 7 years ago.
I am trying to redirect to an HTML page from a servlet. For debugging, I have minimal amount of code in my servlet, HTML page and in web.xml
I can load HTML page fine in browser without the servlet. But when I try to redirect to the same page from a servlet, only a blank page is rendered. No error is displayed.
Following is the relevant code.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>name</display-name>
<listener>
<listener-class>net.semandex.salsa.webapp.SalsaWebApp</listener-class>
</listener>
<servlet>
<description>
</description>
<display-name>SalsaValidationServlet</display-name>
<servlet-name>SalsaValidationServlet</servlet-name>
<servlet-class>net.semandex.salsa.validationServlets.SalsaValidationServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SalsaValidationServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>20</session-timeout>
</session-config>
</web-app>
Servlet
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SalsaValidationServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String path = request.getPathInfo();
if(path == null) return;
String []p = path.split("/");
if( !path.endsWith("licenseValidation.html") )
//request.getRequestDispatcher("/auth/licenseValidation.html").forward(request, response);
response.sendRedirect( request.getContextPath() + "/auth/licenseValidation.html" );
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doGet(req, resp);
}
}
HTML Page - licenseValidation.html
<html>
<head>
<title>License upload page</title>
</head>
<body>
<form>
<input type="text" name="name"/><br>
<input type="text" name="group"/>
<input type="text" name="pass"/>
<input type="submit" value="submit">
</form>
</body>
</html>
Why is this code loading a blank page and not an HTML page?
Redirection does happen but to a blank page. Status code for the new URL in browser is 200 but the response is empty in debugger.
Edit:
The problem was "/*" URL pattern as stated by BalusC. Found more useful information in his another answer.
Difference between / and /* in servlet mapping url pattern
The request URL that you are using doesn't have any extra path information associated. So the request.getPathInfo() is returning null and the redirection is not getting triggered.
If you want to redirect to any page, even if there are no extra path info, you need to remove the null check. Just redirect it :
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//String path = request.getPathInfo();
//if(path == null) return;
//String []p = path.split("/");
//if( !path.endsWith("licenseValidation.html") )
//request.getRequestDispatcher("/auth/licenseValidation.html").forward(request, response);
response.sendRedirect( request.getContextPath() + "/auth/licenseValidation.html" );
}
request.getPathInfo returns null if there are no extra path info : getPathInfo
Suppose you have defined the servlet-mapping as this:
<servlet-mapping>
<servlet-name>SalsaValidationServlet</servlet-name>
<url-pattern>/salsadb/*</url-pattern>
</servlet-mapping>
And you are sending the request to this URL:
http://localhost:8080/<appName>/salsadb/some_text
This time pathInfo will not be null; it will have the value as /some_text, which is the extra path info associated with the URL.
EDIT:
The SalsaValidationServlet is mapped to serve all the requests to the application. The first request that is coming is this :
http://localhost:8080/salsadb/
The doGet method of SalsaValidationServlet gets invoked and the value of pathInfo is /. It redirects the request to /auth/licenseValidation.html.
Now the browser will send a new request to the redirect URL, which in this case is : /auth/licenseValidation.html. Again the doGet method of SalsaValidationServlet is getting invoked, because it is mapped with this /* : execute for any request to the application. This time the value of pathInfo is /licenseValidation.html, which is not satisfying this if condition:
if( !path.endsWith("licenseValidation.html") )
and because of this the redirection is not getting triggered this time.
I think this will clarify the problem. If possible, change the servlet-mapping to serve only the required requests to the application.
I think your url-pattern tag is the problem please change it to something other than /*.
I didn't understand why you are trying to redirect to a image?
However if you still want to see the image then add the salsa-icon.png in a HTML/jsp page and redirect to it.
I am new to servlets and i have developed a html page which has a submit button that triggers
my servlet.Everything is working fine .But now i want to use GET method as my html page is not posting anything.Hence i made the following changes:
1)In my page.html file, i replaced method="POST" with method="GET".
2)I changed doPost with doGet in my servlet.
But i'm getting error message that "GET not allowed here".Why is it so?
Here are the original files which work correctly(prior to making changes):
My page.html page:
<html>
<head>
<title>A simple revision of servlets</title>
</head>
<body>
<form method="POST" action="Idiot">
<input type="SUBMIT">
</form>
</body>
</html>
My Deployment Descriptor:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<servlet>
<servlet-name>TangoCharlie</servlet-name>
<servlet-class>Revise</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TangoCharlie</servlet-name>
<url-pattern>/Idiot</url-pattern>
</servlet-mapping>
</web-app>
And finally my servlet file named Revise.java
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class Revise extends HttpServlet
{
public void doPost(HttpServletRequest request,HttpServletResponse response) throws IOException,ServletException
{
response.setContentType("text/html");
PrintWriter out=response.getWriter();
out.println("<html><body><h3>Hello India</h3></body></html>");
out.println("Hello");
}
}
I don't want to add any input fields.My aim is just to run the servlet without a single button on html page that too called using "POST" method.
Just do the job in doGet() method (don't forget to properly rebuild/redeploy/restart the project after editing servlet code, otherwise you will still face a "HTTP 405: method not allowed" error) and invoke the URL of the servlet directly instead of the URL of the JSP in the browser's address bar.
So, the URL in browser address bar should be
http://example.com/contextname/Idiot
instead of
http://example.com/contextname/page.html
Unrelated to the concrete problem, emitting HTML in a servlet is bad design. It should be done by a JSP. You can use RequestDispatcher#forward() to forward the request to a JSP after finishing the doGet() business logic. Further, packageless classes are also a bad design. You should always put publicly reuseable Java classes in a package. Packageless servlets will only work on certain combinations of Tomcat + JVM versions.
See also:
Our servlets wiki page - contains concrete (and properly designed) Hello World examples