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.
Related
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)
}
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
I have a Domain:
public class Record {
...
private int STATE;
...
// getters and setters
}
controller:
...
#RequestMapping("recordInsert")
public String insertRecord(#ModelAttribute Record record) {
if (record != null){
recordService.insertRecord(record);}
return "redirect:/recordGetList";
}
JSP page:
<form:form method="POST" action="/recordInsert" modelAttribute="record">
...
<tr>
<td>Enabled :</td>
<td><input type="checkbox" path="STATE" /></td>
</tr>
...
Problem is to bind checkbox to int value. I need set 1 when checkbox is checked and 0 when not checked. I need to use PropertyEditor in my controller
#InitBinder
public void initBinder(WebDataBinder binder)
{
binder.registerCustomEditor(Integer.class, ...);
}
but I don't understand how exactly.
It works for me:
<form:checkbox path="STATE"/>
This question already has answers here:
Repopulate ArrayList from JSP with Struts 2
(3 answers)
Closed 9 years ago.
Does anybody know how to handle this kinda of case in Struts 2 without using any custom converter.
My model definition
1.Booking
public class Booking extends BaseModel{
private String bookingNo;
.....
private List<Part>parts = new ArrayList<Part>();
private List <? extends ToDoItem>toDoItems = new ArrayList< ToDoItem>();
....
}
2.ToDoItem
public class ToDoItem extends BaseModel{
private Integer sequence;
private String bookingNo;
private String serviceCode;...
3.Specified todoitem that inherited from ToDoItem
e.g PDAS
public class PDAS extends ToDoItem{
private Date estPickupTime;
private Date actPickupTime;
private Date estArriAtWarehouseTime;
private Date actArriAtWarehouseTime;...
INSP:
public class INSP extends ToDoItem{
private String confirmOk;
private Date actInspTime;
private List<BookingItem>bookingItems;.....
...(More specified ToDoItem)
Then in html page,The form definition is as following:
PDAS todoitem html
<table class="form-table">
<tr class="row">
<td class="td-label" colspan="2">
<s:label key="INSP" cssStyle="color:blue;"/>
</td>
<td class="td-label">
<s:label key="ToDoItem.status"/>
</td>
<td class="td-field">
<s:property value="booking.toDoItems[1].status"></s:property>
</td>
<td class="td-field" colspan="2">
<s:select list="{'PENDING','COMPLETED','EXCEPTION','CANCELLED'}" labelposition="top"/>
</td>
</tr>
INSP todoitem html
<tr>
<td class="td-label">
<s:label key="ToDoItem.assignedBy"/>
</td>
<td class="td-field">
<s:textfield name="booking.toDoItems[1].assignedBy" cssStyle="width:88%;" value="%{#session.user.userName}"
readonly="true" cssClass="readonly"></s:textfield>
</td>
<td class="td-label">
<s:label key="ToDoItem.assignedTo"/>
</td>
<td class="td-field">
<s:textfield name="booking.toDoItems[1].assignedTo" cssStyle="width:88%;" value="%{#session.user.userName}"
readonly="true" cssClass="readonly"></s:textfield>
</td>
I know the code i pasted in here is a little mass,But please be patient,My problem is when i enter todoitem's fields,e.g PDAS,INSP's field ,then submit the form,the todoitem got in save action is null,e.g when i loop the todoitems and print it in save action,it got following log:
22:23:04,923 INFO BookingAction:100 - Start save booking with
booking:com.chailie.booking.model.booking.Booking#726dad0
22:23:04,925 DEBUG BookingAction:104 - The todoitem is [null]
22:23:04,926 DEBUG BookingAction:104 - The todoitem is [null]
22:23:04,927 DEBUG BookingAction:104 - The todoitem is [null]
22:23:04,928 DEBUG BookingAction:104 - The todoitem is [null]
I know this is because of the Action convert specified todoitem failed,But does anybody could tell me how to fix it?i know maybe i could write a custom converter to convert the List todoitems,But i don't like custom converter,then is there any other way to let struts help me convert these specified ToDoItems?
My problem has solved,i just defined an interceptor to instantiate
List toDoItems with PDAS,INSP etc,then set it to valuestack. as i have instantiated toDoItem,struts would just use this existing toDoItems direct and won't create it any more,then problem solved
i'm generating an html table into a jsp file using struts2. i would like to change values contained into this arraylist, but the behaviour is not what i was expecting...
my flow:
Action.java: generate an arraylist "struct" which contains "n" (for example 5) objects of type MyElem.
private ArrayList<MyElem> struct;
public void setStruct(...) {...}
public ArrayList<MyElem> getStruct() {...}
and the details of MyElem :
private String name;
private String type;
private int length;
private int precision;
private String usage;
private String init;
of course, all getters and setters are declared.
test.jsp :
<s:iterator value="struct" status="elemsStatus">
<tr>
<td><s:textfield name="struct.name" value="%{name}" theme="simple"/></td>
<td><s:textfield name="struct.type" value="%{type}" theme="simple"/></td>
<td><s:textfield name="struct.length" value="%{length}" theme="simple"/></td>
<td><s:textfield name="struct.precision" value="%{precision}" theme="simple"/></td>
<td><s:textfield name="struct.usage" value="%{usage}" theme="simple"/></td>
<td><s:textfield name="struct.init" value="%{init}" theme="simple"/></td>
</tr>
</s:iterator>
then back in Action.java when i iterate on struct, i don't have 5 objects MyElem, but 30 : one with a "name", one with a "type", and so on for every rows...
in fact i would like to have into struct one object MyElem by rows in my html table.
Thanks you !
The correct syntax to set indexed properties is
<s:iterator value="struct" status="elemsStatus">
<tr>
<td><s:textfield name="struct[%{#elemsStatus.index}].name" value="%{name}" theme="simple"/></td>
<td><s:textfield name="struct[%{#elemsStatus.index}].type" value="%{type}" theme="simple"/></td>
<td><s:textfield name="struct[%{#elemsStatus.index}].length" value="%{length}" theme="simple"/></td>
<td><s:textfield name="struct[%{#elemsStatus.index}].precision" value="%{precision}" theme="simple"/></td>
<td><s:textfield name="struct[%{#elemsStatus.index}].usage" value="%{usage}" theme="simple"/></td>
<td><s:textfield name="struct[%{#elemsStatus.index}].init" value="%{init}" theme="simple"/></td>
</tr>
</s:iterator>
Try something like this in your textfield tags:
<s:textfield name="struct[#elemsStatus.index].yourProperty" value="yourValue" theme="simple" />
You should get struct as a list of MyElem, and each of the elements should have all the properties name, type, length, precision, usage and init.