We have a jsp (2.2)/jstl(2.1) form that submits to a java servlet (3.0) on tomcat 7 server. Randomly, intermittently we will get a submission to the servlet with all the http request parameter values as null. Our form has some fields that are pre-populated so we expect at least those to be retrievable but they are null at the serlvet as well. Almost all of the form submissions we receive contain form data and are successfully processed. It's the once in every so many submissions that has the completely empty http request parameter set that I cannot figure out nor reproduce. There are no file uploads involved, the data is submitted via post. We validate client side and server side. I have searched high and low for reasons why the form data can be empty but have not had any success. Any thoughts?
1) no file uploads
2) all fields have 'name='
3) method is post
4) data is validated prior to submission
5) implement a filter for db entity management
partial jsp form:
<%# page contentType="text/html; charset=UTF-8" %>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%
response.setHeader("Cache-Control", "no-cache");//Forces caches to obtain a new copy of the page from the origin server
response.setHeader("Cache-Control", "no-store");//Directs caches not to store the page under any circumstance
response.setDateHeader("Expires", 0);//Causes the proxy cache to see the page as "stale"
response.setHeader("Pragma", "no-cache");//HTTP 1.0 backward enter code here
%>
<!DOCTYPE html>
<!--head/body stuff -->
<form id="app_form" name="app_form" action="process" method="post" novalidate="novalidate" accept-charset="ISO-8859-1">
<!-- general form fields using html/jstl -->
<button type="submit" id="submit_application" name="submit_application" class="submit application submitbtn" title="I'm finished and want to submit my completed application.">SUBMIT APPLICATION</button>
</form>
partial filter:
public class EntityManagerFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
log.debug("Initializing filter...");
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
try {
EntityManagerUtil.getEntityManager().getTransaction().begin();
chain.doFilter(request, response);
EntityManagerUtil.getEntityManager().getTransaction().commit();
} catch (Throwable ex) {
}
partial java servlet:
public class ProcessApplicationFormServlet extends BaseServlet {
private static Logger log = Logger.getLogger(ProcessApplicationFormServlet.class);
private static final long serialVersionUID = 1L;
Application_Domestic appdata = null;
Domestic_user currentUser = null;
String sessID = null;
String program = null;
String type = null;
#Override
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
try {
//values from form
appdata.setTitle(maxLength(req.getParameter("title"),25));
appdata.setFirst(maxLength(req.getParameter("first"),30));
appdata.setMiddle(maxLength(req.getParameter("middle"),30));
appdata.setLast(maxLength(req.getParameter("last"),57));
appdata.setSuffix(maxLength(req.getParameter("suffix"),25));
appdata.setEmail_Address(maxLength(req.getParameter("trueemail"),50));
etc...
process data
}
}
#Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
These are just the portions that deal with submission/http request. If there are other important coding considerations that I need to show, please let me know. Do keep in mind that only 1 - 2 percent of the form submissions come in with empty httpServletRequest data. This code has been tested and working. I just cannot seem to be able to reproduce the scenario when a user submits the form (it can not be submitted until all data as been validated) and it reaches the servlet with an empty data set where every parameter is null.
Related
I just started using JSP and Servlet, so I encountered a really basic problem.
I'm trying to make a request from JSP to servlet, where I set a parameter and then forward the answer from servlet back to the jsp.
Here is the code from my JSP:
<% String s = (String)request.getAttribute("name");
out.println(s);
%>
Here is my code from servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
try (PrintWriter out = response.getWriter()) {
request.setAttribute("name", new String("aa"));
this.getServletContext().getRequestDispatcher("/index.jsp").forward(request,response);
}
}
So in the end, the servlet has the value, but my jsp doesn't.
Here you have already declared a String type but you cast it as String also, this is redundant.
<% String s = (String)request.getAttribute("name");
out.println(s);
%>
Also, there's a difference between <%= %> and <% %>. If you want to output the variable into your jsp use the one with the equals (<%= %>). The second line of your scriptlet code would also generate an error. The code you write in your servlet doesn't just continue on the JSP, it's not how it works.
if you want to output the name attribute just do this:
<%= request.getAttribute("name") %>
However since 2010 scriptlets are discouraged (outdated technology).. We use EL and JSTL instead. You should be able to just output the variable like this:
${name}
In your Servlet all you need to do is this:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = "Jane"; //create a string
request.setAttribute("name", name); //set it to the request
RequestDispatcher rs = request.getRequestDispatcher("index.jsp"); //the page you want to send your value
rs.forward(request,response); //forward it
}
EDIT
You asked,
Is there a way to trigger the servlet let s say on a click of a button
or something like that?
Yes, there are multiple ways to do it and it really depends on how you want it setup. An easy way to trigger the servlet on a button click is like this. *(Assuming you have a servlet mapped onto /Testing):
<a href="/Testing">Trigger Servlet<a>
Another way could be with a form:
<form action="Testing" method="get">
<input type="hidden" name="someParameterName" value="you can send values like this">
<button type="submit">Do some magic</button>
</form>
There's also AJAX (which involves javascript). But this is fairly advanced and i don't recommend doing it until you are familiar with normal synchronous http behaviour.
Try without a writer, you don't want two writing contexts to a single response. You are also not using it:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("name", new String("aa"));
this.getServletContext().getRequestDispatcher("/index.jsp").forward(request,response);
}
I think you should call the request dispatcher method using request object. This is how you do it :
RequestDispatcher rs = request.getRequestDispatcher("index.jsp");
rs.forward(request,response);
I have a problem in java Servlet. Suppose i have two Servlet and two page(jsp). In index.jsp client enter your mobile number and submit form to sendSMS.do. sendSMS.do must be send SMS to mobile number.
servlet 1: index.do
page 1: index.jsp
servlet 2:sendSMS.do
page2 : success.jsp
in index.jsp :
<form action="/sendSMS.do" method="post">
<input type="text" name="mobile">
<input type="submit" value="sendSMS">
</form>
in sendSMS.do:
#WebServlet("/sendSMS.do")
public class RegisterController extends HttpServlet {
#Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String mobileNUmber=req.getParameter("mobile");
SendMessage sendMSG= new SendMessage();
//if there are network problems,sendSMS method my be take several minutes for return false
sendMSG.sendSMS(mobileNumber);
resp.sendRedirect("/success.jsp");
}
}
So sendSMS method return true if there is not any problem else return false after several minutes.If client in index.jsp page multiple click on submit button, there are several same request in server.
So How to detect this same request and is there any best practice for this issue?
I read Solving the Double Submission Issue but i want best practice when Servlet take long time to response.
Thanks in advice.
I have the following servlet:
#WebServlet(name = "Placeholder",urlPatterns = {"/foo"})
public class Placeholder extends HttpServlet {
public static int numbers=5;
HttpSession session;
public void doGet (HttpServletRequest _req, HttpServletResponse _res) throws ServletException, IOException {
/* Refresh session attributes */
session = _req.getSession();
session.setAttribute("wee","ok");
}
}
With the following JSP:
<%#page language="java" contentType="text/html"%>
<%#page import="java.util.*, java.io.*"%>
<%#page import="main.java.Placeholder.*" %>
<html>
<body>
<b><% out.println("wee, printing from java");%></b>
<% out.println("<br/>Your IP address is " + request.getRemoteAddr());
String value = (String) session.getAttribute("wee");
out.println(value);%>
</body>
</html>
I'm surely missing the point somewhere as attribute wee is resolved as null, first time I load the page. If I go to /foo I get empty an page, and after I get back and reload the root page of servlet, wee actually gets its value.
My goal here is to simply print variables from the servlet into the view, no routing needed. Not sure that urlPatterns are needed here, but it does not work for now without this little hack.
UPD. Ok, so I've figured out that whatever route I put in, I need to add some characters in browser, get back and reload the page.
So, the root is 0.0.0.0:8080/webapp
I need to access,say 0.0.0.0:8080/webapp/qwerty , get back to /webapp and refresh the page.
How do I get session instantiated by just going to /webapp?
Why don't I have 404 or 500 on accessing some random unexisting route /webapp/randomstuff?
First configure servlet as welcome file in web.xml. If web.xml not present than create it manually inside WEB-INF folder and put below content inside it.
<welcome-file-list>
<welcome-file>foo</welcome-file>
</welcome-file-list>
than in your servlet dispatch request to your jsp lets say your jsp name is index.jsp than your servlet code would be look like:
#WebServlet(name = "Placeholder",urlPatterns = {"/foo"})
public class Placeholder extends HttpServlet {
public static int numbers=5;
public void doGet (HttpServletRequest _req, HttpServletResponse _res) throws ServletException, IOException {
HttpSession session = _req.getSession();
session.setAttribute("wee","ok");
_res.sendRedirect("index.jsp");
}
}
Now run your servlet you will see output.
Hope this solve your problem!!!
I want to send data to controller action and I want to get value from action. But I cannot send value and I cannot convert value getting from controller to boolean, string etc..
contact =(List)response.sendRedirect("contact/login.action");
My contactController's login.action is below: (Also, I tried the boolean function)
#RequestMapping(value="/contact/login.action")
public #ResponseBody Map<String,? extends Object> login(#RequestParam Object data) throws Exception {
try{
List<Contact> contacts = contactService.login(data);
return getMap(contacts);
} catch (Exception e) {
}
return null;
}
My jsp codes are below:
<%#page import="com.loiane.web.ContactController"%>
<%#page import=" com.loiane.model.Contact"%>
<%#page import="java.util.List"%>
<%# page language="java" pageEncoding="UTF-8"%>
<%
String result;
List<Contact> contact;
String loginUsername = request.getParameter("loginUsername");
String loginPassword = request.getParameter("loginPassword");
contact =(List)response.sendRedirect("contact/login.action");
out.println(request.getAttribute("message"));
if ((null != loginUsername && loginUsername.length() > 0) && (null != loginPassword && loginPassword.length() > 0)) {
if (contact.size()>0)
result = "{success:true}";
else
result = "{success:false,errors:{reason:'Login failed.Try again'}}";
} else {
result = "{success:false,errors:{reason:'Login failed.Try again'}}";
}
%>
<%=result %>
Rather than doing response.sendRedirect to your servlet from JSP, your form should have the servlet as its action.
<form action='contact/login.action' method='post'>
Your servlet needs to implement doPost. Having just a method called login will not work.
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
Your JSP should be the login form that sends to the servlet (via HTML, when you click submit, not via JSP code) and the servlet should do ALL of the login stuff, including the request.getParameter calls.
Then if there is a login error, the servlet should response.sendRedirect to the login form jsp.
And please note that response.sendRedirect actually sends the browser to another page. Thus it will never return a list or any other datatype.
And you would be better off not using scriptlets in your JSP. You can do everything in the servlet. Just use the jsp like a HTML page.
I'm learning Java Web, but I have some problems and I need help.
I use a template.jsp in which I include header.jsp, footer.jsp, login.jsp (the left side of the template ) and ${param.content}.jsp. For each page named X.jsp I made another jsp with the following content, because I want each page to have the same layout:
<jsp:include page="template.jsp">
<jsp:param name="content" value="X"/>
<jsp:param name="title" value="Start navigate"/>`enter code here`
</jsp:include>
When I click on the Review link,for example, I want to be redirect to Review.jsp, but I have some problems.
In footer.jsp I have something like this:
(...)
< a href =" Review.jsp "> Review </a>
(...)
After login, I try to click Review, it sends me to the Review.jsp, but it shows me that I'm not logged in. I use Spring Framework, Tomcat 7, Eclipse, MySQL. When I log in, I create a cookie:
String timestamp = new Date().toString();
String sessionId = DigestUtils.md5Hex(timestamp);
db.addSession(sessionId, username, timestamp);
Cookie sid = new Cookie("sid", sessionId);
response.addCookie(sid);
For each method, I have something like this (I saw this in a tutorial):
#RequestMapping(value = "/writeReview", method = RequestMethod.GET)
public String nameMethod(#CookieValue("sid") String sid,...)
Using the sid, I can find out who's the user. I have a database with the user's account and some other tables. The problem is that when I click review or any other, it shows me that I'm not logged in. What can I do?
UPDATE:
I use JavaBean for user and login.jsp. The JSP that has the text box for the login, I have a GET method when I click on the button to log in.
#RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView createCookie(
#RequestParam("username") String username, #RequestParam("password") String password,
HttpServletRequest request, HttpServletResponse response) throws SQLException {
//code for creating the cookie here, after testing if the user is in my database
}
For each page, I send the sid and I have an attribute for the model, username:
public String methodName(#CookieValue(required = false) String sid, Model model) {
if (sid != null) {
User user = getUserBySid(sid);
model.addAttribute("user", user);
}
(..other data.)
return "nameJSP.jsp";
}
I check in each JSP if the username is not empty, so that's how I see if a user is logged in. The application goes well, it passes parameters if I don't click on the links from the header or footer. The problem is that I have to pass , let's say, a parameter from a JSP who's the actual content of the layout to the JSP referred by the footer and this JSP will be the next content of my layout. The layout only recognize content and title:
<title>${param.title}</title>
(I didn't paste all the code, I use a table <table>....)
<%# include file="header.jsp"%>
<%# include file="login.jsp"%>
<jsp:include page="${param.content}.jsp"/>
<%# include file="footer.jsp"%>
So how can I include a parameter in this JSP which will be received from another JSP? Also it will have to be accessed by layout.jsp and sent to the footer or the header?
<jsp:include page="layout.jsp">
<jsp:param name="content" value="X"/>
<jsp:param name="title" value="Start navigate"/>
</jsp:include>
To pass some parameter(s) to the included JSP:
<jsp:include page="somePage.jsp" >
<jsp:param name="param1" value="someValue" />
<jsp:param name="param2" value="anotherParam"/>
....
</jsp:include>
You are already doing it.
OK, the details of the question is not very clear, but I get the idea.
One of the solutions could be the following.
In your Login action, if the authentication was successful, create HttpSession and set an attribute for the authenticated User:
if (/* authentication was successfull */) {
request.getSession().setAttribute("loggedInUser", user);
...
}
And in the code where you are controlling if the user is logged in just check the presence of the appropriate HttpSession attribute:
HttpSession session = request.getSession(false);
if (session == null || session.getAttribute("loggedInUser") == null) {
// user is not logged in, do something about it
} else {
// user IS logged in, do something: set model or do whatever you need
}
Or in your JSP page you can check if the user is logged in using JSTL tags as showed by BalusC in the example here:
...
<c:if test="${not empty loggedInUser}">
<p>You're still logged in.</p>
</c:if>
<c:if test="${empty loggedInUser}">
<p>You're not logged in!</p>
</c:if>
...
Filters to the rescue
But usually, you check if the user is logged in to restrict access to some pages (so only authenticated user could access them). And you write some class that implements javax.servlet.Filter.
Here is an example of the LoginFilter from one of my projects:
package com.example.webapp.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* The purpose of this filter is to prevent users who are not logged in
* from accessing confidential website areas.
*/
public class LoginFilter implements Filter {
/**
* #see Filter#init(FilterConfig)
*/
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
/**
* #see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
#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);
if (session == null || session.getAttribute("loggedInUser") == null) {
response.sendRedirect(request.getContextPath() + "/login.jsp");
} else {
chain.doFilter(request, response);
}
}
/**
* #see Filter#destroy()
*/
#Override
public void destroy() {}
}
In this project I used plain servlets and JSP without Spring, but you'll get the idea.
And of course, you must configure web.xml to use this filter:
<?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_3_0.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
...
<filter>
<filter-name>Login Filter</filter-name>
<filter-class>com.example.webapp.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Login Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
</web-app>
Note:
If you are using a Web Container or Application Server that supports Servlet version 3.0 and higher then you can annotate your filter class with #WebFilter annotation in which case there is no need to configure the filter in the deployment descriptor (web.xml). See an example of using #WebFilter annotation and more Filter related information here.
Hope this will help you.
Or just use:
String username = request.getRemoteUser();