Monday, April 4, 2011

Chapter 29: WebApp Log

One of the most important requirements for any error handling mechanism is the presence of a Log File. The log file is used to capture all the events that happen in the application and it helps the developer debug his application in case anything doesn't work as expected. In this chapter, we are going to take a look at the WebApp Log and see how it is useful in the debugging part of Exception Handling.

So, lets get started!!!

The WebApp Log:

The Server Configuration File defines the component elements that comprise the “Server,” a singleton element that represents the entire JVM. Two of these elements are the Access log and the Activity log. These are simple text files to which the container appends messages. While containers differ, Tomcat implements the specification very closely, except for just a few things. Since Tomcat is our server of choice for this series on SCWCD Certification, lets now take a look at how Tomcat uses logs.

By default, log files are created in the “logs” directory relative to the home directory of Tomcat installation ($CATALINA_HOME). You can specify a different directory, using either a relative (to $CATALINA_HOME) or absolute path, with the “directory” attribute in the server.xml file. Different containers handle this in various ways, but Tomcat creates two new files, access and activity, every time you start the server.

Tomcat implements several log files. One of them is the Global log file (for example, catalina_log.2011-04-04.txt). Its contents look like this after starting, stopping, and starting again:

2011-04-04 13:52:29 HttpConnector Opening server socket ...
2011-04-04 13:52:34 HttpConnector[8080] Starting ...
2011-04-04 13:52:34 HttpProcessor[8080][0] Starting ...
2011-04-04 13:52:34 HttpProcessor[8080][1] Starting ...
2011-04-04 13:52:34 HttpProcessor[8080][2] Starting ...
2011-04-04 13:52:34 HttpProcessor[8080][3] Starting ...
2011-04-04 13:52:34 HttpProcessor[8080][4] Starting ...
2011-04-04 14:33:36 HttpProcessor[8080][4] Stopping ...
2011-04-04 14:33:36 HttpProcessor[8080][3] Stopping ...
2011-04-04 14:33:36 HttpProcessor[8080][2] Stopping ...
2011-04-04 14:33:36 HttpProcessor[8080][1] Stopping ...
2011-04-04 14:33:36 HttpProcessor[8080][0] Stopping ...
2011-04-04 14:33:36 HttpConnector[8080] Stopping ...
2011-04-04 14:34:52 HttpConnector Opening server ...
2011-04-04 14:34:55 HttpConnector[8080] Starting ...
2011-04-04 14:34:56 HttpProcessor[8080][0] Starting ...
2011-04-04 14:34:56 HttpProcessor[8080][1] Starting ...
2011-04-04 14:34:56 HttpProcessor[8080][2] Starting ...
2011-04-04 14:34:56 HttpProcessor[8080][3] Starting ...
2011-04-04 14:34:56 HttpProcessor[8080][4] Starting ...

When something breaks, this log is somewhat helpful in that you can see what thread is broken. A more helpful log is Tomcat's access log (such as localhost_access_log.2011-04-04.txt), which appends the following line after I request the previous servlet above with

http://localhost:8080/examples/servlet/ErrorServlet:

127.0.0.1 - - [25/Dec/2011:14:23:53 -0800]
"GET /examples/servlet/ErrorServlet HTTP/1.1" 200 75

The log which is most interesting to us is the file localhost_examples_log.2011-04-04.txt. This is the one that is written to when you use the logging functionality in the servlet environment.

Writing Stuff into the Log File:

Now that we know what the log files are and the types of log files that get created, let us take a look at a sample program that is going to write out stuff into the log file.

Code:

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.util.Enumeration;
import java.sql.Timestamp;
import java.io.PrintWriter;
import java.io.IOException;

public class LoggingServlet extends HttpServlet
{

public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("< html >");
out.println("< head > < title >Servlet Exception Handling " +
"Example < / title > < / head >");
out.println("< body >");

String logMessage = getSbuf(request);
out.println(" We are Logging this request.");

ServletContext context = getServletContext();
context.log(logMessage);

out.println(logMessage);
out.println(" < / body > ");
out.println("< / html >");
}

public String getSbuf(HttpServletRequest request)
throws ServletException
{

// get generic servlet request properties
StringBuffer sbuf = new StringBuffer();
sbuf.append("Activity occurred at " + (new Timestamp(System.currentTimeMillis())) + '\n');
sbuf.append(" characterEncoding=" + request.getCharacterEncoding() + '\n');
sbuf.append(" contentLength=" + request.getContentLength() + '\n');
sbuf.append(" contentType=" + request.getContentType() + '\n');
sbuf.append("locale=" +request.getLocale() + '\n');

Enumeration names = request.getParameterNames();
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
sbuf.append(" parameter=" + name + "=");
String values[] = request.getParameterValues(name);
for (int i = 0; i < values.length; i++) { if (i > 0)
sbuf.append(", ");
sbuf.append(values[i]);
}
sbuf.append('\n');
}
sbuf.append(" protocol=" + request.getProtocol() + '\n');
sbuf.append(" remoteAddr=" + request.getRemoteAddr() + '\n');
sbuf.append(" remoteHost=" + request.getRemoteHost() + '\n');
sbuf.append(" scheme=" + request.getScheme() + '\n');
sbuf.append(" serverName=" + request.getServerName() + '\n');
sbuf.append(" serverPort=" + request.getServerPort() + '\n');
sbuf.append(" isSecure=" + request.isSecure() + '\n');

// Render the HTTP servlet request properties
if (request instanceof HttpServletRequest) {

sbuf.append("********************************");

HttpServletRequest reqObj = (HttpServletRequest) request;

sbuf.append(" contextPath=" + reqObj.getContextPath() + '\n');

Cookie cookies[] = reqObj.getCookies();

if (cookies == null)

cookies = new Cookie[0];

for (int i = 0; i < cookies.length; i++) {

sbuf.append(" cookie=" + cookies[i].getName() + "=" + cookies[i].getValue());
}

names = reqObj.getHeaderNames();

while (names.hasMoreElements()) {

String name = (String) names.nextElement();

String value = reqObj.getHeader(name);

sbuf.append(" header=" + name + "=" + value + '\n');

}

sbuf.append(" method=" + reqObj.getMethod() + '\n');

sbuf.append(" pathInfo=" + reqObj.getPathInfo() + '\n');

sbuf.append(" queryString=" + reqObj.getQueryString() + '\n');

sbuf.append(" remoteUser=" + reqObj.getRemoteUser() + '\n');

sbuf.append("requestedSessionId=" + reqObj.getRequestedSessionId());

sbuf.append(" requestURI=" + reqObj.getRequestURI() + '\n');

sbuf.append(" servletPath=" + reqObj.getServletPath() + '\n');

}

sbuf.append("*****************************" +'\n');


// return the information

return sbuf.toString();

}

}


The above code is just a wrapper on the Logger. It creates a string buffer of the request parameters and then prints them all into the log file using the ServletContext.log(String) method. You may not actually need all of this information but it's a good place to start. It is just an example to tell you how to write contents into the log. You can alter it in anyway to print out stuff into your log file for debugging your application effectively.


Contents of the Log File:

If you execute the above sample servlet, your log file will be loaded with a lot of information that may not make much sense from the debugging point of view. But, nonetheless, lets take a look at what got written into our log file localhost_examples_log.2011-012-04.txt:

2011-04-04 16:09:15 Activity occurred at 2011-04-04 16:09:15
characterEncoding=null
contentLength=-1
contentType=null
locale=en_US
protocol=HTTP/1.1
remoteAddr=127.0.0.1
remoteHost=127.0.0.1
scheme=http
serverName=localhost
serverPort=8080
isSecure=false
contextPath=/examples
header=accept=*/*
header=accept-language=en-us
header=accept-encoding=gzip, deflate
header=user-agent=Mozilla/4.0 (compatible;
MSIE 5.01; Windows 7)
header=host=localhost:8080
header=connection=Keep-Alive
method=GET
pathInfo=null
queryString=null
remoteUser=null
requestedSessionId=null
requestURI=/examples/servlet/LoggingServlet
servletPath=/servlet/LoggingServlet
*********************************************

2011-04-04 16:09:15 InvokerFilter(ApplicationFilterConfig
[name=Path Mapped Filter,
filterClass=filters.ExampleFilter]): 10 milliseconds

The contents of the log file were altered a bit to fit to the blogger page but this is almost everything you will see in your log file. I repeat, what you see in your log file might be slightly different than what you see above.

There is one more wrinkle to the log feature that you need to know for the exam. You can pass an exception object to the log method. If you add the following code to the preceding LoggingServlet code:

try
{
int zero = 0;
int problem = 10/zero;
} catch (Exception e)
{
log("Oops, You cannot divide by zero.", e);
throw new ServletException(e);
}

The logger will add the following to the log file (localhost_examples_log.2011-012-04.txt):
2011-04-04 22:00:09 org.apache.catalina.INVOKER.LoggingServlet:
Oops, You cannot divide by zero.
java.lang.ArithmeticException: / by zero
at LoggingServlet.service(LoggingServlet.java:38)
at javax.servlet.http.HttpServlet.service(...)
//33 more lines of error messages removed for space
at java.lang.Thread.run(Thread.java:536)

Exam Trivia:
GenericServlet has log method! The abstract GenericServlet class has a log method, log(String), which writes the specified message to a servlet log file, prefixed by the servlet's name.

Previous Chapter: Chapter 28 - The setStatus Method

Next Chapter: Quick Recap - Chapters 25 to 29

1 comment:

  1. How to send an error code (500) to access log file when we get null value in an if condition in Action class? Is anyone aware of this!

    ReplyDelete

© 2013 by www.inheritingjava.blogspot.com. All rights reserved. No part of this blog or its contents may be reproduced or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without prior written permission of the Author.

ShareThis

Google+ Followers

Followers