Spring MVC how to display data from database into a table - java

I am very new with SPRING MVC so really I dont know much about it as of the moment. I want to display all the fields in the database in a table view how do I do this?
in my controller
#RequestMapping(value = "task", method = RequestMethod.GET)
public String taskList(Map<String, Object> model) {
model.put("task", taskRepository.findAll());
return "/tasks/list";
}
my jsp:
<%#include file="/WEB-INF/views/includes/header.jsp"%>
<h4 class="form-header">${title}</h4>
<div class="forms col-md-12 bounceInDown mainContent" data-wow-delay="0.2s">
<table class="table table-striped">
<thead>
<tr>
<th>Task ID</th>
<th>Task Name</th>
<th>Task Description</th>
</tr>
</thead>
<tbody>
<c:if test="${empty task}">
<tr>
<td colspan="8">No task to Display</td>
</tr>
</c:if>
<c:if test="${not empty task}">
<c:forEach items="${tasks}" var="task">
<tr class="">
<td>${task.taskid}</td>
<td>${task.taskName}</td>
<td>${task.taskDescription}</td>
<td>
<fmt:message key="task.list.status.text.${task.status}" />
</td>
</tr>
</c:forEach>
</c:if>
</tbody>
</table>
</div>
<%#include file="/WEB-INF/views/includes/footer.jsp"%>
i dont have anything inside my taskRepository atm

For the starters:
#RequestMapping(value = "task", method = RequestMethod.GET)
public String taskList(Map<String, Object> model) {
model.put("task", taskRepository.findAll());
return "/tasks/list";
}
You should return some object you have created instead of String value. Let's asume you want to transfer two fields to you page lets name them field1 and field2. Now create your Data Transfer Object:
public class MyEntityDto{
private String filed1;
private String field2;
//Getter and setter method
.
.
.
}
Now your controller should look something like this:
#Autowired
SomeSevice someService;
#RequestMapping(value = "task", method = RequestMethod.GET)
#ResponseBody
public List<MyEntityDto> taskList(Map<String, Object> model) {
List<MyEntityDto> dtoList = someService.findALl();
return dtoList;
}
Your service from the other hand should look something like this:
#Service
public class SomeService(){
#Autowired
TaskRepository taskRepository;
public List<MyEntityDto> findAll(){
return assemblyTasks(taskRepository.findAll());//TODO implement method assemblyTasks
}
}
Notice that I put your repository usage into the service.This is the way it supposed to be done. You should use services in order to fetch data from your database and than you want to return your data using specificlly design for that purpose object - Data Transfer Object.
I leave the implementation of assemblyTask method to you. What you need to do there is to assign fields you want to pass from entity to view through your dto object. Generally you would want to have an assembler class for every DTO object but for the sake of simplicity I introduced the idea by using method. If you want to read more about DTO, view this post:
getting-value-of-invalid-field-after-methodargumentnotvalidexception
If you are completely new to the Spring world I recommend also find some basics web tutorials, for example here:
gonetoseries

Related

spring thymeleaf error EL1008E Property or field cannot be found on object of type 'LiveDataController$LiveDataSet' maybe not public or not valid?

im using thymeleaf to pass index.html to model attribute containing LiveDataSet Class. but i keep encountering this error.
***org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'LiveDataSet' cannot be found on object of type 'com.ex.excom.controller.LiveDataController$LiveDataSet' - maybe not public or not valid?***
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:217)
PropertyOrFieldReference.java:217
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:104)
PropertyOrFieldReference.java:104
at org.springframework.expression.spel.ast.PropertyOrFieldReference.access$000(PropertyOrFieldReference.java:51)
PropertyOrFieldReference.java:51
at org.springframework.expression.spel.ast.PropertyOrFieldReference$AccessorLValue.getValue(PropertyOrFieldReference.java:406)
PropertyOrFieldReference.java:406
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:90)
CompoundExpression.java:90
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:109)
SpelNodeImpl.java:109
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:328)
SpelExpression.java:328
at org.thymeleaf.spring5.expression.SPELVariableExpressionEvaluator.evaluate(SPELVariableExpressionEvaluator.java:263)
SPELVariableExpressionEvaluator.java:263
at org.thymeleaf.standard.expression.VariableExpression.executeVariableExpression(VariableExpression.java:166)
VariableExpression.java:166
at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:66)
SimpleExpression.java:66
LiveDataController
#RestController
#Controller
public class LiveDataController extends BaseController
{
public class LiveDataSet
{
String getActive;
String getApparent;
String getCurrent;
String getEnergy;
}
public LiveDataSet getLiveDatas(){
...
LiveDataSet liveDatas = new LiveDataSet();
liveDatas.getCurrent = "1234"
liveDatas.getEnergy = "92.1"
...
return liveDatas
}
}
IndexController
#RequestMapping("/")
#PreAuthorize("hasAnyAuthority('ROLE_USER','ROLE_ADMIN')")
public String index(Model model, HttpSession session)
{
LiveDataSet liveData = liveDataController.getLiveDatas();
Optional<LiveDataSet> listOptLiveData = Optional.of(liveData);
listOptLiveData.ifPresent(LiveDataSet -> model.addAttribute("liveData", liveData));
return "index";
}
index.html
<tr th:each="row : ${liveData}">
<td th:text="${row.LiveDataSet}"></td>
</tr>
how i can handle this error.. data does exist, but i can even see the data in the view.
Thank you for reading this.
liveData that you are sending to view is an instance of LiveDataSet. In the view you are accessing it as ${row.LiveDataSet}. It doesn't make sense. There isn't any LiveDataSet field in your LiveDataSet! That's why you are getting this error.
You should access the attrs of the Object row (that is an instance of that LiveDataSet i belive)
<thead>
<tr>
<td>Col1</td>
<td>Col2</td>
<td>Col3</td>
</tr>
</thead>
<tbody>
<tr th:each="row : ${liveData}">
<td th:text="${row.attr1}"></td>
<td th:text="${row.attr2}"></td>
<td th:text="${row.attr3}"></td>
</tr>
</tbdoy>
[[${liveData}]]
public class LiveDataSet
{
String getActive; -> dActive;
String getApparent; -> dApparent;
String getCurrent; -> dCurrent;
String getEnergy; -> dEnergy
}
the problem is, variable naming. if i declare variable get + Active , it returns get, property so this cause java variable detect malfunction so i changed variable names and it safely returns value.
I encountered a similar issue and in the long run i realised i didn't have a getter/setter for them in their parent class (another downside of not using lombok). After the getter setter and renaming, it worked. Perhaps you should look into that.

Is it possible to paginate in jsp with JpaRepository<T, I>

I'm new to Spring boot,
I have a question that, is it possible to paginate table in JSP with JpaRepository<T, I>, I've been searching the internet for two days but haven't found one. The Query results were mostly for Thymeleaf, but I don't want to use thymeleaf. I know how to paginate in JSP using Jdbctemplate but for that, I've to write a query and the number of pages manually. I've already written a spring boot & JSP code.
EmployeeRepository:
public interface EmployeeRepository extends JpaRepository<Emp, Integer> {}
EmployeeController:
#Controller
public class EmployeeController {
#Autowired
private EmployeeRepository repo;
#GetMapping("/")
public String showPaginate(Model m, #RequestParam(defaultValue = "0") int page) {
m.addAttribute("data", repo.findAll(new PageRequest(page, 4)));
return "index";
}
}
index.jsp
<table border="2" width="70%" cellpadding="3"
class="table">
<thead class="thead-dark">
<tr align="center">
<th scope="col">Id</th>
<th scope="col">Name</th>
<th scope="col">Designation</th>
<th scope="col">Edit</th>
<th scope="col">Delete</th>
</tr>
</thead>
<c:forEach var="emp" items="${list}">
<tbody>
<tr align="center">
<td>${emp.id}</td>
<td>${emp.name}</td>
<td>${emp.designation}</td>
<td>Edit</td>
<td>Delete</td>
</tr>
</tbody>
</c:forEach>
</table>
<hr>
<!-- Pagination code will come here -->
Yes it is possible. But first you have to make an interface of PagingAndSortingRepository<T, I> repository and a controller and in your case I don't see one, you have to add a attributes of page, size, elements, stc which is returned by PagingAndSortingRepository<T, I> so your jsp page will get to know the attributes of page, etc and you can use it like ${page} to show page number. I am referring to this repository.
Employee Repository:
public interface EmployeeRepository extends PagingAndSortingRepository<Employee, Integer> {}
The PagingAndSortingRepository<T, I> has a findAll(page) method which passes the object according to page data.
Employee Dao:
#Service
public class EmpDao {
#Autowired
private EmpRepository repo;
public Page<Emp> getPage(Pageable pageable){
return repo.findAll(pageable);
}
If you want the object according to page then you have to use Page<T> interface because A page is a sublist of a list of objects. It allows gain information about the position of it in the containing entire list.
#Controller
public class EmpController {
#Autowired
private EmpDao dao;
#RequestMapping("/viewemp")
public String viewemp(Model m, Pageable pageable){
Page<Emp> pages=dao.getPage(pageable);
m.addAttribute("number", pages.getNumber());
m.addAttribute("totalPages", pages.getTotalPages());
m.addAttribute("totalElements", pages.getTotalElements());
m.addAttribute("size", pages.getSize());
m.addAttribute("data",pages.getContent());
return "viewemp";
}
}
The Pageable is an abstract interface for pagination information
getNumber()- Returns the number of the current Slice. Is always non-negative.
getTotalPages()- Returns the number of total pages.
getTotalElements()- Returns the total amount of elements.
getSize()- Returns the size of the Slice.
getContent()- Returns the page content as List.
Jsp page assuming that you already have stored data.:
Just write this in your tables body i.e <tbody>
<tbody id="myTable">
<c:choose>
<c:when test="${data.size() > 0 }">
<c:forEach var="emp" items="${data}">
<tr align="center">
<td>${emp.id}</td>
<td>${emp.name}</td>
<td>${emp.designation}</td>
<td>Edit</td>
<td>Delete</td>
</tr>
</c:forEach>
</c:when>
<c:otherwise>
<tr align="center">
<td colspan="5">No Users available</td>
</tr>
</c:otherwise>
</c:choose>
<c:if test="${data.size() > 0 }">
<div class="panel-footer">
Showing ${number+1} of ${size+1} of ${totalElements}
<ul class="pagination">
<c:forEach begin="0" end="${totalPages-1}" var="page">
<li class="page-item">
${page+1}
</li>
</c:forEach>
</ul>
</div>
</c:if>
</tbody>
and you're good to go..
Hope it helps..
There are some methods that can be determined through this example.
public class StudentRepository {
#PersistenceContext
private EntityManager entityManager;
public List<StudentEntity> listAll() {
Query query = entityManager.createQuery("from StudentEntity");
return query.getResultList();
}
}
Try this: Extend your EmployeeRepository with PagingAndSortingRepository. Then change the findall() method type PageRequest findAll(PageRequest pagerequest).
public interface EmployeeRepository extends PagingAndSortingRepository<Emp, Integer> {
PageRequest<Emp> findAll(PageRequest pagerequest)
}

Thymeleaf display HashMap

It may be a silly qustion, but I still cannot find an answer to it.
My Spring Boot application looks something like this:
Model:
public class Company {
public static final String URL_COMPANY = "http://193.142.112.220:8337/companyList";
private Long iD;
private String companyName;
public static Map<Long, Object> companyMap;
public Long getiD() {
return iD;
}
public void setiD(Long iD) {
this.iD = iD;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
#Override
public String toString() {
return companyName;
}}
Controller:
#Controller
public class UrlController {
#GetMapping("/success")
public String show(Model model) {
HashMap<Long, Object> company = (HashMap<Long, Object>) Company.companyMap;
model.addAttribute("companyID", company);
return "success";
}
View:
<h1>All Companies:</h1>
<table border="1">
<tr>
<th>ID</th>
<th>Name</th>
</tr>
<tr th:each="mapEntry: ${companyID}">
<td th:text="${mapEntry.key}"></td>
<td th:text="${mapEntry.value}"></td>
</tr>
</table>
<a th:href="#{/}">Homepage</a>
</body>
</html>
So my goal is to display a table filled with Company ID's and Names. Even though, my model gets a map, I still can't see it in my browser. The table is empty.
</tr>
<tr th:each="mapEntry: {1=Tire Systems, 2=IT Enterprise, 3=Car Manufacture, 4=Electro Market}">
<td th:text=""></td>
<td th:text=""></td>
</tr>
This is what i get if i check the page source. So I clearly see, that map is loaded, but not displayed.
Moreover, a link with "homepage" does not work, and i am not sure why?
What am I missing? I am trying to fill a table with Companies, and then, using Id's of those companies, show materials attached to company via this ID. Can i use hyperlinks in table for Id's?
So you want to display a map. IF value of your map is a POJO Try something like followings
<tr><th>ID</th><th>Name</th></tr>
<tr th:each="mapEntry : ${companyID}">
<td th:text="${mapEntry.key}">keyvalue</td>
<td th:each="item : ${mapEntry.value}" th:text="${item.FIELD_NAME_OF_YOUR_POJO}">keyvalue</td>
</tr>
This should work. What i tried to show is, it is possible. The iteration depends on your data structure. If you have complex data structure iteration will change accordingly.
If value of your map is a primitive type or java reference type your current code should work. I have executed similar code like your's and it worked without any trouble. Please have a look -
HashMap<Long, Object> company = new HashMap<>();
company.put(1L, "Hello World");
model.addAttribute("companyID", company);
If value of your map is custom java type. Then follow the previous snippet.

How do I pass the dropdown select value to a button click in the controller and search against the value in data base?

here is the controller
#RequestMapping(value = "/submitrule", method = RequestMethod.POST)
public String addruleSerch(#ModelAttribute("SpringWeb") Rule obj2, ModelMap model) {
model.addAttribute("Select", obj2.getId());
System.out.println("********" + obj2.getId());
ruleApi.getRule(obj2.getId());
model.addAttribute("listrule", ruleApi.getRule(obj2.getId()));
return "redirect:/hello";
}
here is the html....
<form action="/CommissionTool/submitrule" method="post">
<table>
<tr>
<td><select name="Select"><c:forEach items="${listRules}" var="rule">
<option value="${rule.id}">
<c:out value="${rule.id}" />
</option>
</c:forEach>
</select>
</td>
<td><input type="submit" onClick="addRow('in_tbl_name')" VALUE="Add New"></td>
</tr>
</table>
</form>
How could i fix this.. please help me
Thanks in Advance...
Well you need to do several changes in your code, but is pretty near.
You need to send the object you want to use as modelAttribute to the view the first time.
In your html you need to say to the form which is the object to render, your model attribute
Create a POST method in your controller to retrieve the object
Lets put all together in this this example. I have a class called RuleForm, which contains an attribute of type Rule.
public class RuleForm {
...
#Getter #Setter //here use lombok, but you could create your getters-setters methods
private Rule rule;
...
}
Now in the controller, into the GET method, we set the view resolver(JSP) and the object we will send to there. In this case an object of type FormRule
#RequestMapping(value = "/submitrule", method = RequestMethod.GET)
public ModelAndView addruleSerch() {
ModelAndView model = new ModelAndView("yourView");
//here you choose the name you will use in your view, is up to you the name to choose
model.addObject("formRule", new FormRule());
return model;
}
Now we need to pick up that object we sent to the view and use it into our form tag.
<form action="/CommissionTool/submitrule" method="post" model="formRule">
...
<select name="rule.id"><c:forEach items="${listRules}" var="rule">
<option value="${rule.id}">
<c:out value="${rule.id}" />
</option>
</c:forEach>
</select>
In this point when we send the form to the Controller, we will send the RuleForm object with a value into rule.id object, then in the controller we have to get that id value and add out business logic.
#RequestMapping(value = "/submitrule", method = RequestMethod.POST)
public String addruleSerch(#ModelAttribute RuleForm ruleForm) {
//Here you will have access to your object
ruleForm.getRule().getId();// rule selected in the form
... your business logic
return "redirect:/someUrl";
}

How to bind spring MVC jsp page to two classes

I have two classes Person and Passport. Passport has foreignkey = personid.
This is my controller
model.addAttribute("personAttribute", new Person());
JSP PAge
<form:form modelAttribute="personAttribute" method="POST" action="${saveUrl}">
<table>
<tr>
<td><form:label path="firstName">First Name:</form:label></td>
<td><form:input path="firstName"/></td>
<td><form:errors path="firstName"/>gfgf</td>
</tr>
<td><form:label path="country_issue">Passport:</form:label></td>
<td><form:input path="country_issue"/></td>
<td><form:errors path="country_issue"/></td>
NOw i want to put country_issue in other passport table.
I don't have that column in Person so how will i bind that in JSP page
Passport has only id , person_id, country_issue field
All you have to do is wrap your form backing objects in a form:
public class MyForm
{
private final Person person;
private final Passport passport;
public MyForm()
{
this.person = new Person();
this.passport = new Passport();
}
public MyForm(Person person, Passport passport)
{
this.person = person;
this.passport = passport;
}
// getters & setters
}
Then in your controller:
model.addAttribute("myForm", new MyForm());
or you could do
model.addAttribute("myForm", new MyForm(personService.findPerson(1), passportService.findPassport(1)));
and in your jsp:
<form:form modelAttribute="myForm" method="POST" action="${saveUrl}">
<table>
<tr>
<td><form:label path="person.firstName">First Name:</form:label></td>
<td><form:input path="person.firstName"/></td>
<td><form:errors path="person.firstName"/>gfgf</td>
</tr>
<tr>
<td><form:label path="passport.country_issue">Passport:</form:label></td>
<td><form:input path="passport.country_issue"/></td>
<td><form:errors path="passport.country_issue"/></td>
<tr/>
</table>
</form>
I would suggest you to create a class that maps your GUI form 1:1 and then write a transformer/validator. This class should ideally be package-private (maybe even inner class) for your GUI element so it doesn't mix with the DAO objects, such as Person or Passport.
UI data is managed best with Classes like TransferObjects are ModelObjects which represent the page data binding requirements. If we do that we can move the concern to the controller to extract out the spring (persistent) objects from the UI object.
If the object is called PassportForm then the method passportForm.person() and passportForm.Passport() should give you the persistent object. In this way we can also eliminate the need for transformer/validator classes and push the behavior into the objects.

Categories

Resources