unable to receive parameters in POST request, Spring - java - java

I am very new to java so may be this question seems duplicate, BUT i spent one day already on this issue. So I need solution now, or any guideline.
I am trying to receive post parameters from front end through web service BUT I am unable to receive any values.
This is my HTML FORM :
<form role="form" id="" name="" method="post">
<div class="form-group associateTypeFormGroup">
<label class="control-label">Associate Type : </label>
<select class="form-control associateType" id="associateType" name="associateType">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
</div>
<div class="form-group datasetNameFormGroup">
<label class="control-label">Dataset Name : </label>
<input type="text" class="form-control" name="datasetName" id="datasetName" />
</div>
<div class="form-group daterangeFormGroup">
<label class="control-label">Date Range : </label>
<input type="text" class="form-control daterange" name="daterange" id="daterange" data-time-picker="true" data-time-picker-increment="5" data-format="YYYY-MM-DD h:mm:ss A">
</div>
<div class="form-group listaFormGroup">
<label class="control-label">List A : </label>
<textarea class="form-control" id="lista" name="lista"></textarea>
</div>
<div class="form-group listbFormGroup">
<label class="control-label">List B : </label>
<textarea class="form-control" id="listb" name="listb"></textarea>
</div>
<div class="form-group minimumCallingFormGroup" style="display:none;">
<label class="control-label">Minimum Calling : </label>
<select class="form-control" id="minimumCalling" name="minimumCalling">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
</div>
<div class="form-group">
<input type="button" class="btn btn-success" value="SUBMIT" onclick="return get_values(this);" />
</div>
</form>
JS function to call web service :
function get_values() {
associateType = $("#associateType").find(":selected").val();
datasetName = $("#datasetName").val();
startdate = $('#daterange').data('daterangepicker').startDate.toISOString().split('.')[0] + "Z";
enddate = $('#daterange').data('daterangepicker').endDate.toISOString().split('.')[0] + "Z";
if ($("#lista").val() != "")
lista = '\'' + $("#lista").val().split(',').join('\',\'') + '\'';
if ($("#listb").val() != "")
listb = '\'' + $("#listb").val().split(',').join('\',\'') + '\'';
minimumCalling = $('#minimumCalling').find(":selected").val();
var cdrReqParams = {};
cdrReqParams.associateType = associateType;
cdrReqParams.datasetName = datasetName;
cdrReqParams.fromDate = startdate;
cdrReqParams.toDate = enddate;
cdrReqParams.listA = lista;
cdrReqParams.listB = listb;
cdrReqParams.minimumCalling = minimumCalling;
var jsonStr = JSON.stringify(cdrReqParams);
API.call("save_associate.json", 'POST', function(data) {
console.log(data);
}, function(error) {
console.log(error);
}, jsonStr);
}
My controller
#RestController
public class AssociateController {
#RequestMapping(value = "/associate", method = RequestMethod.GET)
public ModelAndView associateIndex() {
ModelAndView mav = null;
mav = new ModelAndView("associate.html");
return mav;
}
#Layout(Layout.NONE)
#RequestMapping(value = "/save_associate.json", method = RequestMethod.POST)
public #ResponseBody AjaxResponseBody save_associate(HttpServletRequest request, Model model) throws Exception {
AssociateParams params = new AssociateParams();
try {
params.setAssociateType(request.getParameter("associateType"));
params.setDatasetName(request.getParameter("datasetName"));
params.setFromDate(request.getParameter("fromDate"));
params.setToDate(request.getParameter("toDate"));
params.setListA(request.getParameter("listA"));
params.setListB(request.getParameter("listB"));
params.setMinimumCalling(request.getParameter("minimumCalling"));
System.out.println("+++ Associate Controller +++");
System.out.println(params.getAssociateType());
System.out.println(params.getDatasetName());
System.out.println(params.getFromDate());
System.out.println(params.getToDate());
System.out.println(params.getListA());
System.out.println(params.getAssociateType());
System.out.println(params.getAssociateType());
} catch(Exception e){
e.printStackTrace();
}
finally{
//dbHelper.closeDBConnection(conn);
}
return null;
}
}
Associateparams.java
public class AssociateParams {
private String associateType;
private String datasetName;
private String fromDate;
private String toDate;
private String listA;
private String listB;
private String minimumCalling;
public String getAssociateType() {
return associateType;
}
public void setAssociateType(String associateType) {
this.associateType = associateType;
}
public String getDatasetName() {
return datasetName;
}
public void setDatasetName(String datasetName) {
this.datasetName = datasetName;
}
public String getFromDate() {
return fromDate;
}
public void setFromDate(String fromDate) {
this.fromDate = fromDate;
}
public String getToDate() {
return toDate;
}
public void setToDate(String toDate) {
this.toDate = toDate;
}
public String getListA() {
return listA;
}
public void setListA(String listA) {
this.listA = listA;
}
public String getListB() {
return listB;
}
public void setListB(String listB) {
this.listB = listB;
}
public String getMinimumCalling() {
return minimumCalling;
}
public void setMinimumCalling(String minimumCalling) {
this.minimumCalling = minimumCalling;
}
}
I receive null in all post parameters, any idea what I am doing wrong here ?
I have seen the network tab on browser and service is sending all the required data correctly
API.CALL fUNCTION
var API = {
call:function(url,type,successcallback,errorCallback,data){
var data = (!!data) ? data : {};
var callback = (!!callback) ? callback : function(){};
$.ajax({
contentType : "application/json",
dataType: "json",
//crossDomain: true,
xhrFields: { withCredentials: true },
url: url,
data:data,
type:type,
success:successcallback,
error:errorCallback
});
}
}

Spring controller code
#RequestMapping(value = "/save_associate.json", method = RequestMethod.POST)
public #ResponseBody String save_associate(#RequestBody AssociateParams associateParams , HttpServletRequest request) {
String asscociateType = associateParams.getAssociateType();
// For other parameters use as abaove
// your logic next
}

Related

How do I fix this error message: xhr.js:178 GET http://localhost:8080/jpa/users/undefined/accounts/undefined?

My app is in React, Node, Java, and uses a mySQL db. The username & password are posted & retrieved from the db using node. Accounts are supposed to be retrieved from the db using Java. I'm needing assistance in trying to resolve this error: xhr.js:178 GET http://localhost:8080/jpa/users/undefined/accounts/undefined.
Here is a portion of my login component:
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [loginStatus, setLoginStatus] = useState("");
const history = useHistory();
const loginClicked = () => {
Axios.post("http://localhost:3000/login", {
username: username,
password: password,
}).then((response) => {
if (response.data.message) {
setLoginStatus(response.data.message)
console.log(response.data.message)
} else {
setLoginStatus(response.data[0].username)
AuthenticationService.registerSuccessfulLogin(
setUsername({ username }),
setPassword({ password })
);
history.push(`/welcome/${username}`);
console.log(response.data[0].username)
}
});
};
Here is my api code in React:
import axios from "axios";
import { JPA_API_URL } from "../Constants";
class AccountDataService {
retrieveAllAccounts(name) {
return axios.get(`${JPA_API_URL}/users/${name}/accounts`);
}
retrieveAccount(name, id) {
return axios.get(`${JPA_API_URL}/users/${name}/accounts/${id}`);
}
deleteAccount(name, id) {
return axios.delete(`${JPA_API_URL}/users/${name}/accounts/${id}`);
}
updateAccount(name, id, account) {
return axios.put(`${JPA_API_URL}/users/${name}/accounts/${id}`, account);
}
createAccount(name, account) {
return axios.post(`${JPA_API_URL}/users/${name}/accounts/`, account);
}
}
export default new AccountDataService();
Constants.js:
export const API_URL = "http://localhost:8080";
export const JPA_API_URL = `${API_URL}/jpa`
Here is where AccountDataService is called & used:
import React, { Component } from "react";
import moment from "moment";
import { Formik, Form, Field, ErrorMessage } from "formik";
import AccountDataService from "../../api/AccountDataService.js";
import AuthenticationService from
"../../components/authentication/AuthenticationService.js";
class Accounts extends Component {
constructor(props) {
super(props);
this.state = {
id: this.props.match.params.id,
accountName: "",
deposits: "",
asOfDate: moment.utc(new Date()).format("YYYY-MM-DD"),
};
this.onSubmit = this.onSubmit.bind(this);
this.validate = this.validate.bind(this);
}
componentDidMount() {
if (this.state.id === -1) {
return;
}
let username = AuthenticationService.getLoggedInUserName();
AccountDataService.retrieveAccount(username, this.state.id).then(
(response) =>
this.setState({
accountName: response.data.accountName,
deposits: response.data.deposits,
asOfDate: moment.utc(response.data.asOfDate).format("YYYY-MM-DD"),
})
);
}
validate(values) {
let errors = {};
if (!values.accountName) {
errors.accountName = "Enter an account name";
} else if (values.accountName.length < 3) {
errors.accountName = "Account name must be at least 3 characters";
}
if (!values.deposits) {
errors.deposits = "Enter a balance";
}
if (!moment(values.asOfDate).isValid()) {
errors.asOfDate = "Select a date";
}
return errors;
}
onSubmit(values) {
let username = AuthenticationService.getLoggedInUserName();
let account = {
id: this.state.id,
accountName: values.accountName,
deposits: values.deposits,
asOfDate: values.asOfDate,
};
if (this.state.id === -1) {
AccountDataService.createAccount(username, account).then(() =>
this.props.history.push("/accounts")
);
} else {
AccountDataService.updateAccount(
username,
this.state.id,
account
).then(() => this.props.history.push("/accounts"));
}
console.log(values);
}
render() {
let { accountName, deposits, asOfDate } = this.state;
return (
<div>
<h1>Account Updates/Additions</h1>
<div className="container">
<Formik
initialValues={{ accountName, deposits, asOfDate }}
onSubmit={this.onSubmit}
validateOnChange={false}
validateOnBlur={false}
validate={this.validate}
enableReinitialize={true}
>
{(props) => (
<Form>
<ErrorMessage
name="accountName"
component="div"
className="alert alert-danger"
/>
<ErrorMessage
name="balance"
component="div"
className="alert alert-danger"
/>
<ErrorMessage
name="asOfDate"
component="div"
className="alert alert-danger"
/>
<fieldset className="form-group">
<label>Account Name</label>
<Field
className="form-control"
type="text"
name="accountName"
/>
</fieldset>
<fieldset className="form-group">
<label>Balance</label>
<Field
className="form-control"
type="number"
name="deposits"
/>
</fieldset>
<fieldset className="form-group">
<label>As of</label>
<Field className="form-control" type="date" name="asOfDate" />
</fieldset>
<button className="btn btn-success" type="submit">
Save
</button>
</Form>
)}
</Formik>
</div>
</div>
);
}
}
export default Accounts;
Here is another file that imports AccountDataService:
import React, { Component } from "react";
import moment from "moment";
import CurrencyFormat from "react-currency-format";
import AccountDataService from "../../api/AccountDataService";
import AuthenticationService from
"../../components/authentication/AuthenticationService.js";
import "./Accounts.css";
import Cube from "./Cube.jsx";
class AccountsBalanceList extends Component {
constructor(props) {
console.log("constructor");
super(props);
this.state = {
accounts: [],
message: null,
};
this.deleteAccountClicked = this.deleteAccountClicked.bind(this);
this.updateAccountClicked = this.updateAccountClicked.bind(this);
this.addAccountClicked = this.addAccountClicked.bind(this);
this.refreshAccounts = this.refreshAccounts.bind(this);
}
componentWillUnmount() {
console.log("componentWillUnmount");
}
shouldComponentUpdate(nextProps, nextState) {
console.log("shouldComponentUpdate");
console.log(nextProps);
console.log(nextState);
return true;
}
componentDidMount() {
console.log("componentDidMount");
this.refreshAccounts();
console.log(this.state);
}
refreshAccounts() {
let username = AuthenticationService.getLoggedInUserName();
AccountDataService.retrieveAllAccounts(username).then((response) => {
this.setState({ accounts: response.data });
});
}
deleteAccountClicked(id) {
let username = AuthenticationService.getLoggedInUserName();
AccountDataService.deleteAccount(username, id).then((response) => {
this.setState({
message: `Deletion of account ${id} was successful`,
});
this.refreshAccounts();
});
}
addAccountClicked() {
this.props.history.push(`/accounts/-1`);
}
updateAccountClicked(id) {
console.log("update " + id);
this.props.history.push(`/accounts/${id}`);
}
render() {
console.log("render");
return (
<>
<Cube />
<div style={{textAlign: "center"}}>
<h1>Accounts and their Current Balances</h1>
{this.state.message && (
<div class="alert alert-success">{this.state.message}</div>
)}
<div className="container">
<table className="table table-bordered table-hover">
<thead>
<tr>
<th>Account Name</th>
<th>Balance</th>
<th>As of</th>
<th>Update</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{this.state.accounts.map((account) => (
<tr key={account.id}>
<td>{account.accountName}</td>
<td>
<CurrencyFormat
value={Math.abs(
account.deposits - account.withdrawals
).toFixed(2)}
displayType={"text"}
thousandSeparator={true}
prefix={"$"}
/>
</td>
<td>
{moment.utc(account.asOfDate).format("MMM-DD-YYYY")}
</td>
<td>
<button
className="btn btn-success"
onClick={() => this.updateAccountClicked(account.id)}
>
Update
</button>
</td>
<td>
<button
className="btn btn-warning"
onClick={() => this.deleteAccountClicked(account.id)}
>
Delete
</button>
</td>
</tr>
))}
</tbody>
</table>
<div className="row">
<button
className="btn btn-success"
onClick={this.addAccountClicked}
>
Add
</button>
</div>
<br />
</div>
</div>
</>
);
}
}
export default AccountsBalanceList;
Here is my AccountJpaResource file in Java:
#RestController
#CrossOrigin(origins = "*", allowedHeaders = "*")
public class AccountJpaResource {
#Autowired
private AccountService accountService;
#Autowired
private AccountJpaRepository accountJpaRepository;
#GetMapping("/jpa/users/{username}/accounts")
public List<Account> getAllAccounts(#PathVariable String username) {
return accountJpaRepository.findByUsername(username);
}
#GetMapping("/jpa/users/{username}/accounts/{id}")
public Account getAccount(#PathVariable String username, #PathVariable long id) {
return accountJpaRepository.findById(id).get();
}
// DELETE /users/{username}/accounts/{id}
#DeleteMapping("/jpa/users/{username}/accounts/{id}")
public ResponseEntity<Void> deleteAccount(#PathVariable String username, #PathVariable long id) {
accountJpaRepository.deleteById(id);
return ResponseEntity.noContent().build();
}
//Edit/Update an Account
//PUT /users/{username}/accounts/{id}
#PutMapping("/jpa/users/{username}/accounts/{id}")
public ResponseEntity<Account> updateAccount(
#PathVariable String username,
#PathVariable long id, #RequestBody Account account){
account.setUsername(username);
Account accountUpdated = accountJpaRepository.save(account);
return new ResponseEntity<Account>(account, HttpStatus.OK);
}
#PostMapping("/jpa/users/{username}/accounts")
public ResponseEntity<Void> createAccount(
#PathVariable String username, #RequestBody Account account){
account.setUsername(username);
Account createdAccount = accountJpaRepository.save(account);
URI uri = ServletUriComponentsBuilder.fromCurrentRequest()
.path("/{id}").buildAndExpand(createdAccount.getId()).toUri();
return ResponseEntity.created(uri).build();
}
}

How to sort data in spring jpa?

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
}

Spring + Thymleaf validation for dynamic generated fields

I am trying to validate the input field generated dynamically. below code will give us more input:
code from HTML:
<th:block th:each="word,itera : ${credentialsForm.credentialRequirements}">
<div class="rtr_credential" style="display: inline-block;">
<span th:text="${word.attribute}" ></span>
<input type="hidden" th:name="|credentialRequirements[${itera.index}].attribute|" th:value="${word.attribute}">
</div>
<div class="rtr_credential" style="display: inline-block;">
<input type="text" name="userValue" th:field="*{credentialRequirements[__${itera.index}__].userValue}" class="userValue" maxlength="30"
th:classappend="${#fields.hasErrors('userValue')}? has-error : ''">
</div>
</th:block>
It gives error as userValue is not in credentialsForm and if I include
th:classappend="${#fields.hasErrors('{credentialRequirements[__${itera.index}__].userValue}')}? has-error : ''">
this will throw indexing error.
Java class structure:
public class CredentialRequirementForm {
private List<CredentialRequirements> credentialRequirements;
public List<CredentialRequirements> getCredentialRequirements() {
return credentialRequirements;
}
public void setCredentialRequirements(List<CredentialRequirements> credentialRequirements) {
this.credentialRequirements = credentialRequirements;
}
}
CredentialRequirements.java
public class CredentialRequirements {
private String attribute;
private String carrierDescription;
#NotBlank
#NotNull
private String userValue;
public CredentialRequirements() {
super();
// TODO Auto-generated constructor stub
}
public CredentialRequirements(String attribute, String carrierDescription, String userValue) {
super();
this.attribute = attribute;
this.carrierDescription = carrierDescription;
this.userValue = userValue;
}
public String getAttribute() {
return attribute;
}
public void setAttribute(String attribute) {
this.attribute = attribute;
}
public String getCarrierDescription() {
return carrierDescription;
}
public void setCarrierDescription(String carrierDescription) {
this.carrierDescription = carrierDescription;
}
public String getUserValue() {
return userValue;
}
public void setUserValue(String userValue) {
this.userValue = userValue;
}
#Override
public String toString() {
return "CredentialRequirements [attribute=" + attribute + ", carrierDescription=" + carrierDescription
+ "]";
}
}
How to validate the userValues, it is dynamically generated, some time only 1 attribute and some time 5 attributes. I am also trying the Jquery validate, but confuse how to implement.
Why don't you simply use a th:field attribute to bind HTML fields to your entity fields? Then you can add a div with the error message (if there will be a validation error):
<th:block th:each="word,itera : ${credentialsForm.credentialRequirements}">
<div class="rtr_credential" style="display: inline-block;">
<span th:text="${word.attribute}" ></span>
<input type="hidden" th:field="*{credentialRequirements[__${itera.index}__].attribute}">
</div>
<div th:if="${#fields.hasErrors('credentialRequirements[__${itera.index}__].userValue')}" th:errors="*{credentialRequirements[__${itera.index}__].userValue}">
Error message
</div>
<div class="rtr_credential" style="display: inline-block;">
<input type="text" name="userValue" th:field="*{credentialRequirements[__${itera.index}__].userValue}" class="userValue">
</div>
</th:block>
Thank you everyone for your answer and comments.
I need to deliver the code, so using Jquery and Javascript to validate:
Please find the code below:
submitHandler : function(form) {
let invalid = 0
$( ".userValue" ).removeClass( "has-error" )
$( ".userValue" ).each(function() {
if($( this ).val() == "" ) {
invalid++
$( this ).addClass( "has-error" );
}
});
if(invalid == 0){
//some logic
form.submit();
}
}

How to upload form with image file in it, AngularJS spring

I have this form
<div class="row">
<h1 class="page-header">
Create
</h1>
<form ng-submit="create()", enctype="multipart/form-data">
<div class="form-group">
<label>Name:</label>
<input type="text" ng-model="subforum.name" class="form-control" />
</div>
<div class="form-group">
<label>Desc:</label>
<input type="text" ng-model="subforum.desc" class="form-control" />
</div>
<input type="file" ngf-select ng-model="subforum.icon" name="subforum.icon"
accept="image/*" ngf-max-size="2MB" required
ngf-model-invalid="errorFile">
<img ng-show="myForm.file.$valid" ngf-thumbnail="subforum.icon" class="thumb"> <button ng-click="subforum.icon= null" ng-show="subforum.icon">Remove</button>
<button class="btn btn-success" type="submit">Create</button>
</form>
``
In my JS
.config(function($stateProvider) {
$stateProvider.state('create', {
url:'/subforum/create',
views: {
'main': {
templateUrl:'subforum/create.tpl.html',
controller: 'CreateCtrl'
}
},
data : { pageTitle : "Create Subforum" }
})
and
.factory('subforumService', function($resource) {
var service = {};
service.create = function (subforum, success, failure) {
var SubForum= $resource ("/web-prog/rest/subforums");
SubForum.save({}, subforum, success, failure) ;
};
.controller("CreateCtrl", function($scope, $state, subforumService) {
$scope.create = function() {
$scope.subforum.author = JSON.parse(localStorage.getItem ("logedUser"));
subforumService.create($scope.subforum,
function(returnedData) {
$state.go("home");
},
function() {
alert("Error creating");
});
};
I know thats not best practice to save user in LocalStorage but for now its like that.
On backend i have controller and in that controller i have methode:
#RequestMapping(method = RequestMethod.POST)
public ResponseEntity<SubForumResource> createPodforum(#RequestBody SubForumResource sentPodforum) {
}
and SubForumResource is
public class PodforumResource extends ResourceSupport {
private String name;
private String desc;
private byte[] icon;}
with geters and seters and everything i need.
So when i have form without image it works without problems. But i need icon too. Im new to angularjs but need it for this project. When i try to use FormData() i dont know how to use $resource. So if someone can help me i would be thankful. This is my first prject i need to work front end so im lost.
You can refer below code for angularjs :
this.addEmployee = function (requestData, file) {
var data = new FormData();
data.append('file', file[0]);
data.append('requestData', new Blob([JSON.stringify(requestData)], {
type: "application/json"
}));
var config = {
transformRequest: angular.identity,
transformResponse: angular.identity,
headers: {
'Content-Type': undefined
}
}
var url = "http://localhost:8080/addEmployee";
var promise1 = $http.post(url, data, config);
var promise2 = promise1.then(function (response) {
return response.data;
},
function errorCallback(response) {
alert(response.data.errorMessage);
});
return promise2;
}
And for controller :
#RequestMapping(value = "/addEmployee", method = RequestMethod.POST, consumes = {"multipart/form-data" })
#CrossOrigin
public CustomResponse addEmployee(#RequestPart("file") MultipartFile file, #RequestPart("requestData") Employee emp) {
}

How to using th:if tag to check database field using thymeleaf

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.

Categories