I try to send a parameter applicationNo wrapped inside my form tag.The data inside input generated via javascript snippet. I need to pass this data to my controller, but it always throw null pointer exception, I am not able to figure it out what is the problem.
So kindly suggest me the best way to achieve. I also attached required source code and snapshot.
I want to send the data highlighted in red area in below screenshot.
JSP CODE:
<form action="${baseURL}view_grp_conn_applications" id="grpCreationForm" method="post" commandName="command" >
<div class="col-sm-12">
<table id="addAppTable" class="table table-responsive table-bordered table-striped text-center" id="newField">
<thead>
<tr>
<th>#</th>
<th>Application No.</th>
<th>Name</th>
<th>Mobile No.</th>
<th>E-mail</th>
</tr>
</thead>
<tbody>
<c:set var="i" value="0"></c:set>
<tr>
<td valign="center"><input name="workOrderPostSps[${i}]" id="workOrderPostSps[${i}]" type="checkbox" value="${wo.woPostIdEnc}" onclick="highlightrow(this);" /></td>
<td align="center"><b><input onkeypress="show_list('${i}');" id="appNo1${i}" name="applicationNo" class="form-control start" autocomplete="off" data-validate="required" required="true" placeholder="press key on keyboard"/></b></td>
<td align="left"><span id="appName1${i}"></span></td>
<td align="left"><span id="appContact${i}"></span></td>
<td align="left"><span id="email1${i}"></span></td>
</tbody>
</table>
</div>
<div class="col-md-12">
<input type="submit" class="btn btn-turquoise pull-right no-margin " name="saveBtn" id="saveBtn" value="Next >>" onclick="myfunction()">
</div>
</form>
JAVA CODE:
This method open the JSP from where I wish to send the applicationNo
#RequestMapping(value = "/create_group_connection")
public ModelAndView createConnection(Model model) {
ModelAndView mav = new ModelAndView("user/create_group_connection");
Application application = new Application();
mav.addObject("command", application);
return mav;
}
This method will open the jsp where i need to extract that applicationNo
#RequestMapping(value = "/view_grp_conn_applications", method = RequestMethod.POST)
public ModelAndView viewApplications(#ModelAttribute("command")Application application,HttpServletRequest request, HttpSession session) {
ModelAndView mav = new ModelAndView("user/grp_conn_applications");
try {
System.out.println("inside view group applications");
String[] applicationNo = request.getParameterValues("applicationNo");
System.out.println("inside " + applicationNo[0]);
// for (int i = 0; application.length > 0; i++) {
// System.out.println("application number is" + application[i]);
// }
} catch (Exception e) {
System.out.println("Exception occured");
e.printStackTrace();
}
return mav;
}
<td><b><input onkeypress="show_list('${i}');" id="appNo1${i}" name="applicationNo" class="form-control start" autocomplete="off" data-validate="required" required="true" placeholder="press key on keyboard"/></b></td>
you just use the below instead of above
<input type='hidden' id="applicationNo" name="applicationNo" /></b></td>
you just set the application number using Javascript through id of hidden field on any event like onBlur, onKeyPress,Your Controller code is Correct
Related
Im doing a CRUD app with Java using Servlets and i have a jsp file as a list of many users where i have a button to edit my row. As i click on my button it should redirect me to ServletPacientes?Param=editar&dni=<%a.getDni()%>.
So this is my ListarPacientes.jsp: Where i have some scriplets and my html forms.
<body>
<% if (request.getSession().getAttribute("usuario") == null) {
request.getRequestDispatcher("Login.jsp").forward(request, response);
throw new UsuarioNoLoggeadoException();
}
Usuario user = (Usuario)request.getSession().getAttribute("usuario");
if (user.getTipo_usuario().getID() != 1) {
request.getRequestDispatcher("Home.jsp").forward(request, response);
throw new UsuarioSinPermisoException();
}
%>
<%
if (request.getParameter("buscarLista") == null) {
request.getRequestDispatcher("ServletPacientes?Param=list").forward(request, response);
}
List<Paciente> listaM = new ArrayList<Paciente>();
if (request.getAttribute("listaPac") != null) {
listaM = (List<Paciente>)request.getAttribute("listaPac");
}
%>
<jsp:include page="Menu.jsp"></jsp:include>
<div class="table-title">
<h3>Tabla Pacientes</h3>
</div>
<form method="post" action="ServletPacientes">
<div class="form-group">
<label>Buscar: </label>
<input type="text" class="form-control" name="txtBuscar">
</div>
<div class="col-12">
<input type="submit" class="btn btn-success" value="Buscar" name="btnBuscar">
</div>
<table class="table-fill">
<thead>
<tr>
<th class="text-left">Nombre</th>
<th class="text-left">Apellido</th>
<th class="text-left">DNI</th>
<th class="text-left">Sexo</th>
<th class="text-left">Direccion</th>
<th class="text-left">Fecha de Nacimiento</th>
<th class="text-left">Email</th>
<th class="text-left">Telefono</th>
<th class="text-left">Nacionalidad</th>
</tr>
</thead>
<tbody class="table-hover">
<tr>
<%
for (Paciente a : listaM) {
%>
<tr>
<form action="ServletPacientes" method="post">
<td><%=a.getNombre()%></td>
<td><%=a.getApellido()%></td>
<td><%=a.getDni()%> <input type="hidden" name="dniPaciente" value="<%=a.getDni()%>" ></td>
<td><%=a.getSexo()%></td>
<td><%=a.getDireccion()%></td>
<td><%=a.getFechaNac()%></td>
<td><%=a.getCorreo()%></td>
<td><%=a.getTelefono()%></td>
<td><%=a.getNacionalidad()%></td>
<td> <input type="submit" name="btnEliminar" value="Eliminar" class="btn btn-danger"></td>
</form>
<td> <input type="submit" name="btnEditar" value="Editar" class="btn btn-warning"></td>
</tr>
<%
}
%>
</tbody>
</table>
<br>
<div align="center">
</div>
</form>
</body>
As you can see i have de following tags
<td> <input type="submit" name="btnEditar" value="Editar" class="btn btn-warning"></td>
So in each row i have this button where i call my Controller (Servlet) with the parameter "editar" and i pass the method getDni() of my class Paciente.
And here is my code of my ServletPacientes:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if(request.getParameter("Param")!=null)
{
String opcion = request.getParameter("Param").toString();
switch (opcion) {
case "previoInsert":
{
break;
}
case "list":
{
request.setAttribute("listaPac", negPac.listarPacientes());
RequestDispatcher dispatcher = request.getRequestDispatcher("/ListarPacientes.jsp?buscarLista=1");
dispatcher.forward(request, response);
break;
}
case "editar":
{
Paciente p = new Paciente();
p = negPac.obtenerUno(request.getParameter("dniPaciente"));
System.out.println(p);
request.setAttribute("dniPac", p);
RequestDispatcher dispatcher = request.getRequestDispatcher("/EditarPaciente.jsp");
dispatcher.forward(request, response);
break;
}
default:
break;
}
}
}
The method above shows a switch where each case is a different parameter that im passing to my route. So when i click on my edit button instead of taking me to for example ServletPacientes?Param=editar&dni=20216447 it just redirects me to ServletsPacientes which is a blank page.
It looks like im never receiving the parameter editar neither the dni property. Becaus if i manually put on my url ServletPacientes?Param=editar&dni=20216447 it does takes me to the Edit view.
You essentially have the following structure:
<form method="post" action="ServletPacientes">
<a href="ServletPacientes?Param=editar&dni=<%=a.getDni()%>">
<input type="submit" value="Editar">
</a>
</form>
This means that when you click on this "Editar" button, a form submission will happen as a POST request. This request is supposed to be processed by a doPost method on the servlet side, and the URL would be /ServletPacientes. This is why you navigate to /ServletPacientes. The link in the wrapping <a> element will have no effect.
If you expect to navigate to something like ServletPacientes?Param=editar&dni=20216447, you'll have to make the nested input element a regular button, not a submit: <input type="button" value="Editar">.
I want to fill the form according to the related book when I click the view or update the link on the page. I know, there is a solution with opening another page but I want to do it on the same page. As you can see on the picture below I can properly get the list on the left table. I have tried a post method below but did not work. So what would you recommend to do it?
Controller class:
#PostMapping(path = "/listbooks")
public String getBook(#ModelAttribute BookConfig bookConfig, Model model)
throws IOException {
model.addAttribute("book", bookConfig);
return "list";
}
#GetMapping(path = "/listbooks")
public String showAllBooks(Model model) throws IOException {
model.addAttribute("books", bookService.getBookConfigList());
return "list";
}
HTML file:
<div class="table-responsive" th:if="${not #lists.isEmpty(books)}">
<table class="table table-hover" style="height:50px;">
<thead class="thead-inverse">
<tr>
<th>Name</th>
<th>View</th>
<th>Update</th>
<th>Delete</th>
</tr>
</thead>
<tr th:each="book : ${books}">
<td th:text="${book.name}">Book Name</td>
<td>View</td>
<td>Update</td>
<td>Delete</td>
</tr>
</table>
</div>
This is what I am trying to do on the HTML file:
<form th:if="${book != null}" th:object="${book}" th:action="#{/book/}"
method="post">
<div class="panel-heading">
<h4 class="panel-title"
">Edit
Book Configuration</h4>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-3 form-group"
>
<label>Book name</label>
<input type="text" class="form-control" th:field="*{name}"/>
</div>
...
I have solved using JavaScript, Firstly, I have adjusted the getBook method below
#PostMapping("/books")
public String getBook(#RequestBody String bookName) throws IOException {
return "list";
}
and then I have add these two JS functions:
$(document).ready(function () {
$(".view").click(function () {
var $row = $(this).closest("tr"); // Find the row
var $text = $row.find(".bookname").text(); // get the text on the view link using its the class name
$.post("http://localhost:8081/books",
{
bookName: $text
},
function (data, status) {
assignDataToTable(data);
});
});
});
function assignDataToTable(data) {
alert("hey" + data);
document.getElementById("booknameinput").value = data;
}
I have an object:
InvoiceData
String name
Date date
List<InvoiceTask>
The InvoiceTask has 3 fields:
InvoiceTask
String name
String project
BigDecimal hours
I have created a thymeleaf formular that is creating an InvoiceData object and persisting it into my MongoDB instance, but it contains only Name and Date. I have no Idea how to modify this form to add not only a task, but multiple tasks (probably with a button "Add task" inside the form).
The controller that is redirecting to add.html looks like this:
#RequestMapping(value = "/add/{id}")
public String addPage(#PathVariable("id") String id, Model model) {
InvoiceData invoiceData = new InvoiceData();
model.addAttribute("contractorid", id);
model.addAttribute("invoicedata", invoiceData);
return "add";
}
The controller that is persising the InvoiceData looks like this:
#RequestMapping(value = "/addinvoice/{id}", method = RequestMethod.POST, produces = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String addInvoice(#PathVariable("id") String id, InvoiceData data, Model model) {
Contractor contractor = contractorRepository.findById(id).get();
data.setData(contractor.getContractorData());
if (contractor.getInvoices() == null) {
contractor.setInvoices(new ArrayList<InvoiceData>());
}
contractor.getInvoices().add(data);
invoiceDataRepository.save(data);
contractorRepository.save(contractor);
model.addAttribute("contractor", contractor);
return "index";
and the Thymeleaf template for the InvoiceData looks like this (it doesnt have the InvoiceTask list yet!):
<form action="#" th:action="#{addinvoice/{id}(id=${contractorid})}" th:object="${invoicedata}" method="post">
<ul class="form-style-1">
<li>
<label>Name<span class="required">*</span></label>
<input type="text" th:field="*{name}" id="receptionDate">
</li>
<li>
<label>Date<span class="required">*</span></label>
<input type="date" th:field="*{orderDate}" id="orderDate">
</li>
<li>
<input type="submit" value="Submit" />
</li>
</ul>
</form>
I'll be honest, I don't know where to start here...
One way is to create a wrapper class (a DTO?)to pass the invoices to create with the their respectives tasks. For
#RequestMapping(value = "/add/{id}")
public String addPage(#PathVariable("id") String id, Model model) {
InvoiceDataDTO invoiceData = new InvoiceDataDTO();
for(int i = 1; i <= 5; i++) {
invoiceData.addTask(new invoiceTask())
}
model.addAttribute("invoiceData", invoiceData);
return "add";
}
In your thymleaf form you have to display the constructed DTO, as following :
<form action="#" th:action="#{/invoices/save}" th:object="${invoicesData}"
method="post">
<fieldset>
<input type="submit" id="submitButton" th:value="Save">
<input type="reset" id="resetButton" name="reset" th:value="Reset"/>
<table>
<thead>
<tr>
<th> Name</th>
<th> Date</th>
</tr>
</thead>
<tbody>
<tr th:each="invoiceTask, itemStat : *{invoicesTaks}">
<td><input th:field="*{invoicesTasks[__${itemStat.index}__].name}" /></td>
<td><input th:field="*{invoicesTasks[__${itemStat.index}__].project}" /></td>
</tr>
</tbody>
</table>
</fieldset>
</form>
As you see you get the model attribute of the invoiceDataDTO with already added empty tasks.
After the object fill you only have to save.
I am trying to pass the information from a thymeleaf list and trying to add it to database.
I am getting data from the tmdb and it will be changing so i display the information obtain to the endpoint "/LatestMovies" this information is not saved in the db and ether should it be. so i am trying to add a save button for the custumer to add the movie listed.(its simple it just haves movieid and moviename)
Showing the movies listed i have no problem and it works fine but where i get error is when i add a hidden form. The current code i have is this:
<div class="container">
<table class="table table-hover">
<tr>
<th>Id</th>
<th>Name</th>
</tr>
<tr th:each="LatestMovies : ${latestMovies}">
<td th:text="${LatestMovies.id}"></td>
<td th:text="${LatestMovies.movieName}"></td>
<td>
<form action="#" th:action="#{/LatestMovies}" th:object="${addMovies}" method="post">
<p><input type="hidden" th:field="*{id}" th:attr="value = ${LatestMovies.id}" /></p>
<p><input type="hidden" th:field="*{movieName}" th:attr="value = ${LatestMovies.movieName}" /></p>
<p><input type="submit" value="Submit" /></p>
</form>
</td>
</tr>
</table>
#Controller
public class LatestMoviesController {
#Autowired
private LatestMoviesDao listOfMovies;
#Autowired
private savedMoviesDao movieRepo;
#GetMapping("/LatestMovies")
public String prueba(Model model) {
TmdbMovies movies = new TmdbApi("22914f477aaa3e7f86c6f5434df8d1eb").getMovies();
ResultsPage<MovieDb> movie = movies.getPopularMovies("en", 1);
for(int i=0; i <= 19; i++){
int movieId = movie.getResults().get(i).getId();
String movieName = movie.getResults().get(i).toString();
listOfMovies.save(new LatestMovies(movieId, movieName));
}
model.addAttribute("latestMovies", listOfMovies.findAll());
return "index";
}
#PostMapping("/LatestMovies")
public String save(#ModelAttribute("addMovies") Model model, SavedMovies addMovies) {
movieRepo.save(addMovies);
return "index";
}
}
Thx in advance
First, let's change your form. You don't need to add a new object to it, since you are already iterating through a list of them. That way, you will also avoid having to add the value for each field manually using th:attr. What we are gonna do, is send the required params separately and then build our movie object with them.
<div class="container">
<table class="table table-hover">
<tr>
<th>Id</th>
<th>Name</th>
</tr>
<tr th:each="LatestMovies : ${latestMovies}">
<td th:text="${LatestMovies.id}"></td>
<td th:text="${LatestMovies.movieName}"></td>
<td>
<form th:action="#{/LatestMovies}" method="post">
<p><input type="hidden" th:value="${LatestMovies.id}" name="id"/></p>
<p><input type="hidden" th:value="${LatestMovies.movieName}" name="name"/></p>
<p><input type="submit" value="Submit"/></p>
</form>
</td>
</tr>
</table>
</div>
Now, on your controller, do the following modifications.
#PostMapping("/LatestMovies")
public String save(#RequestParam("id") Integer id, #RequesParam("name") String name) {
SavedMovies movie = new SavedMovies();
movie.setId(id);
movie.setName(name);
movieRepo.save(movie);
return "index";
}
These changes should do the trick.
I asked a question earlier how to do this using Webflow, but it has proven to be impractical for my situation.
I am trying to have a walk through 3 screens which add to an object information and then require a confirm to add to the database at the end. [To maintain simplicity etc]
The first screen takes in username for example
then the next screen requires contact information
then the third screen shows a summary and asks to confirm
I am having trouble figuring out how to pass the same object through several screens. I understand how to pass information from one screen to next, but for some reason same technique doesn’t work through several screens.
Sample 3 pages:
AddUser.jsp
<div id="form">
<h2 >Step 1</h2>
<form action="AddUserContact" method="post">
<table>
<tr>
<td>User Name:</td>
<td><input type="text" id="username" name="username"/></td>
</tr>
<tr>
<td><input type="submit" value="Next"/></td>
</tr>
</table>
</form>
</div>
AddUserContact.jsp
<div id="form">
<h2 >Step 2</h2>
<form action="UserSummaryConfirm" method="post">
<table>
<tr>
<td>${user.username}</td>
</tr>
<tr>
<td>Address:</td>
<td><input type="text" id="address" name="address"/></td>
</tr>
<tr>
<td><input type="submit" value="Next"/></td>
</tr>
</table>
</form>
</div>
UserSummaryConfirm.jsp
<h2>Step 3</h2>
<form action="home" method="post">
<table>
<tr>
<td>User Name:</td>
<td>${user.username}</td>
</tr>
<tr>
<td>Address:</td>
<td>${address}</td>
</tr>
<tr>
<td>Confirm</td>
</tr>
</table>
</form>
I have a Controller for every page [its for me to understand better what is going on, Ill simplify it later]
AddUserController.java
#Controller
public class AddUserController{
#RequestMapping(value = "AddUser")
public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
User user = new User();
ModelAndView mav = new ModelAndView("AddUser");
user.setUserName(request.getParameter("username"));
mav.addObject("user", user);
return mav;
}
}
AddUserContactController.java
#Controller
public class AddUserContactController{
#RequestMapping(value = "AddUserContact")
public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mav = new ModelAndView("AddUserContact");
mav.addObject("user", request.getParameter("user"));
return mav;
}
}
AddUserConfirm.java
#Controller
public class AddUserConfirm{
#RequestMapping(value = "UserSummaryConfirm")
public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView mav = new ModelAndView("UserSummaryConfirm");
mav.addObject("user", request.getParameter("user"));
mav.addObject("address", request.getParameter("address"));
return mav;
}
}
And then the User class is just a simple class with getters and setters.
The problem I am having is no matter what I have tried to pass the object, I cannot seem to figure out why the same technique doesnt work.
The address on the third screen is beeing displayed no problem, but the username is not displayed on any of the screens.
With the webflow the way I did it was created a UserBean that was global to all webflow screens. It was easy to add to the same object from any screen and display any information. How can I achieve the same result for this?
Thank you.
WORKING CODE:
Using SessionAttributes
AddUser.jsp
<%#taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<div id="form">
<h2 >Step 1</h2>
<form:form action="AddUserContact" commandName="user" method="POST">
<table>
<tr>
<td>User Name:</td>
<td><form:input type="text" id="username" path="username"/></td>
</tr>
<tr>
<td><input type="submit" value="Next"/></td>
</tr>
</table>
</form:form>
</div>
AssUserContact.jsp
<div id="form">
<h2 >Step 2</h2>
<form:form action="UserSummaryConfirm" commandName="user" method="post">
<table>
<tr>
<td>Address:</td>
<td><input type="text" id="address" path="address"/></td>
</tr>
<tr>
<td><input type="submit" value="Next"/></td>
</tr>
</table>
</form>
</div>
UserSummaryConfirm.jsp
<h2>Step 3</h2>
<form:form action="home" method="get">
<table>
<tr>
<td>User Name:</td>
<td><%=session.getAttribute("username")%></td>
</tr>
<tr>
<td>Address:</td>
<td><%=session.getAttribute("address")%></td>
</tr>
<tr>
<td>Confirm</td>
</tr>
</table>
</form:form>
AddUserController.java
#Controller
#SessionAttributes({ "username", "address" })
public class AddUserController{
User usr = new User();
#RequestMapping(value = "AddUser")
public String loadIndex(Model model, User user) {
model.addAttribute("User", user);
return "AddUser";
}
#RequestMapping(value = "AddUserContact")
public String processUserName(Model model, User user) {
usr.setUsername(user.setUsername());
model.addAttribute("User", user);
return "AddUserContact";
}
#RequestMapping(value = "UserSummaryConfirm")
public String processUserContact(Model model, User user) {
usr.setAddress(user.getAddress());
model.addAttribute("username", usr.getUsername());
model.addAttribute("address", usr.getAddress());
return "UserSummaryConfirm";
}
Because in second screen you are using
<tr>
<td>${user.username}</td>
</tr>
User input is not bind to any input so it will not be passed to controller with form data .
While you are using address as
<tr>
<td>Address:</td>
<td><input type="text" id="address" name="address"/></td>
</tr>
As it is bind to input (as you have assigned name="address" which is same as path="name") so its value will be send to controller.
If you want to pass the same object across 3 screens then it's better use #SessionAttribute instead of hiding it and passing again and again.
EDIT :
As you are using session attribute now, remove input element .(which is bind to username) from second screen. Just use instead
<td>session.getAttribute("username")%></td>
I have done a "wizard-style" form like this before. My solution used a single form bean that we put into session for the entire process, and included only the pieces in each page that needs to be added. Spring will not erase a value in the form bean unless you include an input for the given value. We don't use JSR-303, and I don't think this method would work if you are using it. Our validation uses a combination of BindingErrors and custom validation code, so I just setup the code to only validate portions at a time, corresponding to what page the form just submitted.