Can JSP file return a json object for a ajax call? - ajax

I want to call a jsp file to return a json object to my ajax call. is it possible?
if it is possible, could you please share some example code of both the jsp file and jquery ajax code? Thanks in advance.

Lots and lots of example is in web , guess you are Little lazy in searching let me share an example, And i am using a servlet for the server side
Create a bean,
public class Countries {
public Countries(String code,String name)
{
this.setCode(code);
this.setName(name);
}
public Countries() {}
private String code;
private String name;
public void setCode(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
And DAO class to add the data from the database or even hardcode the data,
ArrayList<Countries> countryList = new ArrayList<Countries>();
while(rs.next()) {
Countries country=new Countries();
country.setCode(rs.getString("Code"));
country.setName(rs.getString("Name"));
countryList.add(country);
}
After that create a servlet , which gets the data from the DAO and sends it to the JSP ,
ArrayList<Countries> country=new ArrayList<Countries>();
country=FetchData.getAllCountries();
Gson gson = new Gson();
JsonElement element = gson.toJsonTree(country, new TypeToken<List<Countries>>() {}.getType());
JsonArray jsonArray = element.getAsJsonArray();
response.setContentType("application/json");
response.getWriter().print(jsonArray);
}
And finally a JSP to view ,
<script type="text/javascript">
$(document).ready(function() {
$("#tablediv").hide();
$("#showTable").click(function(event){
$.get('PopulateTable',function(responseJson) {
if(responseJson!=null){
$("#countrytable").find("tr:gt(0)").remove();
var table1 = $("#countrytable");
$.each(responseJson, function(key,value) {
var rowNew = $("<tr><td></td><td></td></tr>");
rowNew.children().eq(0).text(value['code']);
rowNew.children().eq(1).text(value['name']);
});
}
});
$("#tablediv").show();
});
});
</script>
<input type="button" value="Show Table" id="showTable"/>
<div id="tablediv">
<table cellspacing="0" id="countrytable">
<tr>
<th scope="col">Code</th>
<th scope="col">Name</th>
</tr>
</table>
</div>
Hope it helps !!

Related

How to pass loop paramters from JSP to Spring Controller

I am having a loop on my JSP page and want to pass these values in my Spring Controller. On every click on Retry button in JSP, I need all values in my controller for further processing. The code which I tried so far is:
Any help much appreciated.
JSP File
<table class="gridtable">
<tr>
<th>Queue Name</th>
<th>Retry Attempt</th>
<th>Reason for failure</th>
<th>Action</th>
</tr>
<% int i=0; %>
<c:forEach var="queueRowDetail" items="${queueRowDetailList}">
<tr>
<td>${queueRowDetail.queueName}</td>
<td>${queueRowDetail.attempt}</td>
<td>${queueRowDetail.errorDetails}</td>
<td>
<form:form method="post" action="/retry" id="frmFailure_<%=i%>" modelAttribute="queueRowDetail"/>
<form:hidden path="queueName<%=i %>" value="${queueRowDetail.queueName}"/>
<form:hidden path="attempt<%=i %>" value="${queueRowDetail.attempt}"/>
<form:hidden path="errorDetails<%=i %>" value="${queueRowDetail.errorDetails} "/>
<input type="button" value="Retry" onClick="sendobj(<%=i%>)" />
</form>
</td>
</tr>
<% i++; %>
</c:forEach>
function sendObj()
<script>
function sendobj(i)
{
var x = document.getElementById("frmFailure_"+i);
alert(obj);
alert("frmFailure_"+i);
x.submit();// Form submission
}
</script>
QueueRowDetail Class
package com.gartner.gqueuefailureapi.model;
public class QueueRowDetail {
private String queueName;
private String errorDetails;
private int attempt;
private Object payLoad;
public String getQueueName() {
return queueName;
}
public void setQueueName(String queueName) {
this.queueName = queueName;
}
public String getErrorDetails() {
return errorDetails;
}
public void setErrorDetails(String errorDetails) {
this.errorDetails = errorDetails;
}
public int getAttempt() {
return attempt;
}
public void setAttempt(int attempt) {
this.attempt = attempt;
}
public Object getPayLoad() {
return payLoad;
}
public void setPayLoad(Object payLoad) {
this.payLoad = payLoad;
}
}
InderController.Java
#RequestMapping(value = "/retry", method = RequestMethod.POST)
public String retryMessage( #ModelAttribute("queueRowDetail")QueueRowDetail queueRowDetail, ModelMap model) {
model.addAttribute("queuename", queueRowDetail.getQueueName());
return "success";
}

Spring + thymeleaf Validanting integer error Neither BindingResult nor plain target object for bean name available as request attribute

I'm in the process of learning spring and thymeleaf and working on a timekeeping project.
For this I need to validate the number of hours an employee clocks in one day.
I used the tutorial in the spring documentation for this however i keep getting the following error
Neither BindingResult nor plain target object for bean name 'timetable' available as request attribute
Any ideas what I might be doing wrong?
Controller class
#RequestMapping(value="Timetable/AddToTimetable", method = RequestMethod.GET)
public String newUser(Model md) {
md.addAttribute("assignments", serv.findAll());
return "AddToTimetable";
}
#RequestMapping(value = "/createEntry", method = RequestMethod.POST)
public String create(#RequestParam("assignmentId") int assignmentId,
#RequestParam("date") #DateTimeFormat(pattern = "yyyy-MM-dd") Date date,
#RequestParam("hoursWorked") int hoursWorked,
#Valid Timetable timetable, BindingResult bindingResult,
Model md) {
timetable = new Timetable();
timetable.setAssignmentId(assignmentId);
timetable.setDate(date);
timetable.setHoursWorked(hoursWorked);
md.addAttribute("timetables", service.timetableAdd(timetable));
if (bindingResult.hasErrors()) {
return "AddToTimetable";
}
return "redirect:/Timetable";
}
Service class
public BigInteger timetableAdd(Timetable timetable){
KeyHolder keyHolder = new GeneratedKeyHolder();
String sql = "INSERT INTO timetables ( assignmentId, date, hoursWorked) VALUES ( ?, ?, ?)";
template.update(new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement pst = con.prepareStatement(sql, new String[] {"id"});
pst.setInt(1, timetable.getAssignmentId());
pst.setDate(2, new java.sql.Date(timetable.getDate().getTime()));
pst.setInt(3, timetable.getHoursWorked());
return pst;
}
}, keyHolder);
return (BigInteger) keyHolder.getKey();
}
}
Model class
package ro.database.jdbcPontaj.model;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Date;
public class Timetable {
private int timetableId;
private int assignmentId;
private Date date;
private String project;
#NotNull
#Min(0)
#Max(12)
private int hoursWorked;
public int getTimetableId() {
return timetableId;
}
public void setTimetableId(int timetableId) {
this.timetableId = timetableId;
}
public int getAssignmentId() {
return assignmentId;
}
public void setAssignmentId(int assignmentId) {
this.assignmentId = assignmentId;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public int getHoursWorked() {
return hoursWorked;
}
public void setHoursWorked(int hoursWorked) {
this.hoursWorked = hoursWorked;
}
public String getProject() {
return project;
}
public void setProject(String project) {
this.project = project;
}
public Timetable() {
}
public Timetable(int timetableId, String project, Date date, int hoursWorked) {
this.timetableId = timetableId;
this.project=project;
this.date = date;
this.hoursWorked = hoursWorked;
}
public Timetable(int timetableId, int assignmentId, Date date, int hoursWorked) {
this.timetableId = timetableId;
this.assignmentId = assignmentId;
this.date = date;
this.hoursWorked = hoursWorked;
}
}
Html
<form method="post" name="comment_form" id="comment_form" th:action="#{/createEntry}" th:object="${timetable}" role="form">
<p> Project</p><br>
<select name="assignmentId">
<option value="" th:each="assignment: ${assignments}" th:value="${assignment.assignmentId}" th:text="${assignment.assignmentId}"></option>
</select>
<p>Date</p> <br>
<input class="datepicker" type="text" name="date"><br>
<p>Number of hours</p>
<input type="text" name="hoursWorked" th:field="*{hoursWorked}"><br>
<p th:if="${#fields.hasErrors('hoursWorked')}" th:errors="*{hoursWorked}">Age Error</p>
<button type="submit" id="submit" class="btn btn-primary">Submit</button>
</form>
UPDATE:
Timetable (skipping bootstrap divs)
<div class="row">
<div class="col-md-10 title">
<h2>Timetable</h2>
</div>
<div class="col-md-2">
</div>
<div class="col-md-12">
<table class="table table-bordered">
<thead>
<tr>
<th>id</th>
<th>assignment</th>
<th>date</th>
<th>number of hours</th>
</tr>
</thead>
<tbody>
<tr th:each = "timetable: ${timetables}">
<td th:text="${timetable.timetableId}">45</td>
<td th:text="${timetable.project}">vasi</td>
<td th:text="${timetable.date}">1 ian</td>
<td th:text="${timetable.hoursWorked}">3000</td>
</tr>
</tbody>
</table>
Service method for Timetable
#Autowired
JdbcTemplate template;
public List<Timetable> findAll(String loginname) {
String sql = " SELECT timetables.timetableId, timetables.assignmentId, timetables.date, " +
"timetables.hoursWorked, users.username, projects.projectName AS project " +
"FROM timetables INNER join assignments on timetables.assignmentId = assignments.assignmentId " +
"INNER JOIN projects on assignments.projectId = projects.projectId " +
"INNER JOIN users on users.userId = assignments.userId where username= ?";
RowMapper<Timetable> rm = new RowMapper<Timetable>() {
#Override
public Timetable mapRow(ResultSet resultSet, int i) throws SQLException {
Timetable timetable = new Timetable(resultSet.getInt("timetableId"),
resultSet.getString("project"),
resultSet.getDate("date"),
resultSet.getInt("hoursWorked"));
return timetable;
}
};
return template.query(sql, rm, loginname);
}
The controller method for Timetable
#RequestMapping(value = {"/Timetable"}, method = RequestMethod.GET)
public String index(Model md){
org.springframework.security.core.Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String loginname = auth.getName();
md.addAttribute("timetables", service.findAll(loginname));
return "Timetable";
}
If I understand correctly you have two html pages one that shows all the assignments and one that you enter the new entry.I think that get the error when there is a validation error in the new entry page.
Substitute these lines
if (bindingResult.hasErrors()) {
return "AddToTimetable";
}
with these ones
if (bindingResult.hasErrors()) {
return "newEntry";//replace the newentry with the html page that you enter the new entry
}
When there is an error, you should go to the page that you tried to enter the new entry and not in the page that has all the assignments.

Submit a List from a form generated with JavaScript with a Spring controller [duplicate]

This question already has answers here:
Passing a list generated with Javascript to a Spring controller
(3 answers)
Closed 5 years ago.
I'm building an app with Spring Boot, the MVC pattern, and Thymeleaf as template engine. I have a form that generates a list with JavaScript, and a controller with a #ModelAttribute expecting a list, to be saved into the database.
At the JavaScript side I collect the items with this array:
groupList = [];
groupList.push(inputValue);
function getGroupList(){
return groupList;
}
In the html I'm trying to assign the array value to a hidden input field:
<input type="hidden" class="invisible" id="groupList" th:field="*{groupList}"/>
With this inline function:
<script th:inline="javascript" type="text/javascript">
$(function() {
var groupListCollected = getGroupList();
$("#groupList").val(groupListCollected);
});
</script>
My problem at this point, is that I don't find the way to collect the array, and pass it to the Controller as a list.
This is the value that the console shows, for the input field:
<input type="hidden" class="invisible" id="groupList" name="groupList"
value="[object HTMLInputElement]">
Any advice to face this issue, would be much appreciated. Thanks in advance.
You can proceed like this :
Create a Model, for exemple:
public class User {
private String username;
public User() {
}
public User(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
Create a FormModel:
public class FormUsers {
private List<User> listUsers;
public FormUsers(List<User> listUsers) {
this.listUsers = listUsers;
}
public FormUsers() {
}
public List<User> getListUsers() {
return listUsers;
}
public void setListUsers(List<User> listUsers) {
this.listUsers = listUsers;
}
#Override
public String toString() {
return "FormUsers{" + "listUsers=" + listUsers + '}';
}
}
in your controller (Get and Post) :
#RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello(ModelMap model) {
FormUsers formUsers = new FormUsers();
List<User> list = new ArrayList<>();
list.add(new User("Wassim"));
formUsers.setListUsers(list);
logger.debug("--> " + formUsers.toString());
model.addAttribute("formUsers", formUsers);
return "hello";
}
#RequestMapping(value = "/hello", method = RequestMethod.POST)
public String helloPost(#ModelAttribute FormUsers formUsers, ModelMap model) {
logger.debug("Get List of new users --> " + formUsers.toString());
return "hello";
}
In my view (hello.html) : for listing all users :
<button id="addAction">ADD</button>
<form action="#" th:action="#{/hello}" th:object="${formUsers}" method="post">
<ul id="myUl">
<input type="text" th:field="*{listUsers[0].username}" />
</ul>
<input type="submit" value="Submit" />
</form>
Now if I want to add another user with javascript when I clic in the button 'ADD, I will append() a new 'li' element containing the new user :
<script type="text/javascript">
$(document).ready(function () {
console.log("ready!");
$("#addAction").click(function () {
console.log("FUNCTION");
$("#myUl").append('<li><input id="listUsers1.username" name="listUsers[1].username" value="Rafik" type="text"/></li>');
});
});
</script>
When I Submit, I will get a list with 2 User : 'Wassim' & 'Rafik'.
You can manage this exemple (also the index of the list must managed properly) to append your list with the needed DATA.

Use a single freemarker template to display tables of arbitrary pojos

Attention advanced Freemarker gurus:
I want to use a single freemarker template to be able to output tables of arbitrary pojos, with the columns to display defined separately than the data. The problem is that I can't figure out how to get a handle to a function on a pojo at runtime, and then have freemarker invoke that function (lambda style). From skimming the docs it seems that Freemarker supports functional programming, but I can't seem to forumulate the proper incantation.
I whipped up a simplistic concrete example. Let's say I have two lists: a list of people with a firstName and lastName, and a list of cars with a make and model. would like to output these two tables:
<table>
<tr>
<th>firstName</th>
<th>lastName</th>
</tr>
<tr>
<td>Joe</td>
<td>Blow</d>
</tr>
<tr>
<td>Mary</td>
<td>Jane</d>
</tr>
</table>
and
<table>
<tr>
<th>make</th>
<th>model</th>
</tr>
<tr>
<td>Toyota</td>
<td>Tundra</d>
</tr>
<tr>
<td>Honda</td>
<td>Odyssey</d>
</tr>
</table>
But I want to use the same template, since this is part of a framework that has to deal with dozens of different pojo types.
Given the following code:
public class FreemarkerTest {
public static class Table {
private final List<Column> columns = new ArrayList<Column>();
public Table(Column[] columns) {
this.columns.addAll(Arrays.asList(columns));
}
public List<Column> getColumns() {
return columns;
}
}
public static class Column {
private final String name;
public Column(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public static class Person {
private final String firstName;
private final String lastName;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
public static class Car {
String make;
String model;
public Car(String make, String model) {
this.make = make;
this.model = model;
}
public String getMake() {
return make;
}
public String getModel() {
return model;
}
}
public static void main(String[] args) throws Exception {
final Table personTableDefinition = new Table(new Column[] { new Column("firstName"), new Column("lastName") });
final List<Person> people = Arrays.asList(new Person[] { new Person("Joe", "Blow"), new Person("Mary", "Jane") });
final Table carTable = new Table(new Column[] { new Column("make"), new Column("model") });
final List<Car> cars = Arrays.asList(new Car[] { new Car("Toyota", "Tundra"), new Car("Honda", "Odyssey") });
final Configuration cfg = new Configuration();
cfg.setClassForTemplateLoading(FreemarkerTest.class, "");
cfg.setObjectWrapper(new DefaultObjectWrapper());
final Template template = cfg.getTemplate("test.ftl");
process(template, personTableDefinition, people);
process(template, carTable, cars);
}
private static void process(Template template, Table tableDefinition, List<? extends Object> data) throws Exception {
final Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("tableDefinition", tableDefinition);
dataMap.put("data", data);
final Writer out = new OutputStreamWriter(System.out);
template.process(dataMap, out);
out.flush();
}
}
All the above is a given for this problem. So here is the template I have been hacking on. Note the comment where I am having trouble.
<table>
<tr>
<#list tableDefinition.columns as col>
<th>${col.name}</th>
</#list>
</tr>
<#list data as pojo>
<tr>
<#list tableDefinition.columns as col>
<td><#-- what goes here? --></td>
</#list>
</tr>
</#list>
</table>
So col.name has the name of the property I want to access from the pojo. I have tried a few things, such as
pojo.col.name
and
<#assign property = col.name/>
${pojo.property}
but of course these don't work, I just included them to help convey my intent. I am looking for a way to get a handle to a function and have freemarker invoke it, or perhaps some kind of "evaluate" feature that can take an arbitrary expression as a string and evaluate it at runtime.
?eval is (almost?) always a bad idea, because it often comes with performance drawbacks (e.g. a lot of parsing) and security problems (e.g. "FTL injection").
A better approach is using the square bracket syntax:
There is an alternative syntax if we want to specify the subvariable name with an expression: book["title"]. In the square brackets you can give any expression as long as it evaluates to a string.
(From the FreeMarker documentation about retrieving data from a hash)
In your case I'd recommend something like ${pojo[col.name]}.
Found the answer.
${("pojo." + col.name)?eval}

Stripes: I can pre-populate a form, but after submit the formBean is null

I can pre-populate my Stripes JSP form with an object, client in my case, but when I submit this form, my object is returning as null.
I have created a second "temp" object that is a parallel duplicate of client and this retains its values, so I can't see an issue passing an object in the request
My form is as follows :
<s:form beanclass="com.jameselsey.salestracker.action.ViewClientAction">
<s:hidden name="clientA" value="${actionBean.clientA}"/>
<s:hidden name="clientId" value="${actionBean.clientId}"/>
<table>
<tr>
<td>Name : </td>
<td><s:text name="client.name"/></td>
</tr>
<tr>
<td>Sector : </td>
<td><s:text name="client.sector"/></td>
</tr>
<!-- omitted some attirbutes, not needed here -->
</table>
</s:form>
My action looks like
public class ViewClientAction extends BaseAction
{
#SpringBean
ClientService clientService;// = new ClientService();
private Integer clientId;
private Client client;
private Client clientA;
public void setClient(Client client)
{
this.client = client;
}
public Integer getClientId()
{
return clientId;
}
public void setClientId(Integer clientId)
{
this.clientId = clientId;
}
public Client getClientA()
{
return clientA;
}
public void setClientA(Client clientA)
{
this.clientA = clientA;
}
public Client getClient()
{
return client;
}
#DefaultHandler
public Resolution quickView()
{
clientA = clientService.getClientById(clientId);
client = clientService.getClientById(clientId);
return new ForwardResolution("/jsp/viewClientQuickView.jsp");
}
public Resolution save()
{
clientService.persistClient(client);
return new ForwardResolution("/jsp/reports.jsp");
}
public Resolution viewClientInfo()
{
client = clientService.getClientById(clientId);
return new ForwardResolution("/jsp/viewClientClientInfo.jsp");
}
...
If I set a breakpoint at clientService.persistClient(client); I can see that ClientA has all of the original values of the object, yet client is nulled.
Have I missed something that binds the form bean to the client object in my action?
Thanks
Add this line in your JSP:
<s:hidden name="client" value="${actionBean.client}"/>
I got this scenario working by adding a #Before method to re-hydrate the nested object. After this, save works properly
#Before(stages = LifecycleStage.BindingAndValidation)
public void rehydrate() {
if (context.getRequest().getParameter("save")!=null){
this.domainObject = getHibernateSession().load(DomainObject.class, context.getRequest().getParameter("id"));
}
}
public void save(){
Session session=getHibernateSession();
session.update(domainObject);
session.commit();
//...
}

Resources