This is the line where I'm getting the error
List<Map<String, Object>> users = jdbcTemplate.queryForList("select * from user where email=? and pass=?",new Object[] { email, pass }, new MyRowMapper());
This is the whole code:
package com.example.dao;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import com.example.model.User;
#Repository
public class UserDao {
#Autowired
private JdbcTemplate jdbcTemplate;
public int insert(User user) {
return jdbcTemplate.update("insert into user values(?,?,?,?,?)",
new Object[] { user.getName(), user.getEmail(), user.getPass(),user.getProfileimage(),user.getExpensetable() });
}
public int updateProfile(User user) {
return jdbcTemplate.update("update user set name=?,pass=?,profile=?,expensetable=? where email=?",
new Object[] { user.getName(), user.getPass(), user.getProfileimage(),user.getExpensetable(), user.getEmail() });
}
public User login(String email, String pass) {
User user = null;
List<Map<String, Object>> users = jdbcTemplate.queryForList("select * from user where email=? and pass=?",new Object[] { email, pass }, new MyRowMapper());
if (users.size() > 0) {
user = (User) users.get(0);
}
return user;
}
private class MyRowMapper implements RowMapper<User> {
#Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setName(rs.getString(1));
user.setEmail(rs.getString(2));
user.setPass(rs.getString(3));
user.setProfileimage(rs.getString(4));
user.setExpensetable(rs.getString(5));
return user;
}
}
}
This is the error:
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/ExpenseSpringProject] threw exception [Request processing failed; nested exception is org.springframework.dao.TransientDataAccessResourceException: PreparedStatementCallback; SQL [select * from user where email=? and pass=?]; Invalid argument value: java.io.NotSerializableException; nested exception is java.sql.SQLException: Invalid argument value: java.io.NotSerializableException] with root cause
java.io.NotSerializableException: com.example.dao.UserDao$MyRowMapper
You are calling the wrong JdbcTemplate method.
The method you are calling takes a query and a varargs array of the bind parameter values. The way you are calling it, you are passing the following as bind parameter values:
an array containing your email and password.
a row-mapper.
The row-mapper is not being used to map rows, instead you are attempting to pass it to the database as if it is a value itself.
I think you want to use the overload of JdbcTemplate.query that takes a query, a row-mapper and the bind parameter values in that order.
Try replacing the line
List<Map<String, Object>> users = jdbcTemplate.queryForList("select * from user where email=? and pass=?",new Object[] { email, pass }, new MyRowMapper());
with
List<User> users = jdbcTemplate.query("select * from user where email=? and pass=?", new MyRowMapper(), email, pass);
Once you've done that, the cast to User in the line user = (User) users.get(0); should become unnecessary and you can remove it.
Related
I am new to MongoDB Mlab, which means not familiar with how to use it and how to connect it with a DAO file. And I encounter a technical issue on SERVLET. Firstly, I try to extract data from MongoDB mlab to get an email & password of a user for my login page. And I also capture the email & password entered by a user on login JSP page by using "request.getParameter("")" method. These two points work fine because I already tested them. More info about my issue is that when I try to extract email and password from MongoDB mlab, I store these two parameters into a user object, and store the user object into an ArrayList. Then return this Arraylist to the login Servlet. Using for-each loop to traversal this list. I put the codes below.
When I try to enter an email and password on the login page, this is the result I encountered
how can I solve it
FDao.java
package Dao;
import static com.sun.corba.se.spi.presentation.rmi.StubAdapter.request;
import java.net.UnknownHostException;
import java.sql.*;
import java.util.*;
import javax.servlet.RequestDispatcher;
import model.Book;
import model.Staff;
import model.User;
import org.bson.Document;
public class FDao {
public List<User> checkLogin() throws UnknownHostException {
Iterator it = DB.getDB().getCollection("users").find().iterator();
List<User> aUser = new ArrayList();
while(it.hasNext()){
Document o = (Document) it.next();
aUser.add(new User(o.getString("email"), o.getString("password")));
}
return aUser;
}
}
LoginServlet.java(I capture string email and string password from login JSP page)
#WebServlet("/Login")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public LoginServlet() {
super();
}
FDao userDao = new FDao();
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
String email = request.getParameter("email");
String password = request.getParameter("pass");
List<User> users = new ArrayList();
users = userDao.checkLogin();
for (User user : users) {
if (email.equals(user.getEmail()) && password.equals(user.getPassword()) ) {
//HttpSession session = request.getSession();
//session.setAttribute("user", user);
request.getRequestDispatcher("/home.jsp").include(request, response); //the problem looks like appeared in this line of code
//out.println("Hello World");
} else {
//String message = "Your account does not exist in out database!";
//request.setAttribute("message", message); //message is object
request.getRequestDispatcher("/Login.jsp").include(request, response);//the problem looks like appeared in this line of code
//out.println("Nothing");
}
break;
}
}
}
Hello I keep getting this error while using API URL to get specific parking spot number list of reservations, this is the error:
java.lang.ClassCastException: org.apache.tomcat.dbcp.dbcp2.DelegatingPreparedStatement cannot be cast to java.sql.ResultSet
here is my method that sends a query for specific parking space ID:
public List<Book> getSpecBook(int id) throws Exception {
List<Book> books = new ArrayList<>();
//int idInt = Integer.parseInt(id);
Connection myConn = null;
PreparedStatement myStmt = null;
ResultSet myRs = null;
try {
myConn = dataSource.getConnection();
// create sql statement
String sql = "SELECT * FROM `rezerwacje_miejsc` WHERE `NR_MIEJSCA`=?";
myStmt = myConn.prepareStatement(sql);
myStmt.setInt(1, id);
myRs = myStmt.executeQuery();
while (myRs.next()) {
// retrive data from result set row
int placeNo = ((ResultSet) myStmt).getInt("NR_MIEJSCA");
Date start = ((ResultSet) myStmt).getDate("START");
Date end = ((ResultSet) myStmt).getDate("KONIEC");
String userName = ((ResultSet) myStmt).getString("IMIE_NAZWISKO");
int phone = ((ResultSet) myStmt).getInt("TELEFON");
// create new temporary Book object
Book tempBook = new Book(placeNo, start, end, userName, phone);
// add it to our list of Books
books.add(tempBook);
}
return books;
} finally {
// clean up JDBC objects
close(myConn, myStmt, myRs);
}
}
and here is my API class:
package com.pbs.web.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pbs.web.jdbc.ParkingBookSystem.Book;
import com.pbs.web.jdbc.ParkingBookSystem.BookDbUtil;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
#Path("books")
#Produces(MediaType.APPLICATION_JSON)
public class BookingRestController {
private BookDbUtil bookDbUtil = new BookDbUtil();
#GET
#Path("/")
public Response getAllBooks() throws Exception {
List<Book> books = bookDbUtil.getBooks();
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(books);
return Response.ok().entity(json).build();
}
#GET
#Path("/{id}")
public Response getSpecBook(#PathParam("id") int id) throws Exception {
List<Book> books = bookDbUtil.getSpecBook(id);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(books);
return Response.ok().entity(json).build();
}
}
I'm not able to find the issue.
You're writing lines like
int placeNo = ((ResultSet) myStmt).getInt("NR_MIEJSCA");
This is evidently where you are getting the error. The error says that a statement cannot be cast to a result set, and here you are trying to cast a statement to a result set.
I cannot fathom why you would think you'd access the result set this way, especially given that you've already done the work to get the result set from the statement. It's in your variable myRs.
You probably want
int placeNo = myRs.getInt("NR_MIEJSCA");
(and similar for other lines) instead.
I am new to hibernate and am struggling with adding a single projection to a criteria query. I am getting an error with the following code: "java.lang.Integer cannot be cast to [Ljava.lang.Object, on line 29. I know it is something very simple, but I cant figure out what I am doing wrong here!
Code is as follows:
package com.simpleprogrammer;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import java.util.Date;
import java.util.List;
import java.util.Objects;
public class Program {
public static void main(String[] args) {
System.out.println(org.hibernate.Version.getVersionString());
System.out.println("Creating session!");
PopulateSampleData();
Session session = HibernateUtilities.getSessionFactory().openSession();
session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.eq("name", "Joe")).setProjection(Projections.property("id"));
List<Object[]> results = criteria.list();
for(Object[] result : results) {
for (Object o : result)
System.out.println("Name is " + o.toString());
}
session.close();
HibernateUtilities.getSessionFactory().close();
}
private static void PopulateSampleData() {
Session session = HibernateUtilities.getSessionFactory().openSession();
session.beginTransaction();
User joe = CreateUser("Joe", 500, 50, "Good job", "You made it!");
session.save(joe);
User bob = CreateUser("Bob", 300, 20, "Taco time!");
session.save(bob);
User amy = CreateUser("Amy", 250, 200, "Yes!!!");
session.save(amy);
session.getTransaction().commit();
session.close();
}
private static User CreateUser(String name, int goal, int total, String... alerts) {
User user = new User();
user.setName(name);
user.getProtienData().setGoal(goal);
user.addHistory(new UserHistory(new Date(), "Set goal to " + goal));
user.getProtienData().setTotal(total);
user.addHistory(new UserHistory(new Date(), "Set total to " + total));
for (String alert : alerts) {
user.getGoalAlerts().add(new GoalAlert(alert));
}
return user;
}
}
I suspect that criteria.list() is returning List<Integer> instead of List<Object[]> since a single column is fetched.
Try changing
List<Object[]> results = criteria.list();
to
List<Integer> results = criteria.list();
I'm having an issue with my login class. If a user unsuccessfully attempts to login with a username then that user account should be disabled. At runtime there are no errors but nothing changes in my database. Am I doing something wrong with updating my database through Hibernate, I thought I could just use my UserBean.class to access properties, change them and then commit the Hibernate transaction?
Here is my LoginDAO.class:
package com.sga.app.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.context.internal.ManagedSessionContext;
import org.hibernate.criterion.Restrictions;
import org.owasp.encoder.Encode;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import com.sga.app.beans.UserBean;
import com.sga.app.hibernate.HibernateUtil;
import com.sga.app.security.LoginFailureEventListener;
import com.sga.app.security.XssRequestWrapper;
#Component("loginDAO")
#Transactional
#Configuration
public class LoginDAO implements
ApplicationListener<AuthenticationFailureBadCredentialsEvent> {
private int loginAttemptsThreshold;
private int failedLoginAttempts;
private static Logger logger = Logger
.getLogger(LoginFailureEventListener.class);
private static Session session;
private Criteria criteria;
private String username;
private boolean enabled;
private String forename;
private String authority;
private XssRequestWrapper xssReqWrapper;
private PreparedStatement prepStmtUsers;
private PreparedStatement prepStmtAuthorities;
private String URL = "jdbc:oracle:thin:system/sgaWebApp#localhost:1521/XE";
private String updateUsersStatement = "insert into users (username, password)
values (:username, :password)";
private String updateAuthoritiesStatement = "insert into authorities (username,
authority) values (:username, :authority)";
#Bean
public LoginDAO loginDAO() {
return new LoginDAO();
}
public void setLoginAttemptsThreshold(int threshold) {
this.loginAttemptsThreshold = threshold;
}
#Transactional
public void loginUser(UserBean user, BindingResult result) {
try {
Connection conn = DriverManager.getConnection(URL);
// clean out any possible XSS injection
String cleanUsernameValueInput = cleanOutXSSVulnerabilities("j_username");
String cleanPasswordValueInput = cleanOutXSSVulnerabilities("j_password");
// OWASP encoding
String safeUsername = Encode.forHtml(cleanUsernameValueInput);
prepStmtUsers.setString(1, safeUsername);
String safePassword = Encode.forHtml(cleanPasswordValueInput);
prepStmtUsers.setString(2, safePassword);
prepStmtAuthorities.setString(1, safeUsername);
String safeUserAuthority = Encode.forHtml(user.getAuthority());
prepStmtAuthorities.setString(2, safeUserAuthority);
// execute login process
prepStmtUsers = conn.prepareStatement(updateUsersStatement);
prepStmtAuthorities = conn
.prepareStatement(updateAuthoritiesStatement);
prepStmtUsers.executeUpdate();
prepStmtAuthorities.executeUpdate();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
} catch (AccessDeniedException accessDenied) {
accessDenied.printStackTrace();
}
}
private String cleanOutXSSVulnerabilities(String input) {
return xssReqWrapper.cleanXSS(input);
}
#Override
public void onApplicationEvent(
AuthenticationFailureBadCredentialsEvent event) {
if (event.getException().getClass()
.equals(UsernameNotFoundException.class)) {
return;
}
// print registration attempts to log file for security investigation if
// required
logger.info("Registration attempt failed: " + event.getException());
logger.info("Registration attempt number: " + event.getTimestamp());
String userId = event.getAuthentication().getName();
logger.info("FAILED LOGIN ATTEMPT NUMBER "
+ recordLoginAttempts(userId));
recordLoginAttempts(userId);
if (recordLoginAttempts(userId) >= loginAttemptsThreshold) {
lockoutUser(userId);
}
}
private int recordLoginAttempts(String userId) {
failedLoginAttempts++;
return failedLoginAttempts;
}
#SuppressWarnings("unchecked")
private ArrayList<UserBean> getUserAccountDetails(String input) {
ArrayList<UserBean> returnValues = new ArrayList<UserBean>();
session = HibernateUtil.createSessionFactory().openSession();
session.setFlushMode(FlushMode.MANUAL);
ManagedSessionContext.bind(session);
session.beginTransaction();
criteria = session.createCriteria(UserBean.class);
List<UserBean> retrievedUser = criteria.add(
Restrictions.like("username", input)).list();
for (UserBean userDetails : retrievedUser) {
logger.debug("USERNAME INSIDE THE GET USER ACCOUNT DETAILS METHOD: "
+ userDetails.getUsername());
logger.debug("AUTHORITY INSIDE THE GET USER ACCOUNT DETAILS METHOD: "
+ userDetails.getAuthority());
returnValues.add(userDetails);
}
session.flush();
session.getTransaction().commit();
session.close();
return returnValues;
}
private void lockoutUser(String userId) {
ArrayList<UserBean> userAccountValues = getUserAccountDetails(userId);
session = HibernateUtil.createSessionFactory().openSession();
session.setFlushMode(FlushMode.MANUAL);
ManagedSessionContext.bind(session);
session.beginTransaction();
for (UserBean user : userAccountValues) {
username = user.getUsername();
forename = user.getForename();
enabled = user.getEnabled();
authority = user.getAuthority();
logger.debug("USERNAME: " + username);
logger.debug("FORENAME: " + forename);
logger.debug("ENABLED BEFORE CHANGE: " + enabled);
user.setEnabled(false);
logger.debug("AUTHORITY BEFORE CHANGE: " + authority);
user.setAuthority("BLOCKED");
}
session.flush();
session.getTransaction().commit();
logger.debug("ENABLED AFTER CHANGE: " + enabled);
logger.debug("AUTHORITY AFTER CHANGE: " + authority);
session.close();
ManagedSessionContext.unbind(HibernateUtil.createSessionFactory());
}
}
I don't think you should be invoking openSession in that manner. I would highly suggest you rewrite the method to not do any "session" related work at all. Let Spring handle it, especially since you are already using #Transactional.
Either way, in the lockoutUser() method, the users you find, aren't bound to the session that gets created after it.
ArrayList<UserBean> userAccountValues = getUserAccountDetails(userId);
session = HibernateUtil.createSessionFactory().openSession();
So, later in the method when you update the user instances of that ArrrayList, the session doesn't realize that the user instances are to be persisted because the session was never tracking them.
Try to have only one session per thread. Each method can have its own transaction, but we rarely come across situations where we need more than one session in a thread. This doesn't seem to be that kind of a situation.
session.flush();
session.getTransaction().commit();
session.close();
Try to delete session.flush(); or put it after session.getTransaction().commit(); may work.
It doesn't appear that you call session.save(Object) or session.update(Object).
I am newbie in using Spring MVC 3.0. I am writing a custom authentication class and I would like to know how I can extract the values from a SQL query into variables? Here is an example of what I am trying to achieve, and some code, which I am asking about, is omitted;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.log4j.Logger;
import org.springframework.jdbc.core.simple.ParameterizedRowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import com.crimetrack.DAO.LoginDAO;
import com.crimetrack.business.Login;
public class JdbcLoginDAO extends JdbcDaoSupport implements LoginDAO {
private final Logger logger = Logger.getLogger(getClass());
String dbUserName;
String dbPassword;
public boolean AuthenticateUser(Login login) {
logger.debug("Authenticating User");
String sql = "SELECT userName, password FROM tblofficers WHERE userName = :userName AND password = :password ";
//code for parameters : userName and password using login.getPassword() and login.getUsername()
//and code to get vaules out from query for comparison
if (dbUserName == login.getUserName()) {
if (dbPassword == login.getPassword()){
return true;
}
}
return false;
}
public static class LoginMapper implements ParameterizedRowMapper<Login>{
public Login mapRow(ResultSet rs, int rowNum) throws SQLException {
Login dbLogin = new Login();
dbLogin.setUserName(rs.getString("userName"));
dbLogin.setPassword(rs.getString("password"));
return dbLogin;
}
}
}
Return the query as another instance of your "Login" class using JDBCTemplate and BeanPropertyRowMapper and then compare the objects.
You'll have to look into JDBCTemplate to define the database connection but eventually this would look like:
UserLogin authenticLogin = (UserLogin) db_connection.queryForObject(sql, new BeanPropertyRowMapper(UserLogin.class));
if (userLogin.getPassword() == authenticLogin.getPassword()) {
return true
}
Basically, BeanPropertRowMapper will create a new instance of a class settting any properties with the same names as columns returned from the query.