How to get a form parameter in servlet? request.getAttribute does not work - servlets

Is it possible to have the same servlet perform validation? It seems that one might have to utilize some sort of recursion here, but when I type in something in the e-mail box and click submit the e-mail parameter is still blank.
After I click submit, the URL changes to: http://localhost/servlet/EmailServlet?Email=test
The page shows Email: null and the text box, but I was expecting it to go through the validation function (i.e. not be null). Is it possible to achieve this type of recursive behavior?
public class EmailServlet extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String theForm =
"<FORM METHOD=\"GET\" ACTION=\"EmailServlet\">\n<INPUT TYPE=\"TEXT\" NAME=\"Email\"><P>\n"
+ "<INPUT TYPE=\"SUBMIT\">\n</FORM>";
String email = (String) request.getAttribute("Email");
// Bogus email validation...
if( email == null )
{
out.println("Email: " + email + "\n" + theForm);
}
else if(emailAddressNotBogous(email))
{
out.println("Thank you!");
}
else
{
out.println("“Invalid input. Please try again:\n" + theForm);
}
out.flush();
}
}
Update: as the accepted answer pointed out, there was an error in the code. Changing the getAttribute to getParameter fixes the "problem" :).
String email = (String) request.getAttributegetParameter("Email");

To get a form parameter in a servlet you use:
request.getParameter("Email");
And yes you can use the same servlet but it would be way easier to use two different servlets to do this.

you could have the form's method set to POST and then implement a doPost() method in your servlet. the doGet() will get called to display the form and the doPost() will get called to process the form submission.
alternatively you could have the doGet() method test for the presence of any parameters. if there aren't any then just display the form. if there are then process the submission...

Related

Issue with mvc:annotation-driven and #PathVariable

Not sure what I am doing wrong here but when I DO NOT define the mvc:annotation-driven in my servlet, the value returned from the #PathVariable is not getting displayed in my jsp page and when I do define the annotation-driven, all other links e.g. home gets broken and I get the The specified HTTP method is not allowed for the requested resource (Request method GET not supported).
#Controller("HealthCheckController")
#RequestMapping("/healthCheckSummary")
public class HealthCheckController {
private Log log = LogFactory.getLog(GolSimpleMappingExceptionResolver.class);
private HealthCheckService healthCheckService = null;
private IEappDataAccessFacade dataAccessFacade;
#RequestMapping(value = "/{username}/{password}", method = RequestMethod.GET)
public String getEappStatus(#PathVariable String username, #PathVariable String password, Model model){
String dbConnectivityStatus = getDatabaseConnectivityStatus() ? "online" : "offline";
if (!username.equals("lola") || !password.equals("123")) {
// wrong credentials were provided
log.error("The login credentials in the header are not valid." + username + password);
throw new RuntimeException( "Unable to continue, the login credentials in the header are not valid." + username + password);
}
model.addAttribute("healthCheckSummary", dbConnectivityStatus);
return "healthCheckSummary";
}
public HealthCheckService getHealthCheckService()
{
return healthCheckService;
}
public boolean getDatabaseConnectivityStatus() {
String result = “OK”;
if (result != null) {
return true;
}
return false;
}
}
Oh and in the application context we have defined the
<tx:annotation-driven />
JSP page
<%# page language="java"%>
Welcome ${username} - ${password}
Eapp is currently ${healthCheckSummary}
Two things:
You never put your username and password #PathVariables in the model. Your jsp page has no way of knowing that they even existed as you lose any reference to them after the code leaves getEappStatus. Add the following to your handler method:
model.addAttribute("username", username);
model.addAttribute("password", password);
and see if that works.
You might want to add <mvc:annotation-driven/> just to avoid some surprises when you use some spring-mvc annotations. This isn't strictly necessary, but might save you some head scratching when some #RequestBody doesn't work.

class variable set to null outside of a servlet

I wrote a simple servlet, in the doPost I got the user name and the password from a jspand authenticated the user by sending the password entered by the user to the data base(mysql). I got the data correctly and I am redirecting the user to another jsp page called welcome.jsp.
my question is , I wrote this method public String getUser(){return userNmae;}; I put it outside of the dopost method, however it is returning null. I have declared the variable userNmae as a class variable and when I debug , the variable contains a value in the dopost method , but it is null outside of the dopost method.why it is null outside of the dopost method?
I am calling getUser() method in the welcome.jsp page.
here is my code
public class UIclass extends HttpServlet {
public UIclass() { };
private String passWord = null;
private String userNmae = null;
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("userName");
String password = request.getParameter("password");
Connection connection = null;
try {
connection = Connections.getConnection();
java.sql.PreparedStatement statement = connection.prepareStatement("SELECT PASSWORD,USERNAME FROM LOGIN where username =?");
statement.setString(1, name);
ResultSet resultset = statement.executeQuery();
while (resultset.next()) {
passWord = resultset.getString("PASSWORD");
userNmae = resultset.getString("USERNAME");
}
} catch (Exception e) {
// TODO: handle exception
} finally {
if (connection != null)
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
};
}
if (passWord.equalsIgnoreCase(password)) {
RequestDispatcher rd = request.getRequestDispatcher("welcome.jsp");
rd.forward(request, response);
}
}
public String getUser() {
return userNmae;
}
}
I'll answer by giving you a simpler example of what your code is actually doing:
Bottle bottle1 = new Bottle();
bottle1.setMessage("Hi there");
Bottle bottle2 = new Bottle();
System.out.println(bottle2.getMessage());
What would you expect this program to display? I would expect null, because you set a message on bottle1, and read the message from bottle2. These are two different bottles. When you put a message in a bottle, the message is in that bottle, not in the other bottles.
Your code does the same thing.
The servlet container creates an instance (unique) of UIclass. This is equivalent to creating the first bottle in my example.
The servlet is invoked when you send an HTTP request. It sets the user attribute in the servlet. This is equivalent to bottle1.setMessage("Hi there") in my example.
The container executes your JSP, which contains the code
<jsp:useBean id="uiclass" class="com.servlet.UIclass" scope="request">
This creates a new UIClass instance. It is equivalent to creating the second bottle in my example.
The JSP calls uiclass.getUser(). This is equivalent to getting the message from the second bottle in my example.
There are many, many things wrong in your code:
You shouldn't use scriptlets, and jsp:useBean tags
You should never create instances of servlets by yourself. A servlet is meant to be instanciated and called by the container.
You should realize that a unique servlet instance is called to serve, concurrently, all the requests of all the users to this servlet URL. Storing user-specific data in servlet attributes is thus really wrong
You probably want the user name to be available for all the subsequent requests of this user. That's what the HTTP session is for. You should store the user as an attribute of the HTTP session: request.getSession().setAttribute("userName", userName)
The JSP should use the JSP EL and the JSTL to access beans stored in the request or the session by the servlet:
<c:out value="${userName}"/>

How do I extract the username and password out of a URL in a servlet filter?

I've created a BasicAuthFilter and it has this signature:
#Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException
This is working if someone calls the filter with an Authorization header set the right way. But, if someone on chrome or firefox visits the url like this:
http://username:password#localhost:8888
The browsers are not populating the Authorization header with that information (which surprised me). I looked at the information sent by chrome and the username and password are in the request URL but nowhere else.
I can't figure out how to extract that information from the URL. I've tried a lot of getters on the HttpServletRequest, but haven't found anything that gives me the username and password.
NOTE: Yes, I know this is insecure, it's just really convenient to use when you're trying to test your system.
URL url = new URL(custom_url);
String userInfo = url.getUserInfo();
String[] userInfoArray = userInfo.split(":");
System.out.println("username"+userInfoArray[0]);
System.out.println("password"+userInfoArray[1]);
My coworker found this thread that implies this isn't possible in modern browsers. They refuse to send the username:password part of a url over the wire for security reasons.
I'll add something to this answer
If the password contains the character :, you must specify a limit on your split.
So:
String[] userInfoArray = userInfo.split(":");
Becomes:
String[] userInfoArray = userInfo.split(":", 2);
2 means the pattern : is applied only one time (so the resulting length array is at maximum 2)
For passwords with '#', e.g. "http://user:p#ssw0rd#private.uri.org/some/service":
final String authority = uri.getAuthority();
if (authority != null) {
final String[] userInfo = authority.split(":", 2);
if (userInfo.length > 1) {
this.username = userInfo[0];
int passDelim = userInfo[1].lastIndexOf('#');
if (passDelim != -1) {
this.password = userInfo[1].substring(0, passDelim);
}
}
}
Note that in this case trying to use getUserInfo() won't help since userInfo of the URI is null.

Servlet: proper way to redirect to index versus show view in doGet() method

Given this doGet implementation:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (request.getParameterMap().isEmpty()) {
// DAO initialized in init() method
Collection<User> users = resource.getUsers();
if (users != null){
HttpSession session = request.getSession();
session.setAttribute("users", users);
}
request.getRequestDispatcher("/WEB-INF/users/index.jsp").forward(request, response);
}
else {
String name = request.getParameter("name");
// DAO initialized in init() method
User user = resource.getUser(name);
if (user == null){
request.setAttribute("message", "Unknown user: " + name);
request.getRequestDispatcher("/WEB-INF/errors/404.jsp").forward(request, response);
}
else {
HttpSession session = request.getSession();
session.setAttribute("user", user);
request.getRequestDispatcher("/WEB-INF/users/show.jsp").forward(request, response);
}
}
}
Questions:
Is request.getParameterMap().isEmpty() the preferred way to test for the presence of parameters?
Is there a way to infer the views' location (/WEB-INF/users/) from the either the Servlet's context or an annotation?
Is request.getParameterMap().isEmpty() the preferred way to test for the presence of parameters?
Yes, it is. But this is not the right solution for your particular case. Your code will fail if the enduser supplied an arbitrary parameter with other name than name, causing the parameter map to be not empty and thus enter the block which expects the name parameter. You should really explicitly check the request parameter name itself.
String name = request.getParameter("name");
if (name == null) {
Collection<User> users = resource.getUsers();
// ...
}
else {
User user = resource.getUser(name);
// ...
}
Is there a way to infer the views' location (/WEB-INF/users/) from the either the Servlet's context or an annotation?
Use a MVC framework (recommended) or homebrew one (not recommended, unless 100% internal/private/hobby and thus for pure learning purposes).

Error passing parameters into a servlet

I want to implement a servlet to get the parameters from the browser and insert into db using http post not http get.
the servlet will recieve params from a url such as this http://localhost:8080/NewServlet?firstname=me&middlename=you&lastName=secret&location=here , and insert into the db, but Its like I cant do it properly.
here is the piece of code am trying to run
public class NewServlet extends HttpServlet {
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String firstName = request.getParameter("firstname");
String middleName = request.getParameter("middlename");
String lastName = request.getParameter("lastname");
String location = request.getParameter("location");
String result;
java.sql.Connection connDB = null;
try {
Class.forName("org.postgresql.Driver");
} catch (ClassNotFoundException ex) {
Logger.getLogger(DBConnection.class.getName()).log(Level.SEVERE, null, ex);
}
try {
connDB = DriverManager.getConnection("jdbc:postgresql://" + "localhost" + ":" + 5432 + "/" + "mydb", "username", "secret");
connDB.setAutoCommit(false);
System.out.println("Connection established : [" + connDB.toString() + "]");
java.sql.Statement bankStmt = connDB.createStatement();
java.sql.Statement stt = connDB.createStatement();
bankStmt.execute("INSERT INTO full_names(firstname, secondname, lastname) VALUES('"+firstName+"', '"+middleName+"', '"+lastName+"' )");
java.sql.Statement bnk =connDB.createStatement();
bnk.execute("INSERT INTO employee_details(location) VALUES('"+location+"')");
}
connDB.commit();
} catch (SQLException ex) {
ex.printStackTrace();
try {
connDB.rollback();
} catch (SQLException ex1) {
ex1.printStackTrace();
Logger.getLogger(DBConnection.class.getName()).log(Level.SEVERE, null, ex1);
}
Logger.getLogger(DBConnection.class.getName()).log(Level.SEVERE, null, ex);
}
out.println("<b><font color='blue'>Your FirstName is :</font></b>"
+ "<b>"+ firstName +"</b>" + "<br>");
out.println("<b><font color='blue'>Your Middle Name is :</font></b>"
+ "<b>"+ middleName +"</b>" + "<br>");
out.println("<b><font color='blue'>Your Last Name is :</font></b>"
+ "<b>"+ lastName +"</b>");
}
}
When I try to run the code using the url http://localhost:8080/NewServlet?firstname=me&middlename=you&lastName=secret&location=here
I get the following error:
HTTP Status 405 - HTTP method GET is not supported by this URL
type Status report
message HTTP method GET is not supported by this URL
description The specified HTTP method is not allowed for the requested resource (HTTP method GET is not supported by this URL).
You have only defined the do Post() method in your servlet. But when you are accessing using http://localhost:8080/NewServlet?firstname=me&middlename=you&lastName=secret&location=here , the doGet() is called which you have not defined. Just copy and paste the code in the doPost() method inside a doGet() in the same servlet.
Like this :
public void doGet{
//your code
}
HTTP Status 405 - HTTP method GET is not supported by this URL
Well, this is already the whole answer at its own. You're sending a GET request, but your servlet implementation doesn't support it. According to the code you wrote, it only supports POST requests. You don't have a doGet() implementation anywhere, but only doPost().
I'm not sure what's the functional requirement is and why this error is unclear to you, but to get your code to run, you should either send a POST request instead, or to rename doPost method to doGet in your servlet.
Unrelated to the concrete problem, your code has other problems as well, among others SQL injection holes, DB resource leaking and mingling the view in the controller. To learn servlets properly, you may want to start at our servlets wiki page.

Resources