I am writing my first web-application project about rental a cars in java using Spring Boot, Hibernate and MySql.
In my app I want to have smth like sort methods. I made that by add in my view an input where users can type e.g type or model of car. I want to get result of query e.g type='sportcar' and from this result I want to sort data e.g by price DESC or ASC.
Here is my code of view
<body>
<form action="get" method="get">
<div class="form-group col-md-4">
<label for="inputState">Sort by</label>
<select name="sortMethod" id="inputState" class="form-control">
<option value="">Select sort method</option>
<option value="priceDESC">price desc</option>
<option value="priceASC">price asc</option>
</select>
<input type="submit" value="submit"/>
</div>
</form>
<form action="get" method="get">
Type: <input type="text" name="type">
<input type="submit" value="submit"/>
</form>
<form action="get" method="get">
Brand: <input type="text" name="brand"/>
<input type="submit" value="submit"/>
</form>
<form action="get" method="get">
Model: <input type="text" name="model"/>
<input type="submit" value="submit"/>
</form>
Here is my code of Controller
#GetMapping(path = "/get")
public String getAllCars(ModelMap modelMap) {
cars = carRepository.findAll();
modelMap.addAttribute("cars", cars);
return "car";
}
#GetMapping(path = "/get", params = "sortMethod")
public String getAllCars(#RequestParam(defaultValue = "priceASC", required = false) String sortMethod,
ModelMap modelMap) {
String parameterOfSort = "";
String wayOfSort = "";
char c;
for (int i = 0; i < sortMethod.length(); i++) {
c = sortMethod.charAt(i);
if (c >= 64 && c <= 90)
wayOfSort += c;
else if (c >= 97 && c <= 122)
parameterOfSort += c;
}
Sort.Direction sortType = Sort.Direction.valueOf(wayOfSort);
cars = carRepository.findAll(Sort.by(sortType, parameterOfSort));
modelMap.addAttribute("cars", cars);
return "car";
}
#GetMapping(path = "/get", params = "type")
public String getCarsByType(#RequestParam String type, ModelMap modelMap) {
cars = carRepository.findCarByType(type);
modelMap.addAttribute("cars", cars);
return "car";
}
I think that my approach isn't correct. How can I modify my code to get satisfying result and good approach for this situation?
Check the spring jpa doc, JPA support sort, in your case:
public interface CarRepository extend CrudRepository<Car, Long> {
List<Car> findByTypeOrderByPriceDesc(String type); //sportsCar, order by price desc
}
Related
My Student class has list 'Objects'.
public class Student {
private List<Objects> list;
...
}
public class Objects {
private long id;
private String context;
...
}
#GetMapping("signup")
public String showSignUpForm(Model model) {
List<Objects> objectsList = new ArrayList<>();
objectsList.add(new Objects(1, "Math"));
objectsList.add(new Objects(2, "Phys"));
objectsList.add(new Objects(3, "Chem"));
objectsList.add(new Objects(4, "Geom"));
model.addAttribute("objects", objectsList);
model.addAttribute("student", new Student());
return "add-student";
}
#PostMapping("add")
public String addStudent(Student student, BindingResult result, Model model) {
if (result.hasErrors()) {
return "add-student";
}
return "redirect:list";
}
<form action="#" th:action="#{/students/add}" th:object="${student}" method="post">
<div class="group">
<div th:each="obj : ${objects}">
<input id="check" type="checkbox" th:field="*{list}" th:value="${obj}"/>
<label for="check" th:text="${obj.getContext()}"></label>
</div>
<div class="col-md-6">
<input type="submit" class="btn btn-primary" value="Submit">
</div>
</div>
</form>
So I want to add selected objects to student.list but I get this error:
Failed to convert property value of type 'java.lang.String[]' to required type 'java.util.List' for property 'list'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'example.Objects' for property 'list[0]': no matching editors or conversion strategy found
How to do it right?
First of all, if you want to work with list you have to do it by index. So if you want to bind a list you have to do like below.
#GetMapping("signup")
public String showSignUpForm(Model model) {
List<Objects> objectsList = new ArrayList<>();
objectsList.add(new Objects(1, "Math"));
objectsList.add(new Objects(2, "Phys"));
objectsList.add(new Objects(3, "Chem"));
objectsList.add(new Objects(4, "Geom"));
List<Objects> emptyList = new ArrayList<>();
Student student = new Student();
student.addList(emptyList);
model.addAttribute("objects", objectsList);
model.addAttribute("student", student);
return "add-student";
}
<form action="#" th:action="#{/students/add}" th:object="${student}" method="post">
<div class="group">
<div th:each="obj,iterator : ${objects}">
<input id="check" type="text" th:field="*{list[${iterator.index}].id}" th:value="${obj.id}"/>
<input type="text" th:field="*{list[${iterator.index}].context}" th:value="${obj.context}"/>
</div>
<div class="col-md-6">
<input type="submit" class="btn btn-primary" value="Submit">
</div>
</div>
</form>
Secondly, if you want to do select and add then you have to use javascript. You have to track the index of the list and bind the value separately (id and context) in the correct index. You have to also consider to remove object from the list for unselection.
i am new to spEL and i want to use the "SELECT COUNT(*) FROM Exams;" query with JPQL or spEL to check if the record in the database is less than 6(six);
This is what i have. I can not really figure out how to go about it because i am not able to use the #Query annotation in the controller.
//Problem writing spEL
<div class="form-group" th:if="${exams.count(*) < 6}" >
<form method="post" th:object="${newExam}" th:action="#{/exams}" class="inline new-item">
<label class="form-control input-sm"><input type="text" th:field="*{indexNumber}" placeholder="Index Number" autocomplete="off"/></label>
<select th:field="*{grade}" class="form-control input-sm">
<option value="" disabled="disabled">[Select Grade]</option>
<option th:each="grade : ${grades}" th:value="${grade.values}" th:text="${grade.name}">Grade</option>
</select>
<label class="form-control input-sm"><input type="text" th:field="*{courseOffered}" placeholder="CourseOffered" autocomplete="off"/></label>
<label class="form-control input-sm"><input type="text" th:field="*{examType}" placeholder="ExamType" autocomplete="off"/></label>
<label class="form-control input-sm"><input type="text" th:field="*{subject}" placeholder="Subject" autocomplete="off"/></label>
<label class="form-control input-sm datepicker"><input type="text" th:field="*{gradeYear}" placeholder="ExamYear" autocomplete="off"/></label>
<button type="submit" class="btn btn-primary">Add</button>
</form>
#Controller
public class ExamsController {
#Autowired
private ExamService examService;
#Autowired
private UserService userService;
#RequestMapping(path = "/cert_prog")
public String examsList(Model model){
Iterable<Exams> exams = examService.findAll();
model.addAttribute("exams", exams);
model.addAttribute("newExam", new Exams());
model.addAttribute("grades", Grade.values());
return "cert_prog";
}
#RequestMapping(path = "/mark", method = RequestMethod.POST)
public String toggleComplete(#RequestParam Long id) {
Exams exams = examService.findOne(id);
examService.toggleComplete(id);
return "redirect:/cert_prog";
}
#RequestMapping(path = "/exams", method = RequestMethod.POST)
public String addTask(#ModelAttribute Exams exams, Principal principal){
//User user = userService.findByUsername(principal.getName());
User user = (User)((UsernamePasswordAuthenticationToken)principal).getPrincipal();
exams.setUser(user);
//examService.increment(exams);
examService.save(exams);
return "redirect:/cert_prog";
}
}
#Service
public class ExamServiceImpl implements ExamService {
#Autowired
private ExamsDao examsDao;
#Override
public Iterable<Exams> findAll() {
return examsDao.findAll();
}
#Override
public Exams findOne(Long id) {
return examsDao.findOne(id);
}
#Override
public void toggleComplete(Long id) {
Exams exams = examsDao.findOne(id);
exams.setComplete(!exams.isComplete());
examsDao.save(exams);
}
#Override
public void save(Exams exams) {
examsDao.save(exams);
}
#Override
public void increment(Exams exams) {
//exams.setCounter(exams.getCounter() + 1);
}
You don't need to query the DB again. Exams is already an iterable collection of all exam records, isn't it? Try
<div class="form-group" th:if="${exams.size() < 6}" >
As long as the underlying class of the Iterable object implements the size() method, thymeleaf should be able to find and call it. Otherwise you'll need to cast to a collection that does implement size before you add the object to the model.
I have Spring MVC application with this controller method.
#RequestMapping(value = "/saveMe", method = RequestMethod.POST)
public #ResponseBody String saveMe(#RequestParam(value = "clientId") String strClientId,#RequestParam(value = "clientName") String strClientName,#RequestParam(value = "custBaseNo") String strCustBaseNo, #RequestParam(value = "category") String strCategory,#RequestParam(value = "clientCpt") String strClientCpt, #RequestParam(value = "pbk") String strPbk,#RequestParam(value = "prk") String strPrk,#RequestParam(value = "fileAct") int intFileAct, #RequestParam(value = "b2b") int intB2b,#RequestParam(value = "collection") int intCollection, #RequestParam(value = "primAccNo") String strPrimAccNo,#RequestParam(value = "accFromAcct") String strAccFromAcct,#RequestParam(value = "accToAcct") String strAccToAcct,#RequestParam(value = "intCount") int intCount,#RequestParam(value = "productId") String strProductId,HttpServletRequest request){
String strStatus ="";
System.out.println("strClientId is :::"+strClientId);
strStatus = sabService.saveDetails(strClientId,strClientName,strCustBaseNo,strCategory,strClientCpt,strPbk,strPrk,intFileAct,intB2b,intCollection,strPrimAccNo,strAccFromAcct,strAccToAcct,intCount,strProductId);
String[] strChkService = new String[intCount];
String[] strAccNO = new String[intCount];
int[] intTrnsLimit = new int[intCount];
String[] strProtcl = new String[intCount];
for(int j=1;j<=intCount;j++){
strChkService[j] = request.getParameter("chkService"+j)==null?"":request.getParameter("chkService"+j);
strAccNO[j] = request.getParameter("accountNo"+j)==null?"":request.getParameter("accountNo"+j);
intTrnsLimit[j] = Integer.parseInt(request.getParameter("transactionLimit"+j)==null?"0":request.getParameter("transactionLimit"+j));
strProtcl[j] = request.getParameter("protocol"+j)==null?"":request.getParameter("protocol"+j);
strStatus = sabService.saveServices(strClientId,strProductId,strChkService[j],strAccNO[j],intTrnsLimit[j], strProtcl[j] );
}
return "success";
}
While submitting the form I'm getting this error.
HTTP Status 400 - Required String parameter 'clientId' is not present
Can anyone please help me...Thanks in advance...
jquery-
$("#client-maint-form").attr("action","sabb/saveMe");
$("#client-maint-form").submit();
form-
<form id="client-maint-form" class="form-horizontal" enctype="multipart/form-data" method="POST">
i have also tried with GET ...but getting this error
HTTP Status 405 - Request method 'GET' not supported
Here is the form
<form id="client-maint-form" class="form-horizontal" enctype="multipart/form-data" method="POST">
<div class="box-body">
<div class="form-group">
<label for="client-id" class="col-sm-3 control-label">Client Id<a style="color: red">*</a></label>
<div class="col-xs-4">
<input class="form-control" name="clientId" id="client-id" required="true" placeholder="Client Id" type="text">
</div>
</div>
<div class="form-group" id="password-div-add-update">
<label for="client-name" class="col-sm-3 control-label">Client Name<a style="color: red">*</a></label>
<div class="col-xs-4">
<input class="form-control" name="clientName" id="client-name" required="true" placeholder="Client Name" type="text">
</div>
</div>
</form>
Following are my POJO, Action, and JSP page.
For single instance of Expense I am getting proper input.
I would like to use ModelDriven to fetch multiple instance of Expense from JSP page.
For that I have created multiple <div class="Expense">...</div>, but I dont know what changes should I made in Action class.
How to achieve this?
Pojo Class:
public class Expense implements java.io.Serializable {
private Long id;
private Client client;
private String param;
private BigDecimal value;
private Date dt;
private Date adddate;
//getter and setter
}
Action Class:
public class ExpenxeAction extends ActionSupport implements ModelDriven<Expense> {
Expense e = new Expense();
ExpenseDAO dao = new ExpenseDAO();
private LoginCheck lc = null;
private List<Expense> expenseList = new ArrayList<Expense>();
public String insertExpense() {
dao.insert(e);
return SUCCESS;
}
#Override
public Expense getModel() {
return e;
}
}
JSP page:
<div class="Expense">
<label>Expense Type</label>
<input type="text" name="param" id="param"/>
<label>Amount</label>
<input type="text" name="value" class="form-control" id="value"/>
<label>Date</label>
<input type="text" name="dt" class="form-control" id="dt"/>
</div>
You should create a getter for expenseList
public List<Expense> getExpenseList() {
return expenseList;
}
in the JSP use indexed property names
<s:iterator value="expenseList" status="stat">
<div class="Expense">
<label>Expense Type</label>
<s:textfield name="expenseList[%{#stat.index}].param" id="param"/>
<label>Amount</label>
<s:textfield name="expenseList[%{#stat.index}].value" class="form-control" id="value"/>
<label>Date</label>
<s:textfield name="expenseList[%{#stat.index}].dt" class="form-control" id="dt"/>
</div>
</s:iterator>
To fetch array list of Expense objects in action class you need to make the following changes to your code.
First you have to change ModelDriven<Expense> to ModelDriven<List<Expense>> and remove Expense e = new Expense();, if you wish. So, finally your action class should look like this.
public class ExpenxeAction extends ActionSupport implements ModelDriven<List<Expense>>, Preparable {
ExpenseDAO dao = new ExpenseDAO();
private LoginCheck lc = null;
private List<Expense> expenseList = new ArrayList<Expense>();
public String insertExpense() {
for (Expense e : expenseList) { //loop to iterate over each elements
dao.insert(e);
}
return SUCCESS;
}
public List<Expense> getExpenseList() {
return expenseList;
}
public void setExpenseList(List<Expense> expenseList) {
this.expenseList = expenseList;
}
#Override
public void prepare() throws Exception {
expenseList = new ArrayList<Expense>();
}
#Override
public List<Expense> getModel() {
return expenseList;
}
}
Now, you have to make changes to your jsp page.
<div class="Expense">
<label>Expense Type</label>
<input type="text" name="model[0].param" id="param"/>
<label>Amount</label>
<input type="text" name="model[0].value" class="form-control" id="value"/>
<label>Date</label>
<input type="text" name="model[0].dt" class="form-control" id="dt"/>
<label>Expense Type</label>
<input type="text" name="model[1].param" id="param"/>
<label>Amount</label>
<input type="text" name="model[1].value" class="form-control" id="value"/>
<label>Date</label>
<input type="text" name="model[1].dt" class="form-control" id="dt"/>
<label>Expense Type</label>
<input type="text" name="model[2].param" id="param"/>
<label>Amount</label>
<input type="text" name="model[2].value" class="form-control" id="value"/>
<label>Date</label>
<input type="text" name="model[2].dt" class="form-control" id="dt"/>
</div>
You will notice that in the jsp code we have mentioned
model[index].<pojo_member_variable_name> instead of specifying of
lstExp[index].<pojo_member_variable_name>
This is because now we want struts2 to set the values directly into these member variables. So we have mentioned model[index].<pojo__member_variable_name> so that struts2 should automatically set the value into the list. Here in the above code we are creating list of 3 Expense Object. If you need to insert more values then just increment the index and set the values and remaining will be done by struts2 for you.
#ModelAttribute annotation(Spring) allows for html to create an object.
For example there is a class
class Vasya{
int id;
String name;
//set get
}
and html form
<form action='path'>
<input type='text' name = 'id'/>
<input type='text' name = 'name'/>
<input type='submit'/>
</form>
#controller method:
#RequestMapping("/path")
public String processSkill( #ModelAttribute Vasya vasya) {...}
here it works.
Question:
how can I write html form using *checkbox*es for id and name that my controller method works?
Dont understand how to pass id using checkbox, but you can pass checkbox value that way:
#RequestMapping(value = "/test", method = RequestMethod.POST)
public String form(#RequestParam(required = false) Integer check) {
if(check != null) { // if checkbox is not selected it is null
System.out.println(check);
}
return "your-view";
}
jsp:
<form action="${home}/test" method="POST">
<input type="checkbox" value="1" name="check" />
<input type="submit" />
</form>