I was using this tutorial : spring boot CRUD application with tymeleaf
The problem happen when I try to had a user, I got this error :
2020-03-15 09:51:09.413 ERROR 10168 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException: null
at com.CRUD.CRUD_EXAMPLE.controller.UserController.addUser(UserController.java:33) ~[classes/:na]
Here's the code :
'''
#Controller
public class UserController {
private UserRepository userRepository;
#GetMapping("/signup")
public String showSignUpForm(User user) {
return "add-user";
}
#PostMapping("/adduser")
public String addUser(#Valid User user, BindingResult result, Model model) {
if (result.hasErrors()) {
return "add-user";
}
userRepository.save(user);
model.addAttribute("users", userRepository.findAll());
return "index";
}
#GetMapping("/edit/{id}")
public String showUpdateForm(#PathVariable("id") long id, Model model) {
User user = userRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id));
model.addAttribute("user", user);
return "update-user";
}
#PostMapping("/update/{id}")
public String updateUser(#PathVariable("id") long id, #Valid User user,
BindingResult result, Model model) {
if (result.hasErrors()) {
user.setId(id);
return "update-user";
}
userRepository.save(user);
model.addAttribute("users", userRepository.findAll());
return "index";
}
#GetMapping("/delete/{id}")
public String deleteUser(#PathVariable("id") long id, Model model) {
User user = userRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id));
userRepository.delete(user);
model.addAttribute("users", userRepository.findAll());
return "index";
}
}
'''
My line 33 is 'userRepository.save(user)';
Please mark your UserRepository implementation class with the #Repository annotation, like this:
#Repository
public class UserRepositoryImpl implements UserRepository {
Then inject the dependency via the #Autowired annotation in your controller like this:
#Controller
public class UserController {
private UserRepository userRepository;
#Autowired
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
This will fix your NullPointerException, because Spring will now create and inject this dependency for you.
As it says you, The object User user that comes to the method is null, or one of its field is null.
Make sure that this objects contains all data coming from view.
Check also if all the field in your html file are well mapped to the field of the User object.
Related
As i consume a lot of data in httpservletrequest header and set a lot of values in request attribute in service class, I'm not sure if this would cause thread safety issues, I looked over the web if autowiring httpservlet request would cause threadsafety issues and i got mixed opinion
Following are the places where i autowire httpservletrequest
#RestController
Public class UserController {
#Autowire
HttpServletRequest httpServletRequest;
#Autowire
IAMService iamservice;
#PostMapping("/addUser")
public String addUser(#RequestBody UserDto userdto){
return iamservice.addUser(userdto);
}
}
#Service
Public Class IAMService {
#Autowire
HttpServletRequest httpServletRequest;
#Autowire
UserDao userDao;
public String addUser(UserDto userdto){
Long primaryKey = userDao.save(userdto,httpServletRequest.getHeader("loggedInUserId"));
httpServletRequest.setAttribute("userPrimaryKey",primaryKey);
return "User is added successfully";
}
}
We should not #Autowire HttpServletRequest. Consider modifying your code as below to have valid usage of request object and avoid thread-safety issues-
#RestController
Public class UserController {
#Autowire
IAMService iamservice;
#PostMapping("/addUser")
public String addUser(#RequestBody UserDto userdto, HttpServletRequest httpServletRequest){
return iamservice.addUser(userdto, httpServletRequest);
}
}
#Service
Public Class IAMService {
#Autowire
UserDao userDao;
public String addUser(UserDto userdto, HttpServletRequest httpServletRequest){
Long primaryKey = userDao.save(userdto,httpServletRequest.getHeader("loggedInUserId"));
httpServletRequest.setAttribute("userPrimaryKey",primaryKey);
return "User is added successfully";
}
}
Working on my first app using Spring data with Reactive Couchbase and having trouble with repository operations. I can create a User in my UserRepository and can retrieve it by id or name, but can't delete it. deleteAll() doesn't work either.
#N1qlPrimaryIndexed
#ViewIndexed(designDoc = "user")
interface UserRepository extends ReactiveCouchbaseRepository<User, String> {
Flux<User> findByName(String name)
}
#Service
class UserServiceImpl implements UserService {
#Autowired
private UserRepository userRepository
Mono<User> save(User user) {
return userRepository.save(user)
}
Mono<Void> delete(User user) {
return userRepository.delete(user)
}
Mono<User> findById(String id) {
return userRepository.findById(id)
}
Flux<User> findByName(String name) {
return userRepository.findByName(name)
}
}
class UserServiceTest extends ApplicationTests {
#Autowired
private UserService userService
#Test
void testSave() {
User user = new User(null, 'name')
User savedUser = userService.save(user).block()
List<User> allUsers = userRepository.findAll().collectList().block()
assert allUsers.size() == 1
userService.delete(allUsers.first())
allUsers = userRepository.findAll().collectList().block()
assert allUsers.size() == 0 // fails here
}
}
You simply forgot to subscribe() (or block()) to the delete Mono<Void>
What's the best approach to avoid repeating the same userService DB lookup over and over again in my controller methods?
I'm using Spring Boot 1.5.2 with spring-boot-starter-security and spring-boot-starter-thymeleaf for templating.
I tried adding an instance variable for SecurityContextHolder.getContext().getAuthentication() but it gave me a NullPointerException.
#Controller
public class DashboardController {
#Autowired
private UserService userService;
#Value("${product.name}")
private String productName;
#RequestMapping(value="/dashboard", method = RequestMethod.GET)
public ModelAndView home() {
ModelAndView modelAndView = new ModelAndView();
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
User user = userService.findUserByEmail(auth.getName());
modelAndView.addObject("email", user.getEmail());
modelAndView.setViewName("dashboard");
return modelAndView;
}
#RequestMapping(value="/dashboard/faq", method = RequestMethod.GET)
public ModelAndView faq(){
ModelAndView modelAndView = new ModelAndView();
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
User user = userService.findUserByEmail(auth.getName());
modelAndView.addObject("email", user.getEmail());
modelAndView.addObject("productname", productName);
modelAndView.setViewName("faq");
return modelAndView;
}
If you want to get at the user that is stored in the session, you can use this annotation:
#RequestMapping("/me")
public User me(#AuthenticationPrincipal User user) {
return user;
}
If you then want the user to always be available in thymeleaf I would use a #ControllerAdvice
#ControllerAdvice(annotations = Controller.class)
public class GlobalVariablesControllerAdvice {
#ModelAttribute("user")
public User user() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
User user = null;
// get user from authentication, but make sure to check for nulls
return user;
}
}
Problem
Invoking repository.save(user); where repository is an instance of UserRepository and user.toString is User[id=0, userName='asd', password='asd'], my controller gives the following error:
nested exception is java.lang.IllegalArgumentException: Invoked method public abstract java.lang.Object org.springframework.data.repository.CrudRepository.save(java.lang.Object) is no accessor method!] with root cause
java.lang.IllegalArgumentException: Invoked method public abstract java.lang.Object org.springframework.data.repository.CrudRepository.save(java.lang.Object) is no accessor method!
Details
I know repository.save(new User("user1", "pass1")); works because I tested my repository using:
public CommandLineRunner demo(UserRepository repository) {
return (args) -> {
// save a couple of users
repository.save(new User("user1", "pass1"));
repository.save(new User("user2", "pass2"));
}
}
Here's the full Request mapping of the page:
RequestMapping(value = "/register", method = RequestMethod.GET)
public String showRegistrationForm(WebRequest request, Model model) {
User user = new User();
model.addAttribute("user", user);
return "registrations/register";
}
#RequestMapping(value = "/register", method = RequestMethod.POST)
public String registerUserAccount(WebRequest request,
#ModelAttribute("user") #Valid User user,
BindingResult result,
UserRepository repository) {
if (!result.hasErrors()) {
System.out.println(user);
repository.save(user);
}
return "redirect:/";
}
And here's the UserRepository:
import java.util.List;
import org.springframework.data.repository.CrudRepository;
public interface UserRepository extends CrudRepository<User, Long> {
List<User> findByUserName(String UserName);
}
And here's the User #Entity:
#Entity
public class User {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
private String userName;
private String password;
protected User() {}
public User(String userName, String password) {
this.userName = userName;
this.password = password;
}
// standard getters and setters
#Override
public String toString() {
return String.format(
"User[id=%d, userName='%s', password='%s']",
id, userName, password);
}
}
It seems the UserRepository repository in code of Controller should not be used as parameter:
...
public String registerUserAccount(WebRequest request,
#ModelAttribute("user") #Valid User user,
BindingResult result,
UserRepository repository)
...
Can you just use #Autowired it like:
#Autowired
private UserRepository repository;
And then try again?!
Hope this help.
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