This is pretty simple and straightforward. I want to throw a 503 error from the servlet side.
response.sendError(503);
When this is thrown, I need it to hit a custom error page. Basically a 503 error page itself, but with a few modifications.
Say I have 503.html, and I added
<error-page>
<error-code>503</error-code>
<location>/503.html</location>
</error-page>
in web.xml.
I created a war file, with a servlet which throws the 503 error, and web.xml with this content. I kept the 503.html in the parent folder location. (Should I keep it elsewhere ?)
I deployed the app in WLS, but this custom 503.html is not getting hit. I am getting the generic 503 error.
Am I missing something?
My code is below:
webapp1.war
->web-inf
->web-inf->classes->prject4->Class1.class
->web-inf->jsp->error->custom.html
web.xml
<?xml version="1.0"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>Class1</servlet-name>
<servlet-class>project2.Class1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Class1</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<error-page>
<error-code>503</error-code>
<location>/WEB-INF/jsp/error/custom.html</location>
</error-page>
</web-app>
class1.java
public class Class1 extends HttpServlet
{
private ServletConfig config;
public void init(ServletConfig config)throws ServletException
{
this.config=config;
}
public void service (HttpServletRequest request, HttpServletResponse response)
throws IOException
{
response.setContentType("text/html");
ServletOutputStream l_out = response.getOutputStream();
response.sendError(503);
}
}
Ok, this was a minor error which I didn't figure out in the beginning.
In my web.xml the servlet-mapping was given as /*, which was causing an infinite loop condition as it throws the same code for which it has been mapped. So I had to adjust the servlet mapping so that Class1 doesn't map to any error pages - like say /images/*.
And then everything started working fine. :)
You can also try handling it with custom Error Handler.
public void service (HttpServletRequest request, HttpServletResponse response)
throws IOException
{
try
{
//some error generating code
throw new Exception("503_Exception");
}
catch(Exception e)
{
response.sendRedirect(HandleError.handle(e, request));
}
}
A separate class to handle errors. This can handle different types of errors.
You can add functionality to log stacktrace, send out emails if something is wrong etc.
public class HandleError{
public static String handle(Throwable t, javax.servlet.http.HttpServletRequest request)
{
String sErrorMsg = t.getMessage();
if (sErrorMsg.equals("503_Exception")) {
request.setAttribute("msg", Constants.EINVALSESSION);
return "/503.html";
}
return "/default_error.html";
}
}
If you are using Maven as your project build tool then it will look in the src/main/webapp directory, so for example our config looks like this:
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/jsp/error/error404.html</location>
</error-page>
and our error404.html sits in the folder:
${PROJECT_NAME}/src/main/webapp/WEB-INF/jsp/error/
If your not using Maven the path in the location will have a base directory of wherever you put your index.jsp
I guess there's a minimum limit on the number bytes your custom error page has. The lower limit is usually 512 Bytes. See Important note for your Custom error pages. I've seen this behavior in Google-Chrome too when using Tomcat.
Related
I currently have apache tomcat running on my Ubuntu AWS EC2 server. I have all my html/js exclusive webapps served there, and those work fine. I am currently trying to import my Java project, but I cant get my AJAX calls to reach my java (I'm getting a 404 error). What is weird to me is that my local version works perfectly fine with making these AJAX requests. I suspect I may have a firewall blocking me after doing this Tomcat SSL Guide. I'll post some code, maybe I have a logic mistake.
web.xml
I used to not have this commented out, but I tried annotations. This worked on local, but not on the server.
<?xml version="1.0" encoding="UTF-8"?>
<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_3_1.xsd"
version="3.1">
<!-- <servlet>
<servlet-name>response</servlet-name>
<servlet-class>Demo.ServiceReceiver</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>response</servlet-name>
<url-pattern>/sendIt</url-pattern>
</servlet-mapping> -->
</web-app>
ServiceReceiver.java
#WebServlet("/sendIt")
public class ServiceReceiver extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String first = request.getParameter("stuff");
String second = request.getParameter("other");
Driver driver = new Driver();
String ret = driver.runner();
response.getWriter().write(ret);
}
}
index.js
$(document).ready(function() {
$("#testClick").click( function()
{
testerClick();
}
);
});
function testerClick() {
var send;
send = {
stuff:"ayyyye",
other:"naayyyyyy"
};
$.ajax({
url: 'sendIt',
data: send,
type:'GET',
cache: false,
contentType: "application/json; charset=utf-8",
success:function(data){
alert(data);
},
error:function(error){
alert(error);
}
});
}
Again, this all works on local, so I suspect I'm unknowingly blocking myself. The website I am trying to reach is https://tyleralangreen.com/Dice_Game_war/. If you click the button, you will see that you are given a 404. The address looks right: https://tyleralangreen.com/Dice_Game_war/sendIt?stuff=ayyyye&other=naayyyyyy&_=1521266411409
I have found the issue. I went through all my tomcat logs looking for errors, and one tiny error said that it wasn't going to compile my Java class. Oh wow, thanks for the near silent error. Anyways the issue said:
org.apache.catalina.core.ApplicationContext.log Marking servlet
[Demo.ServiceReceiver] as unavailable 19-Mar-2018 01:26:15.444 SEVERE
[ajp-nio-127.0.0.1-8009-exec-8]
org.apache.catalina.core.StandardWrapperValve.invoke Allocate
exception for servlet [Demo.ServiceReceiver]
java.lang.UnsupportedClassVersionError: Demo/ServiceReceiver has been
compiled by a more recent version of the Java Runtime (class file
version 53.0), this version of the Java Runtime only recognizes class
file versions up to 52.0 (unable to load class [Demo.ServiceReceiver])
I looked and I am compiling with Java 9 on intellij, but I have Java 8 installed on my server. I changed my default JDK on IntelliJ to Java 8 and everything worked. I hope I help others.
On my web application, which is hosted on Google App Engine, whenever I call a Servlet by typing in the URL on a browser, this results in two calls being made to the Servlet. However, if I make a call to the Servlet by clicking on an anchor, then only one call is made.
What is the cause and how can I correct this behavior?
Web.xml
<servlet>
<servlet-name>ServletOne</servlet-name>
<servlet-class>com.test.nz.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletOne</servlet-name>
<url-pattern>/myservlet</url-pattern>
</servlet-mapping>
Servlet:
public class MyServlet extends HttpServlet {
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException
{
final Logger log = Logger.getLogger(MyServlet.class.getName());
log.info("Here in MyServlet");
}
}
Update:
The issue appears to be caused by Google Chrome making requests on its own. Whenever I type in a URL, a request is made before I actually press enter, followed by the actual request. Is there any way to disallow these type of requests to my application?
I had the same issue, only in Chrome, turns out the servlet was mapped to / and was accepting requests for favicon.ico as well. For me this is the source of the second request.
I am new to java programming in the web environment and am having trouble understanding the flow.
For an assignment coming up I need to build a web application accessible with an API via get/post requests. For the tutorials that I have followed here is the flow I understand.
User visits top domain->
Per configuration user is directed to a jsp page->
Jsp contains javascrip and html. To access server code (for database, computations and other processes) the jsp page can use RCP to make async requests to a java servlet->
Java servlet does server handling and returns response to jsp page
Is this the required flow or can a user directly acess a servlet, and can that servlet handle get/post, or do I have to handle at the jsp and foward to the servlet?
Servlets can be accessed directly. You just need to extend HttpServlet and implement doGet and/or doPost. For example:
public class MyServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException {
Integer param = null;
try {
param = Integer.parseInt(req.getParameter("param"));
}
catch(NumberFormatException e) {
}
}
}
You also need to map your servlet to url in web.xml:
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.adam.test.server.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/my_servlet</url-pattern>
</servlet-mapping>
Now you can access your servlet using url like this:
http://domain.com/my_servlet?param=123
I think that my folder hierarchy is wrong.
Should the .html and .jsp file is in WEB-INF?
I tried to move them there, but I received an error 404.
No, everything you put in the WEB-INF folder will NOT be available to the users of your web application. Your hierarchy looks OK.
WEB-INF resources not directly visible for the public. You can use webservlet annotation. For example;
#WebServlet(urlPatterns = {"/adminlogin", "/register"})
or servlet mapping(old-fashioned),
web.xml :
<servlet>
<servlet-name>LoginController</servlet-name>
<servlet-class>yourPackage.LoginController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginController</servlet-name>
<url-pattern>/adminlogin/</url-pattern>
<url-pattern>/logout/</url-pattern>
<url-pattern>/register/</url-pattern>
<url-pattern>/userlogin/</url-pattern>
</servlet-mapping>
LoginController
//post get method
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String userPath = request.getServletPath();
if (userPath.equals("/logout")) {
//Your Model
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
} ...
}
this is my first time that I work on a Java project that use HttpServlet.
So I know that an HttpServlet is a program that run on a Web Application server and act as a middle layer between a request coming from a Web browser or other HTTP client and databases or applications on the HTTP server. So the servlet extend the competence of my application server.
I have some doubt to understand how exactly work this servlet founded into my project, into web.xml file I found this configuration:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>My Project</display-name>
<listener>
<listener-class>it.sistinf.ediweb.quartz.QuartzListener</listener-class>
</listener>
<servlet>
<servlet-name>edimon</servlet-name>
<servlet-class>it.sistinf.ediweb.monitor.servlets.Monitoraggio</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>edimon</servlet-name>
<url-pattern>/edimon.do/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/logon.jsp</welcome-file>
</welcome-file-list>
<taglib>
<taglib-uri>displaytag</taglib-uri>
<taglib-location>/WEB-INF/displaytag-11.tld</taglib-location>
</taglib>
</web-app>
So reading some documentation it seem to understand that I have to tell the servlet container (or application server) what servlets to deploy, and what URL's to map the servlets to.
In the previous case I am configuring a servlet named edimon implemented by the Monitoraggio class.
Then it is mapped the servlet to a URL or URL pattern. In this case the edimon servlet is mapping with the /edimon.do/* URL pattern. So when it is called something that match with the previous pattern the edimon servlet is performed.
Then into my Monitoraggio class that implement the HttpServlet I found the service() method:
public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
LoggerMDC.setup(req, res);
Logger logger = (Logger) Logger.getStdLogger(Monitoraggio.class); // do not declare 'logger' as static field in order to work with MDC
String service = req.getParameter("serv");
char serviceId = Utility.getServizio(req.getParameter("serv"));
if (checkSession(req, serviceId) == false) {
gotoPage(ConfigurationFactory.getPropertiesPages().getProperty("pagina_errore_session"), req, res);
return;
}
LoggerWatch loggerWatch = new LoggerWatch(Monitoraggio.class, Long.valueOf(System.getProperty(Constants.Keys.CONFIG_STATS_WARNING_THRESHOLD, String.valueOf(LoggerWatch.DEFAULT_WARNING_THRESHOLD))).longValue());
if (logger.isTraceEnabled())
logger.trace("lanciaServizio() | logger threshold: " + loggerWatch.getWarningThreshold());
loggerWatch.start();
loggerWatch.info(new StringBuffer("service() | servizio: [").append(service).append("] | service start").toString());
String paginaDaLanciare = lanciaServizio(serviceId, req, res);
String executionTime = loggerWatch.getInfoTime();
//Modifica per export
if (req.getSession().getAttribute("export") == null) {
gotoPage(paginaDaLanciare, req, res);
}
loggerWatch.info(new StringBuffer("service() | servizio: [").append(service).append("] | [").append(executionTime).append("] after forward to ").append(paginaDaLanciare).toString(), true);
loggerWatch.stop();
req.getSession().removeAttribute("export");
req.getSession().removeAttribute("stringaXML");
req.getSession().removeAttribute("downbyte");
return;
}
Reading on the documentation it receives standard HTTP requests from the public service method and dispatches them to the doXXX methods defined in this class
So what exatly do this method? I can't understand how the servlet load the JSP
The documentation you read describes what the service() method of HttpServlet does by default. Since your servlet overrides the service() method and provides a different implementation, it doesn't do that anymore. Instead, it does... what the code in the method does.
A servlet doesn't "load a JSP". I don't see how JSPs have any relation to the servlet code you posted. Maybe gotoPage() does tell the container to forward the request to a JSP. You should look at the documentation and/or code of that method to know what it does.