I am trying to implement simple login system. I have a JSP with form where user enters username and password, and then servlet that is reading those parameters. You'll understand from servlet code:
User user = userDao.findUserWithUsernameAndPassword(username, password);
// user found
if (user!=null) {
session = request.getSession(true);
session.setAttribute("user", user);
loginMessage = "Welcome";
request.setAttribute("loginMessage", loginMessage);
RequestDispatcher dispatcher = request.getRequestDispatcher("login.jsp");
dispatcher.forward(request, response);
} else // username and password not matching
{
loginMessage = "Wrong username or password! Please try again.";
request.setAttribute("loginMessage", loginMessage);
RequestDispatcher dispatcher = request.getRequestDispatcher("login.jsp");
dispatcher.forward(request, response);
}
This works if I enter valid username and password, but if not I am getting next exception:
javax.persistence.NoResultException: Query "SELECT u FROM User u WHERE
u.username like :username AND u.password LIKE :password" selected no
result, but expected unique result.
What is the proper way of handling this situation? I would like for wrong username and password parameters to display appropriate message (forwarding in 'loginMessage' variable).
[added]This is the code in UserDAOBean:
#Stateless
#Local(UserDAOLocal.class)
#TransactionManagement(TransactionManagementType.CONTAINER)
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public class UserDAOBean extends GenericDAOBean<User, Integer> implements UserDAOLocal{
public User findUserWithUsernameAndPassword(String username, String password)
{
Query q = em.createNamedQuery("findUserWithUsernameAndPassword");
q.setParameter("username", username);
q.setParameter("password", password);
User result = (User) q.getSingleResult();
return result;
}
}
And named query in entity User is:
#NamedQuery(name = "findUserWithUsernameAndPassword", query = "SELECT
u FROM User u WHERE u.username like :username AND u.password LIKE
:password")
This Exception is throw by the entity manager when you call the method getSingleResult and there is no resul, so you need to change the findUserWithUsernameAndPassword method.
If you are searching the entity by it's Primary Key you could use the em.find, it method returns null if there is no result.
Another option is not use the getSingleResult() and use the getResultList() it will not throw the NoResultException if there is no result, you need to check if the list is empty if there is no result.
If you want to maintain your method you must to catch the Exception and implements the logic where there is no result.
Related
Login class:
public static String n=request.getParameter("userName");
public static String p=request.getParameter("userPass");
Servlet class:
PreparedStatement ps1= con.prepareStatement("insert into "+Login.n+" values(?,?,?)");
In login class im using a html page where it shows name and password..so when ever user login it validates his pass by Loginps class and returns to login servlet where i placed html form are dress ,dou,pattern fileds ..here action given to servlet class where servlet class request parameters dress ,dou, pattern ...in preparedstatement("sql query have to insert into"+here i want string n value +"values (?,?,?)")
I want to use string n from Login class so that I can make a dynamic tables when user created his account.
Any help appreciated.
Login class:
String n=request.getParameter("userName");
String p=request.getParameter("userPass");
if("YOURSERVLETCLASS".checkUser(n, p))
{
// anything you like for example forwarding to welcome page
RequestDispatcher rs = request.getRequestDispatcher("welcome.html");
rs.forward(request, response);
}else {
// if not correct back to index page
out.println("Username or Password incorrect");
RequestDispatcher rs = request.getRequestDispatcher("index.html");
rs.include(request, response);
}
Servlet class:
public static boolean checkUser(String n,String p){
boolean status=false;
try{
// set your connection here Connection con = .....
PreparedStatement ps=con.prepareStatement(
"INSERT INTO userdetails(username,password)"+"VALUES(?,?)");
ps.setString(1,n);
ps.setString(2,p);
ResultSet rs=ps.executeQuery();
status=rs.next();
}catch(Exception e){System.out.println(e);}
return status;
}
[error] play - Cannot invoke the action, eventually got an error: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
MODEL.USER
When I am working on Play 2.3.x, I want to use JPA to implement login function. Then I got this error. It seems the authenticate has successfully receive the args from controller.
public static User authenticate(String email, String password){
String hql = "from User u where u.email= ? and u.password= ?";
Query query = JPA.em().createQuery(hql);
query.setParameter(0, email);
query.setParameter(1, password);
User user = (User) query.getResultList();
return user;
}
Controller.User
public static class Login{
public String email;
public String password;
public String validate(){
LOG.info("validating user");
User user = User.authenticate(email, password);
if(user == null){
return "Invalid email or password";
}
LOG.info("validated Customer:"+user.toString());
return null;
}
}
I have an issue in Spring (or Hibernate) with checking for data existence in DB till updating. I want to update user’s profile and I can change Name, Password and Email fields. Name and Password hasn’t to be unique but Email has to. I show the form with fields filled by user’s old data, when I enter new data not changing Email it, of course, shows that it is already exists. If delete this check I’ll have two same emails in base. How can I set same data for certain user?
My method for update with checking email.
public void updateUser(User user) throws NotUniqueEmailException {
if (user == null) {
throw new NullPointerException();
}
if (user.getUserId() < 1) {
throw new IllegalArgumentException();
}
if (user.getEmail() == null || user.getEmail().intern().equals("")) {
throw new IllegalArgumentException();
}
if (getUserByEmail(user.getEmail()).getEmail() != null) {
throw new NotUniqueEmailException("The email of user not unique! " + user.getEmail());
}
currentSession().update(user);
// currentSession().saveOrUpdate(user);
}
And I’ve one more method for checking for existence.
public boolean isEmailExists(User user) {
Session session = HibernateUtil.openSession();
boolean result = true;
Query query = session.createQuery("SELECT u FROM User u WHERE u.email=?");
query.setString(0, user.getEmail());
User u = (User) query.uniqueResult();
if (u == null) {
result = false;
}
return result;
}
Update controller
#RequestMapping(value = "/edit/{userId}", method = RequestMethod.GET)
public String updateView(#PathVariable("userId")Integer userId,
UserForm userForm,
HttpSession session,
ModelMap model){
User user=userService.getUserById(userId);
userForm.setUser(user);
model.addAttribute("userForm",userForm);
return"profileupdate";
}
#RequestMapping(value = "/edit.do/{userId}", method = RequestMethod.POST)
public String updateUserProcess(#ModelAttribute(value = "userForm")
UserForm userForm,
#PathVariable("userId")Integer userId,
BindingResult result,Model model,
HttpSession session,
HttpServletRequest request){
User user=userService.getUserById(userId);
session.getAttribute("userForm");
model.addAttribute("userForm",userForm);
updateValidator.validate(userForm,result);
if(result.hasErrors()){
logger.error("Validation error");
return"profileupdate";
}
return updatingUser(userForm,user,model,request);
}
private void fillForm(UserForm userForm,User user){
userForm.setUserId(user.getUserId());
userForm.setLogin(user.getLogin());
userForm.setRegDate(user.getRegDate());
userForm.setComputers(userService.getAllUsersComputers(user.getLogin()));
userForm.setRole(roleService.findByName(user.getRole().getRoleName()));
}
private String updatingUser(UserForm userForm,User user,Model model,HttpServletRequest request){
fillForm(userForm,user);
user=userForm.getUser();
try{
userService.updateUser(user);
logger.info("User updated!");
request.getSession().setAttribute("user",user);
return"newprofile";
}catch(NotUniqueEmailException e){
logger.error("Can't update user - not unique email!!",e);
model.addAttribute("errorMsg","Email is already in use!");
return"profileupdate";
}
}
EDIT : add elements for Hibernate persistence methods
If you want Hibernate to automagically know that it should do an an update and not an insert, the primary key has to be set in user. As you say the fields have been modified, I suppose user fields come from a form input. You have two ways to keep the id :
store it in a hidden input field in your form - on submit, spring will populate it
have it in a path variable, get it in your controller and populate it yourself (#RequestMapping(/.../{id}) public String method(#PathVariable("id") user_id, ...))
But it may not be enough and you could have a merge vs update vs saveOrUpdate problem. This other post from SO could give indications Hibernate : Downside of merge over update
compare the args user.getId() with u.getId()
I'm trying to register a user and allow him to login with userName and Password. My dataStore entity "Racer" contains Name, UserName, Password, Age, BikeModel, City. Key is generated by the application.
I want to validate user. I used query with addFilter() to get the entire details of a particular user. I am struck with getting a particular property of a particular user from the entity in dataStore, say, Password and UserName of a particular user from "Racer".
Over the web, whichever example i got, it was using PersistentManager. I don't want to use it. I don't find any query to fetch details other than Filter and Sort. Please suggest me how to proceed.
Servlet:
public class StoreInDataStore extends HttpServlet {
#SuppressWarnings("deprecation")
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException, ServletException {
//Getting SignUp form values
String name=req.getParameter("name1");
String uname=req.getParameter("uname1");
String pswd=req.getParameter("pswd1");
String age=req.getParameter("age");
String city=req.getParameter("city");
String bike=req.getParameter("bike");
//Getting login form values
String lname=req.getParameter("name");
String lpswd=req.getParameter("pswd");
//Creating dataStore
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
//Creating entity
Entity e=new Entity("Racer");
//Entering details in racer
e.setProperty("Name", name);
e.setProperty("UserName", uname);
e.setProperty("Password", pswd);
e.setProperty("Age", age);
e.setProperty("City", city);
e.setProperty("Bike Model", bike);
//Storing in DataStore
ds.put(e);
//Getting entire details
Query q=new Query("Racer");
q.setFilter(FilterOperator.EQUAL.of("UserName", uname));/* UserName takes only the currently entered value(uname). Doesnot fetch from dataStore */
PreparedQuery pq=ds.prepare(q);
List<Entity> result = ds.prepare(q).asList(FetchOptions.Builder.withDefaults());
System.out.println(result);
}
Instead of
List<Entity> result = ds.prepare(q).asList(FetchOptions.Builder.withDefaults());
use
Entity result = ds.prepare(q).asSingleEntity();
String password = result.getProperty("Password");
The follwoing servlet snippet :
ResultSet set = statement.executeQuery();
// userName = set.getString(1);
if(set.next()) {
userName = set.getString("FirstName");
Email = set.getString("Email");
}
if(set.wasNull()) { //<<------------- line 33
// turn to the error page
response.sendRedirect("LoginFailure.jsp");
} else {
// start the session and take to his homepage
HttpSession session = request.getSession();
session.setAttribute("UserName", userName);
session.setMaxInactiveInterval(900); // If the request doesn't come withing 900 seconds the server will invalidate the session
RequestDispatcher rd = request.getRequestDispatcher("portfolio_one.jsp");
rd.forward(request, response); // forward to the user home-page
}
creates the following exceptions :
INFO: java.sql.SQLException: Invalid operation: wasNull() called with no data retrieved.
at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown Source)
at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)
at org.apache.derby.client.am.ResultSet.wasNull(Unknown Source)
at com.sun.gjc.spi.base.ResultSetWrapper.wasNull(ResultSetWrapper.java:141)
--------->> at projectcodes.ValidateDataForSignIn.doPost(ValidateDataForSignIn.java:33)
..........
Why does this exception occur ? The exception occurs due to the highlighted line : 33
This exception can occur when ResultSet#next() has returned false. I.e. there is no row at all and thus no column has been retrieved at all. The ResultSet#wasNull() only applies on the last retrieved column, not on the last retrieved row.
You need to rearrange your code logic.
if(set.next()) {
userName = set.getString("FirstName");
Email = set.getString("Email");
// start the session and take to his homepage
HttpSession session = request.getSession();
session.setAttribute("UserName", userName);
session.setMaxInactiveInterval(900); // If the request doesn't come withing 900 seconds the server will invalidate the session
RequestDispatcher rd = request.getRequestDispatcher("portfolio_one.jsp");
rd.forward(request, response); // forward to the user home-page
} else {
// turn to the error page
response.sendRedirect("LoginFailure.jsp");
}
More clear would be to refactor all that JDBC mess into a standalone UserDAO DAO class with a User model class which you then use as follows:
User user = userDAO.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user);
request.getRequestDispatcher("portfolio_one.jsp").forward(request, response);
} else {
response.sendRedirect("LoginFailure.jsp");
}
where the find() method look something like this:
public User find(String username, String password) throws SQLException {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
User user = null;
try {
connection = database.getConnection();
statement = connection.prepareStatement("SELECT id, username, email, firstname, lastname, FROM user WHERE username = ? AND password = MD5(?)");
statement.setString(1, username);
statement.setString(2, password);
resultSet = statement.executeQuery();
if (resultSet.next()) {
user = new User();
user.setId(resultSet.getLong("id"));
user.setUsername(resultSet.getString("username"));
user.setEmail(resultSet.getString("email"));
user.setFirstname(resultSet.getString("firstname"));
user.setLastname(resultSet.getString("lastname"));
}
} finally {
close(resultSet, statement, connection);
}
return user;
}
This way you end up with more self-documenting and better reuseable/testable code.
See also:
Show JDBC ResultSet in HTML in JSP page using MVC and DAO pattern