How to display data of objects in JSP - java

I have stored some user details through a register form into db (hibernate and spring). I want to display the user details of all users in a separate JSP page.Could anyone please tell me how to do that?
Below is my code of controller
#Controller
public class RegisterController {
#Autowired
private UserDao userDao;
#RequestMapping(value = "/registerForm.htm", method = RequestMethod.GET)
public ModelAndView registerPage(ModelMap map) {
User user = new User();
map.addAttribute(user);
return new ModelAndView("registerForm", "command", user);
}
#RequestMapping(value = "/registerProcess.htm", method = RequestMethod.POST)
public ModelAndView registerUser(#ModelAttribute("user") User user, Model model) {
model.addAttribute("userName", user.getUserName());
model.addAttribute("password", user.getPassword());
model.addAttribute("emailId", user.getEmailId());
System.out.println("user is " + user);
System.out.println("userdao is" + userDao);
userDao.saveUser(user);
return new ModelAndView("registerProcess", "user", user);
}
}
code inside userdao
public void saveUser(User user) {
Session session=getSessionFactory().openSession();
Transaction tx;
tx=session.beginTransaction();
session.persist(user);
tx.commit();
}

You should obtain the elements you want to show to user in a GET request. This involves the following steps:
Have a proper URL mapping and view to process the GET.
Obtain the data in the method that will pre process your URL.
Store the data to display to users as request attribute.
Forward to the view (JSP).
In view, display the data from request attributes.
A very simple example based on your current code and assuming the existence of some methods:
#Controller
public class RegisterController {
#Autowired
private UserDao userDao;
#RequestMapping(value="/registerForm.htm",method=RequestMethod.GET)
public ModelAndView registerPage(ModelMap map){
User user=new User();
map.addAttribute(user);
return new ModelAndView("registerForm","command",user);
}
#RequestMapping(value="/registerProcess.htm",method=RequestMethod.POST)
public ModelAndView registerUser(#ModelAttribute("user") User user,Model model){
model.addAttribute("userName", user.getUserName());
model.addAttribute("password", user.getPassword());
model.addAttribute("emailId",user.getEmailId());
System.out.println("user is "+user);
System.out.println("userdao is"+userDao);
userDao.saveUser(user);
return new ModelAndView("registerProcess","user",user);
}
//this is the new method with proper mapping
#RequestMapping(value="/userList.htm", method=RequestMethod.GET)
public ModelAndView registerPage(ModelMap map) {
//this method should retrieve the data for all users
List<User> userList = userDao.getAllUsers();
map.addAttribute("userList", userList);
return new ModelAndView("userList", map);
}
}
Then, in userList.jsp:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="en">
<head>
<title>User List</title>
</head>
<body>
List of users:
<br />
<table>
<c:forEach items="${userList}" var="user">
<tr>
<td>${user.userName}</user>
</tr>
</c:forEach>
</table>
</body>
</html>
Note that this is a very basic example about how to do this. The code can be heavily improved.
More info:
How to pass parameter to jsp:include via c:set? What are the scopes of the variables in JSP?
How to avoid Java code in JSP files?

Write another method to get all the users and then store the list of retrieved users in your model object then use the JSTL forEach tag in your JSP to display the users, you can use this link to see how the data can be displayed on JSP using JSTL forEach loop: JSP Errors in ForEach Loop

Related

Spring Boot, Html button which will add parameters to table in database

I want to make a link or another html element which will add parameters to table in MySQL database using JPA and Thymeleaf. I've made a link which have a good url (create a new parameters in table) but after click on this element firefox says : "The address wasn’t understood" but manually entered the same url works. I need that element in index.html which after click will insert into table values. Thank you.
Controller:
#Controller
public class UserController {
#RequestMapping("/")
public String home() {
return "index";
}
#Autowired
private UserDao userDao;
#RequestMapping("/create")
#ResponseBody
public String create(String email, String name) {
String userId="";
try {
User user = new User(email, name);
userDao.save(user);
userId = String.valueOf(user.getId());
}
catch (Exception exception) {
return "Error creating the user" + exception.toString();
}
return "User succesfully created with id = " + userId;
}
index.html :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HomePage</title>
</head>
<body>
<div id="container">
<a href="localhost:8080/create/email=john10234#gmail.com&name=John">Click to
add: ([id], 'john10234#gmail.com', 'John')
</a>
</div>
</body>
</html>
you missed ? in url
your url will
a href="localhost:8080/create?email=john10234#gmail.com&name=John">
instead of a href="localhost:8080/create/email=john10234#gmail.com&name=John">
Also use #RequestParam
#RequestMapping("/create")
#ResponseBody
public String create(#RequestParam("email")String email, #RequestParam("name")String name)

list of objects from controller to jsp and <c:forEach>

I try to send list of Employee from Spring MVC controller and then use it in jsp with forEach loop but receive blank page.
What is wrong?
Here is my code:
#RequestMapping(value = "getuserbylastname", method = RequestMethod.GET)
Employee employee, ModelMap model) {
public ModelAndView searchUserByLastname(#ModelAttribute("employee")Employee employee, ModelMap model) {
List emplList = new ArrayList();
EmployeeDAO employeeDAO = new EmployeeDAOImpl();
emplList = employeeDAO.getByLastname(employee.getLastName());// here list size is 2
model.addAttribute("listOfEmployees", emplList);
return new ModelAndView("redirect:/searchbysurnameresult", "Model", emplList);
}
jsp:
<html>
<body>
<c:forEach var="employee" items="${Model}">
<c:out value="${employee.firstName}"/>
</c:forEach>
</body>
</html>
P.S.I have a taglib url in JSP but there is a problem to display it like code at this site
When you redirect your page this issue occurs and the data present in your model attribute becomes null. Spring MVC has added new type of attribute said as FlashAttributes. Use them to solve this issue.
This link has more information on how to use Flash attributes.
this works:
#RequestMapping(value = "getuserbylastname", method = RequestMethod.GET)
public RedirectView searchUserByLastname(#ModelAttribute("employee") Employee employee, RedirectAttributes redirectAttrs) {
List emplList = new ArrayList();
EmployeeDAO employeeDAO = new EmployeeDAOImpl();
emplList = employeeDAO.getByLastname(employee.getLastName());
redirectAttrs.addFlashAttribute("listOfEmployees", emplList);
return new RedirectView("searchbysurnameresult", true);
}

Sending HttpSession from one controller to another in spring mvc

I am redirecting my request from one controller to another, but while doing that I am loosing my session attributes. But I want to use the session only so that I can verify if user is logged in or not. Whole condition is explained below:
Login.jsp
This is the page in which user gives its username and password and the request goes to "LoginController" .
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Login</title>
</head>
<body>
${loginError }
<h1>Login Details</h1>
<form action="${pageContext.request.contextPath }/login" method="post">
<table>
<tr>
<td>Username</td>
<td><input type="text" name="userId" ></td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" name="password" ></td>
</tr>
<tr>
<td><input type="submit" name="Submit" value="Submit"></td>
</tr>
</table>
</form>
</body>
</html>
LoginController.java
As the action was "login" using post method so the request maps to "verifyLogin()" method.
I have checked for the customer name it is coming after calling "loginCustomer()" method of "CustomerService" class.
But when I set it in session attributes and redirect it to url which match up to "HomeController" method I am losing that session attributes their.
#Controller
#RequestMapping(value="/login")
public class LoginController {
#Autowired
private CustomerService customerService;
#RequestMapping(method=RequestMethod.GET)
public String showLoginForm(){
return "login";
}
#RequestMapping(method=RequestMethod.POST)
public String verifyLogin(#RequestParam String userId, #RequestParam String password, HttpSession session, Model model){
Customer customer = customerService.loginCustomer(userId, password);
if(customer==null){
model.addAttribute("loginError", "Username or password is not correct");
return "login";
}
session.addAttribute("loggedInUser", customer);
return "redirect:/";
}
#RequestMapping(value="logout", method=RequestMethod.GET)
public String logoutUser(HttpSession session){
session.removeAttribute("loggedInUser");
return "login";
}
#ExceptionHandler(Exception.class)
public ModelAndView handleException(){
ModelAndView mav = new ModelAndView();
mav.addObject("loginError", "Usrname or password is not correct");
mav.setViewName("login");
return mav;
}
}
HomeController.java
The request mapped to "home()" method. This method is also called when application loads up, and when user logged in correctly then also it is called.
Here in this method I am loosing my session attribute, but I want it in the page were this method maps i.e. home.jsp the return value of this method.
As session attribute is not available in this method so its not available in the home.jsp page also.
Please help.
#Controller
public class HomeController {
#Autowired
private ProductService productService;
#Autowired
private CategoryService categoryService;
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Model model) {
List<Product> products = productService.getFeaturedProducts();
List<Category> categories = categoryService.getAllCategories();
model.addAttribute("featuredProduct", products);
model.addAttribute("categories",categories);
return "home";
}
}
I would suggest to go for RedirectAttributes.
redirectAttrs.addFlashAttribute("loggedInUser", customer);
Further reading: -Flash Attribute
My first guess would be that your session Id cookie might get lost between login and next page. (could be because the Web app is configured not to use cookies or the cookie is set for the wrong domain)
To verify check in your browser that:
After successful login the server sets the session cookie for the current host (chrome or Firefox Dev tools can help you here)
And also that your Browser sends the same cookie in the next request for the homepage.
If this does not help please also include the set cookie and the cookie headers in your reply
I've used session with the help plain old HttpServletRequest request and that seemed to serve the purpose for me.
#RequestMapping(method=RequestMethod.POST)
public String verifyLogin(#RequestParam String userId, #RequestParam String password, HttpServletRequest request, Model model){
Customer customer = customerService.loginCustomer(userId, password);
HttpSession session = request.getSession(false);
if (session == null) {
session = request.getSession();
}
if(customer==null){
model.addAttribute("loginError", "Username or password is not correct");
return "login";
}
session.addAttribute("loggedInUser", customer);
return "redirect:/";
}
By this way, you can access the session values through the request object in both your controller and jsp page.

Display Spring validation error with jQuery plugin

I am able to validate form and display Spring validation error with Spring form tag. Instead of displaying as HTML markup how can I display those errors using jQuery Noty Plugin?
Controller:
#RequestMapping(value = "/Register", method = RequestMethod.POST)
public ModelAndView Registeruser(#ModelAttribute("registerBean") #Valid RegisterBean registerBean, BindingResult bindingResult) {
ModelAndView mv = new ModelAndView();
if (bindingResult.hasErrors()) {
mv.setViewName("index");
mv.addObject(registerBean);
} else {
boolean registered = userservice.RegisterUser(registerBean);
if (registered) {
List<SimpleGrantedAuthority> authList = new ArrayList<SimpleGrantedAuthority>(1);
authList.add(new SimpleGrantedAuthority("ROLE_USER"));
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(registerBean.getEmail(), registerBean.getPassword(), authList);
SecurityContextHolder.getContext().setAuthentication(auth);
mv.setViewName("auth/Home");
} else {
mv.setViewName("index");
}
}
return mv;
}
You didn't mention which view technology you are using. I assume that JSP is in use.
First you should render any error message into a separate hidden container.
In this example product is my modelAttribute. It is completely up to you what you are showing to your users in case of an error. In this example a unordered list of validation type on property and validation message will be shown.
<%# taglib prefix="s" uri="http://www.springframework.org/tags"%>
<s:hasBindErrors name="product">
<div id="error-noty" style="display:none;">
<h3>You have errors in your input!</h3>
<ul>
<c:forEach items="${errors.fieldErrors}" var="error">
<li>${error.codes[1]} ${error.defaultMessage}</li>
</c:forEach>
</ul>
</div>
</s:hasBindErrors>
Then you should initialize noty only if a container with the selector #error-noty could be found in the page.
Hand over the html from the hidden container to noty and you're done.
<script>
var errors = $('#error-noty');
if(errors.html()) {
noty({text: errors.html()});
}
</script>
A working example can be found here.

Is it possible to have a spring model object as the value of spring form?

I basically have the following jsp which retrieves the advertisement objects which came with the spring model advertisement list ${myAdverts}.
And I would like that when one of those is clicked, a post request is submitted back to my controller but with an instance of the advertisement object. Is that somehow possible?
here is my JSP code:
<xc:forEach var="advertisement" items="${myAdverts}" varStatus="stats">
<li>
<a class="furtherinfo-link" onclick="javascript:submitJoin(${stats.count})" >${advertisement.getName()}</a>
</li>
</xc:forEach>
<form:form id="myform" method="POST" action="form_submit.html" commandName="myForm" name="MyForm">
<form:input id="advertisementObj" path="advertisementObj" type="hidden"/>
</form:form>
here is my attempt to send the post back with javascript inspired by the handling of autopopulating lists in spring MVC and javascript:
javascript code
<script src="js/webmenu_nav.js"></script>
<script type="text/javascript">
function submitJoin(position){
$('#advertisementObj').val("myAdverts["+position+"]");
document.MyForm.submit();
}
</script>
The current behavior of that code is that I always get an empty advertisementObj on my post method in my Controller object.
The controller object is very simple, but just in case here it is part of its code:
#Controller
public class MyController {
#RequestMapping(value="/show_advertisements.html",method = RequestMethod.GET)
public ModelAndView showAdv(#RequestParam(value="response", required=false) String incomingResponse) {
Map<String, Object> model = new HashMap<String, Object>();
model.put("response", incomingResponse);
List<AdvertisementRecord> adverts = methodThatReturnsList();
model.put("myAdverts", adverts);
MyForm jform = new MyForm();
model.put("myForm", jform);
return new ModelAndView("show_advertisements", model) ;
}
#RequestMapping(value = "/form_submit.html", method = RequestMethod.POST)
public ModelAndView formSubmit(MyForm myForm, BindingResult result, Map model){
if(null != myForm.getAdvertisement())
return showPage("adver " + myForm.getAdvertisement().getId());
else
return showPage("null advertisement on join");
}
}
Solution!!
snippets of the solution code
JSP code:
<xc:forEach var="advertisement" items="${myAdverts}" varStatus="stats">
<li>
<a class="furtherinfo-link" onclick="javascript:submitForm(${stats.count})" >${advertisement.getName()}</a>
</li>
</xc:forEach>
<form:form method="POST" id="theForm" action="form_submit.html" modelAttribute="myAdverts" name="MyForm">
</form:form>
javascript:
<script src="js/webmenu_nav.js"></script>
<script type="text/javascript">
function submitForm(position){
$('#theForm').attr("action","form_submit.html?position="+position);
document.MyForm.submit();
}
</script>
</head>
controller:
#Controller
#SessionAttributes("myAdverts")
public class MyController {
#RequestMapping(value="/show_advertisements.html",method = RequestMethod.GET)
public ModelAndView showAdv(#RequestParam(value="response", required=false) String incomingResponse) {
Map<String, Object> model = new HashMap<String, Object>();
model.put("response", incomingResponse);
List<AdvertisementRecord> adverts = methodThatReturnsList();
model.put("myAdverts", adverts);
//MyForm jform = new MyForm();
//model.put("myForm", jform);
return new ModelAndView("show_advertisements", model) ;
}
#RequestMapping(value = "/form_submit.html", method = RequestMethod.POST)
public ModelAndView formSubmit(#RequestParam("position") final int position, #ModelAttribute("adverts") #Valid List<AdvertisementRecord> adverts, BindingResult result, Map model){
if(null != adverts && null != adverts.get(position))
return showPage("adver " + adverts.get(position).getId());
else
return showPage("null advertisement ");
}
}
Be aware on the code above, that it is important to have the request param coming first in the signature as Im calling "form_submit.html?position="+position"
objects you put in your model are only there for the current request by default. It means your myAdverts list is not there any more in the second request (i.e. the POST request). However you can use #SessionAttribute annotation to tell spring mvc to store objects in the http-session, so you can access them in further requests.
your controller could look like this:
#Controller
#SessionAttributes("myAdverts")
public class MyController {
#RequestMapping(value="...", method=RequestMethod.GET)
public void get(ModelMap model){
List myAdverts = // get your list of adverts.
model.put("myAdverts", myAdverts)
}
#RequestMapping(value="...", method=RequestMethod.POST)
public void post(#RequestParam("position") final int position, #ModelAttribute("myAdverts") List myAdverts,SessionStatus sessionStatus){
myAdverts.get(position);
// ...
// tell spring to remove myAdverts from session
sessionStatus.setComplete();
}
}
for more information on #SessionAttribute take a look here.
If advertisements have some kind of unique id and stored in a DAO(or there's another way to get an Advertisement from id), you can implement a converter that will take String argument and converts it back to the Advertisement
public class StringToAdvertisementConverter implements Converter<String, Advertisement> {
private AdvertisementRepository advertisementRepository
#Autowired
public setAdvertisementRepository(AdvertisementRepository repository){
this.advertisementRepositort = repository;
}
#Override
public Advertisement convert(String id) {
return advertisementRepository.lookup(id);
}
}
after registering converter in the conversion service
<mvc:annotation-driven conversion-service="conversionService"/>
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="my.StringToAdvertisementConverter"/>
</set>
</property>
your controller will be able to accept Advertisement class as a parameter of the #RequestParam and similar annotations:
#RequestMapping(method = RequestMethod.POST, value = "/SomeMapping")
public String handleSomething(#RequestParam(required = false) Advertisement advert,
ModelMap model) {}
As an alternative, you can achieve the same results with PropertyEditors, there's a good question on topic with a lot of links to the Spring documentation.

Categories