JPARepository findByUserName method returns null values - java

I want to use Spring security to get the currently logged in user object but it returns a null value. I implemented the findByUsername method from the repository to test but it comes back with null/empty values and I've ensured data is in the database. What could I be doing wrong ?
Entity class
public class User {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
private String firstName ;
private String lastName;
#Column(name="user_name", unique=true)
private String userName;
private String password;
private String Gender;
Repository class
#Repository
public interface UserAccountRepository extends JpaRepository <User, Long> {
Optional<User> findById(Long id);
User findByUserName(String username);
Service class
#Transactional
#Service
public class UserAccountService implements UserDetailsService {
#Autowired
private UserAccountRepository userRepository;
private PasswordEncoder bCryptPasswordEncoder;
public User findByUserName(String username)
{
return userRepository.findByUserName(username);
}
Controller class
#GetMapping(value="/user/{username}")
public User findByUsername(String username) {
System.out.println("Username :" + username);
return userAccountService.findByUserName(username);
}
Application properties
spring.datasource.url=jdbc:mysql://localhost:3306/investmentpartners
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username= root
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=update
## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.main.allow-bean-definition-overriding=true
spring.servlet.multipart.max-file-size=3000KB
spring.servlet.multipart.max-request-size=3000KB
spring.http.multipart.enabled=false
After adding spring.jpa.show-sql=true to application.properties file here is the query generated
Hibernate: select user0_.id as id1_4_, user0_.gender as gender2_4_, user0_.branch_id as branch_11_4_, user0_.created_date as created_3_4_, user0_.email as email4_4_, user0_.first_name as first_na5_4_, user0_.last_name as last_nam6_4_, user0_.password as password7_4_, user0_.phone_number as phone_nu8_4_, user0_.status as status9_4_, user0_.user_name as user_na10_4_ from user user0_ where user0_.user_name is null
null

You have forgotten to mark your path variable with annotation.
Solution:
#PathVariable String username
Controller class
#GetMapping(value="/user/{username}")
public User findByUsername(#PathVariable String username) {
System.out.println("Username :" + username);
return userAccountService.findByUserName(username);
}
Note:
Do not use System.out.println in your code to log out something, especially if you use Spring and your code runs in a server (Tomcat). Spring offers a perfect, easy to use way to write something to log:
public class YourController {
Logger logger = LoggerFactory.getLogger(YourController .class);
#GetMapping(...)
public String index(...) {
logger.debug("A DEBUG Message");
logger.info("An INFO Message");
// ...
}
}

Related

org.hsqldb.HsqlException: user lacks privilege or object not found: USER0_.NAME

I work with small Spring boot app and I get the error org.hsqldb.HsqlException: user lacks privilege or object not found: USER0_.NAME during I compile. I have the same error before and now I reproduce it to the minimal amount of code. This is the project structure,
The error is triggered by the method findAll() from the controller,
#Controller
public class UserController {
#Autowired
private UserService userService;
#GetMapping(value = "/")
public String index() {
return "redirect:/users";
}
#GetMapping(value = "/users")
public String showAllUsers(Model model) {
// triggered by this line
model.addAttribute("users", userService.findAll());
return "list";
}
}
The important part of the error stack is,
org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [select user0_.id as id1_1_, user0_.name as name2_1_ from user user0_]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement
......
Caused by: java.sql.SQLSyntaxErrorException: user lacks privilege or object not found: USER0_.NAME in statement [select user0_.id as id1_1_, user0_.name as name2_1_ from user user0_]
.........
Caused by: org.hsqldb.HsqlException: user lacks privilege or object not found: USER0_.NAME
The entity class is provided,
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
if (getId() != user.getId()) return false;
return getName().equals(user.getName());
}
#Override
public int hashCode() {
int result = (int) (getId() ^ (getId() >>> 32));
result = 31 * result + getName().hashCode();
return result;
}
}
The interfaces in the repository directory provided,
public interface UserRepository extends CrudRepository<User, Long> {
}
The user controller class is provided earlier. I can provide more info if required. My intention is will pass all the user values to the JSP page. I should mention, I don't have any user value now, the app will get the user info from a form and now it has nothing.
AS it asked from the comment, the services interface and classe are provided,
public interface UserService {
List<User> findAll();
User findById(Long idx);
void save(User user);
void delete(Long idx);
}
The service class implementation,
#Service
public class UserServiceImpl implements UserService {
#Autowired
private UserRepository userRepository;
#Override
public List<User> findAll() {
return (List)userRepository.findAll();
}
#Override
public User findById(Long idx) {
return userRepository.findOne(idx);
}
#Override
public void save(User user) {
userRepository.save(user);
}
#Override
public void delete(Long idx) {
userRepository.delete(idx);
}
}
I use HSQL database and the application properties is provided,
server.port=8081
spring.mvc.view.prefix:/WEB-INF/jsp/
spring.mvc.view.suffix:.jsp
spring.thymeleaf.cache=false
spring.application.name=Bootstrap Spring Boot
spring.thymeleaf.enabled=true
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.devtools.restart.additional-paths=.
security.basic.enabled=true
security.user.name=john
security.user.password=123
spring.datasource.url=jdbc:hsqldb:file:db/registration;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
spring.datasource.username=testuser
spring.datasource.password=testpassword
server.error.path=/error
server.error.whitelabel.enabled=false
# Keep the connection alive if idle for a long time (needed in production)
spring.datasource.testWhileIdle=true
spring.datasource.validationQuery=SELECT 1
# ===============================
# = JPA / HIBERNATE
# ===============================
# Use spring.jpa.properties.* for Hibernate native properties (the prefix is
# stripped before adding them to the com.boot.registration.entity manager).
# Show or not log for each sql query
spring.jpa.show-sql=true
# Hibernate ddl auto (create, create-drop, update): with "update" the database
# schema will be automatically updated accordingly to java entities found in
# the project
spring.jpa.hibernate.ddl-auto=create
# Allows Hibernate to generate SQL optimized for a particular DBMS
spring.messages.basename=validation
Update
Appearantly, none of the operations of the service interface works and provide the same set of errors. For example, if I put the code like,
#GetMapping(value = "/users")
public String showAllUsers(Model model) {
User user = new User();
user.setId(1L);
user.setName("Berlin");
userService.save(user);
// model.addAttribute("users", userService.findAll());
return "list";
}
I still have the same error Caused by: org.hsqldb.HsqlException: user lacks privilege or object not found: USER0_.NAME
What is the issue here?
I have excluded the JpaRepositoriesAutoConfiguration from the #SpringBootApplication and this apparently solved the issue here.
#EnableTransactionManagement
#SpringBootApplication(scanBasePackages = {"com.boot"} , exclude = JpaRepositoriesAutoConfiguration.class)
public class WebApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(WebApplication.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(WebApplication.class, args);
}
}

springboot always read data from primary datasource

My springboot app tries to read data from two datasources(emwbis and backupemwbis). I've followed the below link in configuring my springboot app to read data from two different datasources.
http://www.baeldung.com/spring-data-jpa-multiple-databases
The current problem with my app is it is always reading data from the primary datasource(emwbis). I've written below code.
Model classes for primary and backup datasources:
package com.jl.models.primary;
#Entity
#Table(name = "crsbis",schema="emwbis")
#Data
public class CrsBIS {
#Id
private String id;
#NotNull
private String email;
package com.jl.models.backup;
import lombok.Data;
#Entity
#Table(name = "crsbis",schema="backupemwbis")
#Data
public class CrsBIS {
#Id
private String id;
#NotNull
private String email;
Datasource config classes for primary and backup datasources:
#Configuration
#PropertySource("classpath:persistence-multiple-db.properties")
#EnableJpaRepositories(basePackages = "com.jl.dao.backup", entityManagerFactoryRef = "crsBISBackUpEntityManager", transactionManagerRef = "crsBISBackupTransactionManager")
public class BackupCrsBISDatabaseConfig {
#Configuration
#PropertySource("classpath:persistence-multiple-db.properties")
#EnableJpaRepositories(basePackages = "com.jl.dao.primary", entityManagerFactoryRef = "crsBISEntityManager", transactionManagerRef = "crsBISTransactionManager")
public class CrsBISDatabaseConfig {
Repository interfaces for primary and backup datasources:
#Transactional
public interface CrsBISRepository extends JpaRepository<CrsBIS, String> {
public CrsBIS findById(String id);
}
#Transactional
public interface CrBisBackupRepository extends JpaRepository<CrsBIS, String>{
public CrsBIS findById(String id);
}
Persistent db proeprties file :
jdbc.driverClassName=com.mysql.jdbc.Driver
crsbis.jdbc.url=jdbc:mysql://localhost:3306/emwbis
backupcrsbis.jdbc.url=jdbc:mysql://localhost:3306/backupemwbis
jdbc.user=root
jdbc.pass=Password1
Controller class to test both the datasources :
#Controller
public class CrsBISController {
#Autowired
private CrsBISRepository crsBISRepository;
#Autowired
private CrBisBackupRepository crsBackupRepository;
#RequestMapping("/get-by-id")
#ResponseBody
public String getById(String id){
String email="";
try{
CrsBIS crsBIS = crsBISRepository.findById(id);
email = String.valueOf(crsBIS.getEmail());
}catch (Exception e) {
e.printStackTrace();
return "id not found!";
}
return "The email is : "+email;
}
#RequestMapping("/get-by-id-backup")
#ResponseBody
public String getByIdFromBackup(String id){
String email="";
try{
com.jl.models.backup.CrsBIS crsBIS = crsBackupRepository.findById(id);
email = String.valueOf(crsBIS.getEmail());
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
return "id not found!";
}
return "The email is : "+email;
}
Although, I've separated the database schemas in the model classes and in the database config file, both the methods in the controller class hit the same database (emwbis). I want getByIdFromBackup method in controller class to read the data from secondary database (backupemwbis).
Can someone please let me know the mistake in my code? Or you can suggest/guide me to achieve my goal?
From the first configuration file you're creating a primary datasource bean definition with the name myDatasource and in the second emf you're injecting the same datasource reference.
The Bean causing the problem is this
#Bean
#Primary
public DataSource myDataSource()
Just change the second Bean datasource name and use it in the second EMF.
public class BackupCrsBISDatabaseConfig {
...
#Bean
public DataSource backupDS() {
....
#Bean
public LocalContainerEntityManagerFactoryBean crsBISBackUpEntityManager() {
....
em.setDataSource(backupDS());
}
}
Hope this fixes it.
You have to explicitly request a TransactionManager implementation in your #Transactional usage:
#Transactional("crsBISTransactionManager")
//..
#Transactional("crsBISBackupTransactionManager")
//..

update mysql table with hibernate showing error

In my Spring project I want to update mysql table field according to the url :
I have url below:
localhost:9191/access/name/article?key=xyz
I want to fetch the article from url and then update the status and article field of the corrsponding mysql table
In my database I have the table name "user".
user(stu_id,name,email,article,status)
mysql query is:
UPDATE user
SET article='null', status=true
WHERE article='xyz'; here xyz=user.getArticle()
To achieve this I have done the below
User.java is:
public User(String article, String status) {
super();
this.article = article;
this.status = status;
}
UserDao.java
public interface UserDao {
public void updateUser(User user);
}
UserDaoImpl.java is:
#Transactional
#Repository("userDao")
public class UserDaoImpl implements UserDao {
#Autowired
private SessionFactory sessionFactory;
public void updateUser(User user) {
String hql = "update user set article = null,status=true"
+"where article=:key1";
sessionFactory.getCurrentSession().createQuery(hql)
.setParameter("key1", user.getArticle());
}
}
UserService.java is:
public interface UserService {
User updateUser(String article, String status);
}
UserServiceImpl.java is:
#Service("userService")
#Transactional(propagation = Propagation.SUPPORTS)
public class UserServiceImpl implements UserService {
public User updateUser(String article, String status) {
User user = new User(article,status);
userDao.updateUser(user);
return user;
return user;
}
UserController.java is:
//localhost:9191/access/name/article?key=xyz
#RequestMapping(value="/access/name/id", method=RequestMethod.GET)
public #ResponseBody String byParameter( User user, HttpServletRequest request) {
boolean ps=true;
String foo= request.getParameter("key");
userService.updateUserinfo(foo, ps);
return "signupLogin";
}
but it is showing error:
ERROR [] (ErrorCounter.java:56) - line 1:51: unexpected token: key
ERROR [] (ErrorCounter.java:56) - line 1:58: unexpected token: =
java.lang.IllegalArgumentException: node to traverse cannot be null!
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1760)
at com.student.dao.UserDaoImpl.updateUser(UserDaoImpl.java:40)
at com.student.service.UserServiceImpl.updateUserinfo(UserServiceImpl.java:66)
where is the problem?What am I doing wrong??
Make following correction into sql query use User in place of user into query.
String hql = "update User set article = null, status = true where article = :key1";
if you don't want to change this method then you can use createSqlQuery method in place of createQuery method .
this solution may be help.
at com.student.dao.UserDaoImpl.updateUser(UserDaoImpl.java:40)
you were executing the wrong query.you should do like below code:
#Transactional
#Repository("userDao")
public class UserDaoImpl implements UserDao {
#Autowired
private SessionFactory sessionFactory;
public void updateUser(User user) {
String hql = "update user set article = null,status=true"
+"where article=:key1";
sessionFactory.getCurrentSession().createSQLQuery(hql)
.setParameter("key1", user.getArticle());
}
}
the syntax is like:
where user(this is the database table ) and article,status are the fields

Java DAO Object Transactions

I have a question as to how this service and its DAO object are performing persistence transactions.
The service is performing transactions on the database - but it is not using a DAOImpl object - it is instead using an object which is an instance of the interface - and naturally has no implementation of any method signatures. This, in my mind, should not be able to perform any meaningful actions. Am I overlooking something here?
Full link to code
http://www.byteslounge.com/tutorials/spring-with-hibernate-persistence-and-transactions-example
#Service
public class UserManagerImpl implements UserManager {
#Autowired
private UserDAO userDAO;
#Override
#Transactional
public void insertUser(User user) {
userDAO.insertUser(user);
}
#Override
#Transactional
public User getUserById(int userId) {
return userDAO.getUserById(userId);
}
#Override
#Transactional
public User getUser(String username) {
return userDAO.getUser(username);
}
#Override
#Transactional
public List<User> getUsers() {
return userDAO.getUsers();
}
}
public interface UserDAO {
void insertUser(User user);
User getUserById(int userId);
User getUser(String username);
List<User> getUsers();
}
#Service
public class UserDAOImpl implements UserDAO {
#Autowired
private SessionFactory sessionFactory;
#Override
public void insertUser(User user) {
sessionFactory.getCurrentSession().save(user);
}
#Override
public User getUserById(int userId) {
return (User) sessionFactory.
getCurrentSession().
get(User.class, userId);
}
#Override
public User getUser(String username) {
Query query = sessionFactory.
getCurrentSession().
createQuery("from User where username = :username");
query.setParameter("username", username);
return (User) query.list().get(0);
}
#Override
#SuppressWarnings("unchecked")
public List<User> getUsers() {
Criteria criteria = sessionFactory.
getCurrentSession().
createCriteria(User.class);
return criteria.list();
}
}
first of all , instance of an interface can not be created , reference variable can be created for interfaces. Nevertheless ,as i followed the link and found that you are learning Spring with Hibernate. Spring provide you a facility called Dependency Injection which is why there is #Autowire annotation in your UserManagerImpl class which means you have injected a dependency UserDAO in UserManagerImpl class , so on rum time ,spring will provide the instance of the class which implements UserDAO interface .What you are overlooking is thorough study of Spring concepts.by the way all the best .

Storing user object in session in Spring MVC application

I would like to know how to correctly store and retrieve my user in the session via Spring Security. I am using an AuthenticationManager. So far I am using the following approach which I know isn't the cleanest
public class UserController {
#Autowired
private UserService userService;
#RequestMapping(value="/myAccount", method=RequestMethod.GET)
public void myAccount(HttpServletRequest request){
//Verify Logged in user
User user = null;
UserProfile loggedinUser = (UserProfile) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if(loggedinUser != null){
user = userService.loadUserByUsername(loggedinUser.getUsername());
}
//Store User in session
Session session = request.getSession(true);
session.setAttribute("user", user);
}
}
I took a look at the answer here: Set User Object in session using Spring
But I don't fully understand how I should implement it. Could I possibly implement my User class like this
public class User implements UserDetails {
private String username;
private String password;
private String email;
......
}
And then modify my controller like this
public class UserController {
#Autowired
private UserDetailsService userDetailsService;
#RequestMapping(value="/myAccount", method=RequestMethod.GET)
public void myAccount(){
User user = (User)SecurityContextHolder.
getContext().getAuthentication().getPrincipal();
}
}
From my understanding, Spring will automatically load my custom User from the database and store it in the session?
Thanks

Categories