I have a velocity template with tag form.
<div class="row">
<div class="container">
<div class="col-lg-12">
<table class=" table table-striped">
<thead>
<th>#</th>
<th>username</th>
<th>role</th>
<th>password</th>
</thead>
<tbody>
#foreach( $user in $users )
<tr>
<td>$user.id</td>
<td>$user.username</td>
<td>$user.role</td>
<td>$user.password</td>
<td>Delete</td>
<td>Edit</td></tr>
#end
</tbody>
</table>
<form method="post" action="/user">
<div class="form-group">
<label for="username">Username:</label>
<input type="username" class="form-control" id="username">
</div>
<div class="form-group">
<label for="pwd">Password:</label>
<input type="password" class="form-control" id="pwd">
</div>
<div class="form-group">
<label for="role">Role:</label>
<input type="role" class="form-control" id="role">
</div>
<button type="submit" class="btn btn-default">Add</button>
</form>
</div>
</div>
And I need to pass entered data to the controller. Here is controller code.
#RequestMapping(value = "/user", method = RequestMethod.POST)
public String addUser(#ModelAttribute User newUser) {
userService.save(newUser);
return "redirect:/users";
}
I'm newbie in velocity and I haven't figured out in this framework yet. I've google a long time but unsuccessful. Please help velocity guru!
The problem I see here is not just about velocity or Spring. Your form inputs does not have names, it seems you misplaced name for type in your form. It's the input names that's sent to the controller. What you want to do is create a User model and make sure it has the same variable names as the form input names.
public class User {
private String username;
private String password;
private String role;
// Add getter and setter methods
// Add toString method
}
And your form should be like
<form method="post" action="/user">
<div class="form-group">
<label for="username">Username:</label>
<input type="text" class="form-control" id="username" name="username">
</div>
<div class="form-group">
<label for="pwd">Password:</label>
<input type="password" name="password" class="form-control" id="pwd">
</div>
<div class="form-group">
<label for="role">Role:</label>
<input type="text" class="form-control" id="role" name="role">
</div>
<button type="submit" class="btn btn-default">Add</button>
</form>
Your controller method should get the user object like that. I just did a simple spring boot app to test and it worked.
Related
I am using selenium junit testing.
If i try with selenium ide, the test goes well, but with junit it gives me this error:
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"#firstName"}
I think that the span doesn't redirect to the page it should (but in normal schedule it does).
#Test
public void adminCreateDoc() {
driver.get("http://localhost:8080/login");
driver.manage().window().setSize(new Dimension(550, 706));
driver.findElement(By.linkText("Accesso amministratori")).click();
driver.findElement(By.id("username")).sendKeys("8245");
driver.findElement(By.id("password")).click();
driver.findElement(By.id("password")).sendKeys("prova1");
driver.findElement(By.cssSelector(".btn")).click();
driver.findElement(By.id("btn_createDoc")).click();
driver.findElement(By.id("firstName")).click();
driver.findElement(By.id("firstName")).sendKeys("Marco");
driver.findElement(By.id("lastName")).click();
driver.findElement(By.id("lastName")).sendKeys("Battiato");
driver.findElement(By.id("doc_type")).click();
driver.findElement(By.id("doc_type")).sendKeys("Cardiologo");
driver.findElement(By.id("id")).click();
driver.findElement(By.id("id")).sendKeys("855555");
driver.findElement(By.id("password")).click();
driver.findElement(By.id("password")).sendKeys("prova1");
driver.findElement(By.cssSelector(".glyphicon-send")).click();
}
I've tried with xpath, but without success...
HTML page with span redirection:
<body>
<div class="container text-center">
<div align="center">
<h2>Gestione dottori</h2>
<table class="table table-striped table-responsive-md">
<tr>
<th>ID</th>
<th>Nome</th>
<th>Specialità</th>
</tr>
<tr th:each="doc: ${listDoc}">
<td th:text="${doc.getId()}"></td>
<td>Dr. <span th:text="${doc.getFirstName()}"></span> <span th:text="${doc.getLastName()}"></span></td>
<td th:text="${doc.getDoc_type()}"></td>
</tr>
</table>
<a th:href = "#{/admin_createdoc}"><span id="btn_createDoc" class="plus bg-dark" >+</span></a>
<hr>
<div class="col col-lg-2 align-self-center">
<div class="p-1">
<form th:action="#{/admin_logout}" method=post>
<button name="btn_logout_profile" id="btn_logout_profile"
type="submit" class="btn btn-primary">Log Out</button>
</form>
</div>
</div>
</div>
</div>
</body>
Which redirect to this page:
<body>
<div class="container">
<div class="d-flex align-items-center justify-content-start">
<form th:action="#{/admin_homepage}" method=get>
<button name="btn_back_profile" id="btn_back_profile" type="submit"
class="btn btn-info">
<span class="fas fa-chevron-left"></span>
</button>
</form>
</div>
<br>
<div style='text-align: center'>
<form class="well form-horizontal" action="#"
th:action="#{/saveDoctor}" th:object="${doc}" method="POST"
id="contact_form">
<fieldset>
<!-- Form Name -->
<legend>
<center>
<h2>
<b>Doctor Creation Form</b>
</h2>
</center>
</legend>
<br>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label">First Name</label>
<div class="col-md-4 inputGroupContainer">
<div class="input-group">
<span class="input-group-addon"><i
class="glyphicon glyphicon-user"></i></span> <input name="first_name"
th:field="*{firstName}" placeholder="Doc First Name"
class="form-control" type="text" required>
</div>
</div>
</div>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label">Last Name</label>
<div class="col-md-4 inputGroupContainer">
<div class="input-group">
<span class="input-group-addon"><i
class="glyphicon glyphicon-user"></i></span> <input name="last_name"
th:field="*{lastName}" placeholder="Doc Last Name"
class="form-control" type="text" required>
</div>
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label">Type</label>
<div class="col-md-4 inputGroupContainer">
<div class="input-group">
<span class="input-group-addon"><i
class="glyphicon glyphicon-list"></i></span> <input name="doc_type"
th:field="*{doc_type}" placeholder="Doc Type"
class="form-control" type="text" required>
</div>
</div>
</div>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label">Id</label>
<div class="col-md-4 inputGroupContainer">
<div class="input-group">
<span class="input-group-addon"><i
class="glyphicon glyphicon-user"></i></span> <input name="id"
th:field="*{id}" placeholder="Doc ID" class="form-control"
type="number" required>
</div>
</div>
</div>
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label">Password</label>
<div class="col-md-4 inputGroupContainer">
<div class="input-group">
<span class="input-group-addon"><i
class="glyphicon glyphicon-user"></i></span> <input
th:field="*{password}" name="doc_password"
placeholder="Doc Password" class="form-control" type="password"
required>
</div>
</div>
</div>
<!-- Button -->
<div class="form-group" align="center">
<label class="col-md-4 control-label"></label>
<div class="col-md-4">
<br>
<button type="submit" class="btn btn-warning">
SUBMIT <span class="glyphicon glyphicon-send"></span>
</button>
</div>
</div>
</fieldset>
</form>
<div>
<form th:action="#{/admin_logout}" method=post>
<button name="btn_logout_profile" id="btn_logout_profile"
type="submit" class="btn btn-primary">Log Out</button>
</form>
</div>
</div>
</div>
</body>
Thank you for your time!
The failure is happening on this line
driver.findElement(By.id("firstName")).click();
ID as a CSS selector is #firstName. Since this is right after a page transition, my guess is that the page isn't fully loaded before the next line of code is run. This can sometimes happen on a modern site where the page is loaded but there's still stuff being loaded asynchronously in the background. The fix is to add a wait, specifically a WebDriverWait, to the following line. That is one option...
Instead of adding a wait piecemeal when it's found that you need it, I prefer to write helper methods that take care of common actions like click(), sendKeys(), etc. and then let those methods take care of the specific waits for me.
public void click(By locator) {
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(locator)).click();
}
public void sendKeys(By locator, String text) {
findElement(locator).sendKeys(text);
}
public WebElement findElement(By locator) {
return new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfElementLocated(locator));
}
Then you can change your script to
#Test
public void adminCreateDoc() {
driver.get("http://localhost:8080/login");
driver.manage().window().setSize(new Dimension(550, 706));
click(By.linkText("Accesso amministratori"));
sendKeys(By.id("username"), "8245");
sendKeys(By.id("password"), "prova1");
click(By.cssSelector(".btn"));
click(By.id("btn_createDoc"));
sendKeys(By.id("firstName"), "Marco");
sendKeys(By.id("lastName"), "Battiato");
sendKeys(By.id("doc_type"), "Cardiologo");
sendKeys(By.id("id"), "855555");
sendKeys(By.id("password"), "prova1");
click(By.cssSelector(".glyphicon-send"));
}
which I think makes it more readable, adds waits to everything in case it's needed with no extra code, and so on...
The next level is using the Page Object Model to contain the locators and methods for each page. Then your code gets cleaned up significantly, makes it near-human readable, and MUCH easier to manage.
I am new to thymeleaf and I working on a login form. I have found a simple example where there is login input text and password fields.
I have included the project in my system. When I click the login button without filling username and password section, a please fill in details ballon pops up. I have not configured it anywhere, but would like to know from it is getting popped up. Below is the code
<div class="row" style="margin-top:20px">
<div class="form-group " align="right">
</br> </br> </br> </br> </br></br> </br> </br> </br>
<form th:action="#{/login}" method="post">
<fieldset>
<h2 class="form-heading">Log in</h2>
<div th:if="${param.error}">
<div class="alert alert-danger">
Invalid username and password.
</div>
</div>
<div th:if="${param.logout}">
<div class="alert alert-info">
You have been logged out.
</div>
</div>
<div class="form-group">
<input type="text" name="username" id="userName" class="form-control input-lg"
placeholder="UserName" required="true" autofocus="true"/>
</div>
<div class="form-group">
<input type="password" name="password" id="password" class="form-control input-lg"
placeholder="Password" required="true"/>
</div>
<div class="row">
<button class="btn btn-default" role="button">Log In</button>
</div>
</div>
</fieldset>
</form>
</div>
</div>
I have a requirement to store uploaded files in a mysql database. Currently, I'm storing them in a blob format but I'm not converting the files before I store them in the database. I would like to convert the file to pdf format before I store them.
This is the form I'm using:
<form:form id="add__document" class="form-horizontal form-label-left"
action="saveDoc?${_csrf.parameterName}=${_csrf.token}"
method="POST" modelAttribute="newDoc" enctype="multipart/form-data">
<div class="form-group">
<label class="control-label col-md-4 col-sm-4 col-xs-12">Expiry Date: </label>
<div class="col-md-6 col-sm-6 col-xs-6">
<form:input id="expiryDate" path="expiryDate" class="form-control" type="text" />
</div>
</div>
<div class="form-group">
<label class="control-label col-md-4 col-sm-4 col-xs-12">Upload File: </label>
<div class="col-md-6 col-sm-6 col-xs-6">
<form:input class="btn" type="file" path="document" name="document"/>
</div>
</div>
<input class="btn btn-success" type="submit" value="Upload" />
</form:form>
And this is my controller class:
#RequestMapping(value = {"/saveDoc"}, method = RequestMethod.POST)
public ModelAndView addNewDocument(#ModelAttribute NewDoc newdoc, HttpServletRequest request,
final RedirectAttributes redirectAttributes) throws Exception {
newdoc.setFile(newdoc.getDocument().getBytes());
newdoc.setContentType(newdoc.getDocument.getContentType());
documentsDAO.addDocument(newdoc);
return new ModelAndView("redirect:/DocumentsPage");
}
The addDocument method will insert the data into the MySQL table.
Any help would be greatly appreciated.
I have a jsp file with below code
<form:form modelAttribute="user" method="POST" name="loginForm" action="loginProcess" id="loginForm" autocomplete="off">
<input type='hidden' name='remember-me' value="true" />
<div id="login-container">
<spring:bind path="userName">
<c:if test="${status.error}">
<div id="formError" <span><form:errors path="userName" /></span></div>
</c:if>
</spring:bind>
<fieldset>
<ul id="login-form">
<li>
<label for="username"><spring:message code="login.UserName" /></label>
<input id="username" name="username" type="text" <spring:bind path="userName"> <c:if test="${not empty status.error}"> value='<%= (session.getAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_PASSWORD_KEY) == null ? userName :session.getAttribute(UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_PASSWORD_KEY)) %>'</c:if> </spring:bind> />
</li>
<li>
<label for="password"><spring:message code="login.Password" /></label>
<input id="password" name="password" type="password" />
</li>
<li>
<div class="buContainer">
<a class="buOrange large" id="submit" href="#" onclick="validateForm()"><spring:message code="login.logIn" /></a>
</div>
</li>
</ul>
</fieldset>
<div class="buContainer">
<a id="forgot-link" href="forgotPassword"><spring:message code="login.forgotPassword" /></a>
</div>
</div>
</form:form>
Here when login fails i need to retain username.I tried
<form:form>
<form:input path="username" />
</form:form>
But i dont know where to use above code, Please help me on this.
We have this tag in our login.jsp, it seems to work OK:
<input id="j_username"
type="text"
name="j_username"
value="${sessionScope.SPRING_SECURITY_LAST_USERNAME}"
placeholder="Username"
class="form-control no-border">
The $sessionScope.SPRING_SECURITY_LAST_USERNAME seems to do the trick.
I have the following problem. See code below.
<form:form action="${pageContext.request.contextPath}/editUser" commandName="user">
<div id="editUserDialog" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Edit user</h4>
</div>
<div class="modal-body">
<form:select id="slc_picker" path="id" class="selectpicker" data-width="100%" onchange="javascript:onSelectEditUser()">
<c:forEach items="${users}" var="us">
<option>${us.id}</option>
</c:forEach>
</form:select>
<form:input id="surname" path="surname" type="text" class="form-control" placeholder="Surname"/>
<form:input id="name" path="name" type="text" class="form-control" placeholder="Name" />
<form:input id="fatherName" path="fatherName" type="text" class="form-control" placeholder="Father Name"/>
<form:input id="mobilePhone" path="mobilePhone" type="text" class="form-control" placeholder="Mobile Phone"/>
<form:input id="email" path="email" type="text" class="form-control" placeholder="Email"/>
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-success" value="Save user"/>
<input type="button" class="btn btn-danger" data-dismiss="modal" onclick="resetSelectpicker()"/>
</div>
</div>
</div>
</div>
</form:form>
This is spring form in jsp page. After I clicked submit button, I was sending request to controller, and all my form input(name, surname,... and other) were reset, but after I clicked close button, they contain value, and I want reset all form:input, when I clicked close button. I suppose, thet I must reset object /commandName="user"/.
Try changing button type to reset
<button type="reset" class="close" data-dismiss="modal" aria-hidden="true">×</button>