How do I write the Java logger Servlet? - java

I want to do some log in my system, like user action,
and I know in the servelet I can get the request with all the session,parameter..etc
So I want to write the Servlet
public class UserActionCheck extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
Map map = request.getParameterMap();
Set keSet = map.entrySet();
for (Iterator itr = keSet.iterator(); itr.hasNext(); ) {
Map.Entry me = (Map.Entry) itr.next();
Object ok = me.getKey();
Object ov = me.getValue();
String[] value = new String[1];
if (ov instanceof String[]) {
value = (String[]) ov;
} else {
value[0] = ov.toString();
}
for (int k = 0; k < value.length; k++) {
System.out.println(ok + "=" + value[k]);
}
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//HttpSession session = request.getSession();
}
}
then I can see the parameter output in the tomcat console..but I get the blank page..
It seems the page is stop after doGet method..
so how should I make it continue?
use that RequestDispatcher?
also how to handle in the doPost?

For your purpose, the best way would be to use a Filter.
Example :
#WebFilter(filterName = "monitoringFilter", urlPatterns = { "/*" })
public class MonitoringFilter implements Filter
{
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
{
// Right here do your stuff pretty much like in a servlet
request // ... get information you need
// Process request as normal
chain.doFilter(request,response);
}
#Override
public void init(FilterConfig config) throws ServletException
{
}
#Override
public void destroy()
{
}
}
More info :
Filter

You should use log4j and FileAppender to implement logging in your application.
Something like this :::
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
class A{
static Log log = LogFactory.getLog(A.class);
void methodA(){
try{
log.info("I am inside A");
} catch(Exception e) {
log.error("error" , e);
}
}
}

Related

Unit test for Filter class

I am trying to write unit tests for the following Filter class, but I am not sure how it can be done. I am working on a Spring project and trying to fix a vulnerability, that is why I am using this class.
public class HSTSFilter implements Filter {
private static final String HEADER_NAME = "Strict-Transport-Security";
private static final String MAX_AGE_DIRECTIVE = "max-age=%s";
private static final String INCLUDE_SUB_DOMAINS_DIRECTIVE = "includeSubDomains";
private static final Logger logger = LoggerFactory.getLogger(HSTSFilter.class);
private int maxAgeSeconds = 0;
private boolean includeSubDomains = false;
private String directives;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
logger.info("request.isSecure() :: {}" , request.isSecure());
if (request.isSecure() && response instanceof HttpServletResponse) {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader(HEADER_NAME, this.directives);
}
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
maxAgeSeconds = Integer.parseInt(filterConfig.getInitParameter("maxAgeSeconds"));
includeSubDomains = "true".equals(filterConfig.getInitParameter("includeSubDomains"));
if (this.maxAgeSeconds <= 0) {
throw new ServletException("Invalid maxAgeSeconds value :: " + maxAgeSeconds);
}
this.directives = String.format(MAX_AGE_DIRECTIVE, this.maxAgeSeconds);
if (this.includeSubDomains) {
this.directives += (" ; " + INCLUDE_SUB_DOMAINS_DIRECTIVE);
}
}
#Override
public void destroy() {
}
}
In your unit test, create a mock object of ServletRequest, ServletResponse, and FilterChain.
Call doFilter with these mock objects.

i am working on servlets, having only one deGet and DoPost method. i wrote one new method in that. . how can i access that new method directly?

I have call this method under doGet. Please help me to get out of this.
This is my own method and I wanted to call this.
public void doYourThingHere(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
String[] checkedQues = request.getParameterValues("ttom");
List<String> checkedQuesList = Arrays.asList(checkedQues);
Map<String, String> preferences = new LinkedHashMap<String, String>();
if (session.getAttribute("username") != null) {
List<Question> questionsList = (List<Question>) session
.getAttribute("restaurantQuestionList");
List<Question> questionsListTemp1 = new ArrayList<>();
for (int i = 2; i < 4; i++) {
questionsListTemp1.add(questionsList.get(i));
}
session.setAttribute("tomtomRestaurantQuestionList1",
questionsListTemp1);
for (Question question : questionsList) {
String questionId = String.valueOf(question.getId());
if (checkedQuesList.contains(questionId)) {
String answerId = request.getParameter(questionId);
// PreferenceDAO.storePreferences(questionId, answerId,
// CATEGORY);
preferences.put(questionId, answerId);
System.out.println("queid : " + questionId + "answerid : "
+ answerId);
}
}
String username = (String) session.getAttribute("username");
PreferencesProcessor.process(preferences, username);
RequestDispatcher requestdp = request
.getRequestDispatcher("WEB-INF/jsp/table.jsp");
requestdp.forward(request, response);
} else {
RequestDispatcher requestdp = request
.getRequestDispatcher("WEB-INF/jsp/login.jsp");
requestdp.forward(request, response);
}
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
}
/**
* #see HttpServlet doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
Servlets map HTTP request headers to predefined methods, such as doGet(), doPost(), and some others.
https://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpServlet.html
Since your method modifies data, you should call it with POST.
Most simple way is to forward your doPost() to this method:
public void doPost(HttpServletRequest request, HttpServletResponse response) {
doYourThingHere(request, response);
}
What will happen usually is that you'll add some routing logic to your doPost like that:
public void doPost(...) {
String action = request.getParameter("action");
switch (action) {
case "doSomething":
doSomething(request, response);
break;
case "somethingElse":
doSomethingElse(request, response);
break;
...
}
}

Java Servlet parse request body multithread

I've implemented a asynchronous Servlet, which needs to parse the body of request and store the parsed result in cache. Should I implement the parseBody() function in Servlet or implement a new class, which will do the parsing? What is the best practice?
Here is my current code snippet:
public class DocFeedServlet extends FeedServlet {
private static final Logger LOGGER = LoggerFactory.getLogger(DocFeedServlet.class);
private static final ObjectMapper OBJECTMAPPER = new ObjectMapper();
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
final AsyncContext asyncContext = req.startAsync();
asyncContext.start(new Runnable() {
#Override
public void run() {
String bodyStr = getBody(req);
if (bodyStr.isEmpty()) {
resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
asyncContext.complete();
return;
}
int ignoreTime = Integer.parseInt(req.getParameter(Constant.PARAM_IGNORE_TIME));
List<MockDocCacheKeyVal> mockDocCacheKeyVals = new ArrayList<>();
List<String> docUpdateFields = new ArrayList<>();
List<List<String>> docKeepFields = new ArrayList<List<String>>();
List<String> uuidsToRemove = new ArrayList<>();
int parseRet = parseBody(bodyStr, mockDocCacheKeyVals, docUpdateFields, docKeepFields, uuidsToRemove, ignoreTime);
if (parseRet != 0) {
resp.setStatus(HttpServletResponse.SC_OK);
} else {
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
asyncContext.complete();
}
});
}
protected int parseBody(String body, List<MockDocCacheKeyVal> mockDocCacheKeyVals, List<String> docUpdateFields, List<List<String>> docKeepFields, List<String> uuidsToRemove, int ignoreTime) {
try {
ObjectReader reader = OBJECTMAPPER.reader(new TypeReference<List<Document>>() { });
List<Document> documents = reader.readValue(body);
for (Document doc : documents) {
if (doc.getAction() != null && doc.getAction().equalsIgnoreCase(Constant.DOC_FEED_ACTION_DELETE)) {
if (doc.getUuid() != null) {
uuidsToRemove.add(doc.getUuid());
}
continue;
}
if (doc.getA() != null) {
} else if (doc.getB() != null) {
} else {
DocumentUtils.pruneWeightSet(doc.getC(), cPruneSize);
DocumentUtils.pruneWeightSet(doc.getD(), dPruneSize);
DocumentUtils.pruneWeightSet(doc.getE(), ePruneSize);
}
}
return documents.size();
} catch (Exception e) {
LOGGER.error(e.getMessage());
}
return 0;
}
}
Thanks.
Asynchronous Request Body read is accomplished with the HttpServletRequest.getInputStream().setReadListener(ReadListener) concepts introduced in Servlet 3.1
You will only read based on events from your ReadListener, and you will only read enough to not block. (so no reading multi-megabyte buffers!).
This API is what you are looking for, however there be land mines here, so be sure you fully understand the API before you finish it.

#WebFilter exclude url-pattern

I use a filter to check URL patterns for the logged in user.
But I have many URL patterns I need to filter.
{ "/table/*", "/user/*", "/contact/*", "/run/*", "/conf/*", ..., ..., ...}
It's becoming unmaintainable. It will be simpler just to exclude:
{ "/", "/login", "/logout", "/register" }
How can I achieve this?
#WebFilter(urlPatterns = { "/table/*","/user/*", "/contact/*","/run/*","/conf/*"})
public class SessionTimeoutRedirect implements Filter {
protected final Logger logger = LoggerFactory.getLogger("SessionFilter");
#Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (request.getSession().getAttribute("Id") != null) {
chain.doFilter(req, res);
} else {
logger.debug("session is null:"+request.getRequestURL());
response.sendRedirect(request.getContextPath()+"/login");
}
}
#Override
public void init(FilterConfig arg0) throws ServletException {
}
#Override
public void destroy() {
}
}
The servlet API doesn't support an "exclude" URL pattern.
Your best bet is to just map on /* and compare the HttpServletRequest#getRequestURI() against the set of allowed paths.
#WebFilter("/*")
public class LoginFilter implements Filter {
private static final Set<String> ALLOWED_PATHS = Collections.unmodifiableSet(new HashSet<>(
Arrays.asList("", "/login", "/logout", "/register")));
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
String path = request.getRequestURI().substring(request.getContextPath().length()).replaceAll("[/]+$", "");
boolean loggedIn = (session != null && session.getAttribute("Id") != null);
boolean allowedPath = ALLOWED_PATHS.contains(path);
if (loggedIn || allowedPath) {
chain.doFilter(req, res);
}
else {
response.sendRedirect(request.getContextPath() + "/login");
}
}
// ...
}
You can use initParam to have some excluded patterns and implement your logic. This is basically the same as BalusC's answer except by using initParam it can be written in the web.xml if you want/need to.
Below I am ignoring some binary (jpeg jpg png pdf) extensions:
#WebFilter(urlPatterns = { "/*" },
initParams = { #WebInitParam(name = "excludedExt", value = "jpeg jpg png pdf") }
)
public class GzipFilter implements Filter {
private static final Set<String> excluded;
#Override
public void init(FilterConfig filterConfig) throws ServletException {
String excludedString = filterConfig.getInitParameter("excludedExt");
if (excludedString != null) {
excluded = Collections.unmodifiableSet(
new HashSet<>(Arrays.asList(excludedString.split(" ", 0))));
} else {
excluded = Collections.<String>emptySet();
}
}
boolean isExcluded(HttpServletRequest request) {
String path = request.getRequestURI();
String extension = path.substring(path.indexOf('.', path.lastIndexOf('/')) + 1).toLowerCase();
return excluded.contains(extension);
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.print("GzipFilter");
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
if (isExcluded(httpRequest)) {
chain.doFilter(request, response);
return;
}
// Do your stuff here
}
}

Record Request and Response with Servlet Filter

i'm study to devolop a servlet/filter to use in a web application, the filter have to record every request on the site by all user of the web application.
in my head the filter have to work in this way
filter -> request -> save request -> do.chain
public class ServletFilter implements Filter {
private Application fApp;
StringWriter ResponseRECORDER;
StringWriter RequestRECORDER;
#Override
public void init(FilterConfig config) throws ServletException {
fApp = (Application)config.getServletContext().getAttribute("application");
}
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
chain.doFilter(request,response);
// Ignore non-http requests.
if (!(request instanceof HttpServletRequest))
{
chain.doFilter(request,response);
return;
}
((HttpServletRequest)request).getSession();
// Write the request out to the recording file.
recordReqResHTTP((HttpServletRequest) request,
(HttpServletResponse) response);
StringBuilder Fixed = new StringBuilder();
Fixed.append("[Message]");
Fixed.append("[time]");
Fixed.append(System.currentTimeMillis());
Fixed.append("[/time]");
Fixed.append("[Request]");
Fixed.append(RequestRECORDER);
Fixed.append("[/Request]");
Fixed.append("[Response]");
Fixed.append(ResponseRECORDER);
Fixed.append("[/Response]");
Fixed.append("[/Message]");
MessagingService s = (MessagingService)fApp
.getService("it.interprise.core.workflow.MessagingService");
try {
s.send("recorder", Fixed.toString());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void destroy() {
}
public void recordReqResHTTP(HttpServletRequest request,
HttpServletResponse response)
{
//HttpSession session = request.getSession();
//costruisco una stringa per la raccolta dati
StringWriter ResponseRECORDER = new StringWriter();
StringWriter RequestRECORDER = new StringWriter();
try
{
//Registro la Request
PrintWriter out = new PrintWriter(RequestRECORDER);
out.println("<request>");
out.print("<uri>");
out.print(request.getRequestURI());
out.println("</uri>");
Enumeration e = request.getParameterNames();
while (e.hasMoreElements())
{
String paramName = (String) e.nextElement();
String[] values = request.getParameterValues(paramName);
for (int i=0; i < values.length; i++)
{
out.print("<param><name>");
out.print(paramName);
out.print("</name><value>");
out.print(values[i]);
out.println("</value></param>");
}
}
out.println("</request>");
out.close();
//Registro la Response
PrintWriter res = new PrintWriter(ResponseRECORDER);
res.println("<request>");
res.print("<uri>");
res.print(request.getRequestURI());
res.println("</uri>");
Enumeration f = request.getParameterNames();
while (f.hasMoreElements())
{
String paramName = (String) f.nextElement();
String[] values = request.getParameterValues(paramName);
for (int i=0; i < values.length; i++)
{
res.print("<param><name>");
res.print(paramName);
res.print("</name><value>");
res.print(values[i]);
res.println("</value></param>");
}
}
out.println("</request>");
out.close();
}
catch (Exception exc)
{
}
}
}
and the same for the response, have you any idea how i could solve the problem?
With this filter the web application stop response...
thank you
The first thing you should do is to log the Exception at the bottom of your example, at least. Maybe there is an Exception raised that cannot be identified by inspecting the code.
A few lines before you close the PrintWriter twice, which could lead to IOException.
Second: You declare instance variables ResponseRECORDER and RequestRECORDER, but later you declare two local variables with same name. Remove the instance variables - the filter must be implemented thread safe.
Once done, I'll guess we will see a hidden NullPointer.

Categories

Resources