I am working on HTML tables. For that I am returning JSON from my Java code. I have a UI as HTML page where there is a form having from date to date and a select tag having 4 options like this
<form id="formId" method="get">
<div class="container">
<h4>Start Date:</h4>
<input type="text" id="startdate" name="fromdate" width="276"
placeholder="dd/mm/yyyy" required />
<h4>End Date:</h4>
<input type="text" id="enddate" name="todate" width="276"
placeholder="dd/mm/yyyy" required />
<h4>Outlets:</h4>
<select name="outlet" id="all">
<option>ALL</option>
<c:forEach var="item" items="${obj.outlet}">
<option>${item}</option>
</c:forEach>
</select>
<br>
<br>
<div>
<button id="button" class="btn btn-default" type="submit">Search</button>
</div>
</div>
</form>
I am taking that input from the form and getting values in the servlet in doget method like below:
String fromdate=request.getParameter("fromdate");
String todate=request.getParameter("todate");
String outlet=request.getParameter("outlet");
// System.out.println(String.format("fromdate: %s, todate: %s, outlet: %s", new Object[]{fromdate, todate, outlet}));
List<String> outletList = Arrays.asList(outlet.split("\\s*,\\s*"));
try {
String json = HourlySalesDateOutlet.createJson(outletList, fromdate, todate);
response.getWriter().write(json);
// System.out.println("dheeraj"+json);
}
catch (Exception e) {
e.printStackTrace();
}
}
Now here is my Java class where I have written two queries one for if the user selects all and other if user select specific outlet. My problem is the if statement is not executing only else is executing if the user selects one outlet from FORM if the user selects ALL then it's not working.
Below is my code:
public static String createJson(List<String> outletList, String startDate, String endDate) throws Exception {
Connection con = null;
String query1;
List<Map<String, String>> mapList = new LinkedList<Map<String, String>>();
String outletStr = outletList.stream().collect(Collectors.joining("','", "('", "')"));
if (outletList.equals("ALL")) {
query1 = "SELECT a.OUTLET,b.CUSTOMERDESCRIPTOR,a.BILLDATE,HOUR(a.BILLTIME) AS HOURS, SUM(a.NETAMOUNT) AS AMOUNT FROM SYNCBILL a,ecustomer b WHERE a.OUTLET=b.CUSTOMERIDENTIFIER AND a.CANCELLED<>'Y' AND a.BILLDATE BETWEEN STR_TO_DATE(REPLACE('"
+ startDate + "','/','.'),GET_FORMAT(DATE,'EUR')) AND STR_TO_DATE(REPLACE('" + endDate
+ "','/','.'),GET_FORMAT(DATE,'EUR')) GROUP BY OUTLET,BILLDATE,HOUR(BILLTIME)";
System.out.println("all"+query1);
} else {
query1 = "SELECT a.OUTLET,b.CUSTOMERDESCRIPTOR,a.BILLDATE,HOUR(a.BILLTIME) AS HOURS, SUM(a.NETAMOUNT) AS AMOUNT FROM SYNCBILL a,ecustomer b WHERE a.OUTLET=b.CUSTOMERIDENTIFIER AND b.CUSTOMERDESCRIPTOR in "
+ outletStr + " AND a.CANCELLED<>'Y' AND a.BILLDATE BETWEEN STR_TO_DATE(REPLACE('" + startDate
+ "','/','.'),GET_FORMAT(DATE,'EUR')) AND STR_TO_DATE(REPLACE('" + endDate
+ "','/','.'),GET_FORMAT(DATE,'EUR')) GROUP BY OUTLET,BILLDATE,HOUR(BILLTIME)";
System.out.println("2"+query1);
}
try {
con = DBConnection.createConnection();
PreparedStatement ps = con.prepareStatement(query1);
ResultSet rs = ps.executeQuery();
Map<RecordKey, Long> mapData = getMapList(rs);
}
I am not posting the full Java code. What I want is if the user selects all then if statement should execute and the query in it should execute. If the user selects else, then other should work, and here in my code only else is working if is not executing.
How can I debug this?
I have a simple solution for your problem. When user selects all, then in that case pass the empty list and while making the query just put this condition.
if (outletList.size()==0) {
// case for all
} else {
// do regular stuff
}
As pointed out in the comments, you're not comparing comparable types. outletList is a List and it can't be equated to a String even though the list may only contain a single element that happens to be a String. So, outletList.equals("ALL") doesn't do what you think it does.
But that raises an interesting point. You have a select list which isn't multiple so why return a list of what is always a single value? And why switch to sending back an empty list when ALL is selected? That doesn't make sense; there was a single selection made as expected. This adds unnecessary confusion.
Try instead sending back the single value as a String and letting that value determine the logic so you have flexibility. If it's not possible to avoid the list then accept only a single value (list[0] for example) and call equals on that not the List.
if(outletList[0].equals("All")) {...}
If you later find yourself in a situation where you need more than a single if-else pair, you can switch to a switch like so:
switch(outletList[0]) { // or the single value...
case "ALL":
...
...
default:
...
}
Related
I am new to grails and I am a bit confused about how to use <g:paginate>.
I have a table and I want to set the max number of entrees to 10. Most of the examples I find online have used a List and have a set of jobs and services that help create the navigation. I am confused about this because I did not use a list in my controller. The total number of entrees is going through, but every entree is still displayed. If I click on page 2 or a 'next' button, it seems that my controller loses track of the sourceVolume that the user selected to generate this list.
For context - the first page the user sees prompts them to select a source volume - and from there a table is generated that shows a list of all of the entrees(snapshots) in the source volume.
my selectSnapshotVolume.gsp
<g:form class = "myForm" url="[controller:'Vaultrecovery', action:'doRecoveryConfirmation', method:'post']">
<table class = "content-table">
<thead>
<tr>
<th>Select</th>
<th>Cluster</th>
<th>Vserver</th>
<th>Volume</th>
<th>SnapShot</th>
</tr>
</thead>
<tbody>
<g:each in="${destinationVolumes}" var="destinationVolume">
<tr>
<td><g:radio name="snapshot" value="$destinationVolume.snapshot" required="true"></g: radio></td>
<td>
${destinationVolume.cluster}
</td>
<td>
${destinationVolume.vserver}
</td>
<td>
${destinationVolume.volume}
</td>
<td><b>
${destinationVolume.snapshot}
</b></td>
</tr>
<g:hiddenField name="cluster" value="${destinationVolume.cluster}" />
<g:hiddenField name="vserver" value="${destinationVolume.vserver}" />
<g:hiddenField name="volume" value="${destinationVolume.volume}" />
</g:each>
</tbody>
</table>
<div class = "centerMe">
<div class="pagination">
<g:paginate controller='Vaultrecovery' total="${entreeCount.total[0] ?: 0}" />
</div>
</div>
<div class = "centerMeDescription">
<g:submitButton class="submit " name="submit" value="Submit"/>
</div>
</g:form>
and here is my controller. I do not have any services, jobs, or a domain class. I have also cut out parts of the controller that are irrelevant.
class VaultrecoveryController {
def dataSource_model // netapp_model
def dataSource // dataautomation
def mailService
File testFile = new File("/opt/tomcat/work/TEST")
boolean TEST = testFile.exists()
def index() { }
def selectSourceVolume() {
log.info "Vaultrecovery Controller - selectSourceVolume"
def foo = new Sql(dataSource_model)
String SQL
SQL = "SELECT distinct(name) FROM volume WHERE (name NOT LIKE '%_dest%' AND name NOT LIKE 'MDV%' AND name NOT LIKE '%\\_\\_%') ORDER BY name"
log.info "Getting source volumes: " + SQL
def sourceVolumes = foo.rows(SQL)
[sourceVolumes: sourceVolumes]
} // end selectSourceVolume
def selectSnapshotVolume() {
log.info "Vaultrecovery Controller - selectSnapshotVolume"
def sourceVolume = params.srcvolume
log.info "SOURCE VOLUME IS: " + sourceVolume
def foo = new Sql(dataSource)
String SQL
SQL = "SELECT cluster, vserver, volume, snapshot FROM netapp_vault WHERE volume LIKE '%" + sourceVolume + "%' ORDER BY snapshot"
log.info SQL
def destinationVolumes = foo.rows(SQL)
SQL = "SELECT COUNT(cluster) as total FROM netapp_vault WHERE volume LIKE '%" + sourceVolume + "%' ORDER BY snapshot"
def entreeCount = foo.rows(SQL);
[sourceVolume: sourceVolume, destinationVolumes: destinationVolumes, entreeCount: entreeCount]
} // end selectSnapshotVolume
}
You lost the search criteria because the Prev or the Next button did not POST your Source Volume value back to the controller.
I had the same problem in my project. Took me half the day to figure it out. If you check the HTML what the Prev and the Next button is, they only POST back the Max and Offset values back to the controller. Keep this in mind. This kind of project is state-less. So, your action will reset back to the initial state.
Next
I use a private variable to store my last used search criteria. My action checks if the private variable has anything. If so, it use the criteria from the private variable to run the SQL. So, I will get the same records from the page before. I then apply the Max and Offset to get the correct records.
Something like this:
class BookController {
private String _searchString = ''
def index() {
_searchString = (params.searchString == null) ? _searchString : params.searchString
bookList = Book.findAllByName(_searchString, params)
}
}
params.searchString will be null because the Prev/Next button does not POST back the searchString. If it is null, I grab the searchString from the private variable _searchString and use it in my dynamic finders. I am lucky that Grails did not reset the _searchString variable when the Prev/Next calls the action.
Following is my jsp code.
<c:forEach items="${nameList}" var="studentList">
<tr>
<td style="padding-bottom: .5em;">
<a id="student" href="number?regNo=<c:out value="${studentList.regNo}"/>">
<span class="eachStudent">
<span class="studentName"><c:out value="${studentList.name}"/></span><br/>
<span class="collName"><c:out value="${studentList.collName}"/></span><br/>
<span class="deptName"><c:out value="${studentList.deptName}"/></span><br/>
</span>
</a>
</td>
</tr>
</c:forEach>
The above c:forEach lists
Name CollName DeptName
ABCD coll1 dept1
kfkdb coll1 dept2
jbdd coll2 dept3
Following is the code that lists the collName and deptName respectively.
<div>
Filter students by College (not required):
<select id="byCollege" name="byCollege" >
<c:forEach items="${uniqueCollList}" var="uniqueCollList">
<option value="${uniqueCollList}"/>
${uniqueCollList}</option >
</c:forEach >
</select >
</div>
<div>
Filter students by Department Name (not required):
<select id="byDept" name="byDept" >
<c:forEach items="${uniqueDeptList}" var="uniqueDeptList">
<option value="${uniqueDeptList}"/>
${uniqueDeptList}</option >
</c:forEach >
</select >
</div>
Now when I select a value from first dropdown, I want to filter the results given by foreach using the value selected in dropdown. I would like to do this in front end itself, rather going to the back end. May I know how can I do this?
After filtering the c:foreach result using value of first dropdown, if I select a value in second dropdown, I want the updated result of c:foreach to be filtered using the value selected in second drop down.
How can I do this?
If I want to do this in back end, what should I do?
PS:Following is the controller code that sends the list first time
#RequestMapping(value = "/name", method = RequestMethod.POST, params = { "studentName" })
public String searchStudentByCollOrDept(#RequestParam(value = "studentName", required = true)String studentName, ModelMap model){
List<OneStudentResult> nameList = resultService.getStudentList(studentName);
//TODO, null value check.
if(nameList.size() == 0 || nameList == null){
return "header";
}
if(nameList.size() != 0){
// Iterate the list that we get and add only one time a collName and deptname.So a Treeset.
Set<String> uniqueCollList = new TreeSet<String>();
Iterator<OneStudentResult> itr = nameList.iterator();
while(itr.hasNext()){
String collName = itr.next().getCollName();
if(!uniqueCollList.contains(collName)){
uniqueCollList.add(collName);
}
}
uniqueCollList.add(" Select a College ");
model.addAttribute("uniqueCollList", uniqueCollList);
Set<String> uniqueDeptList = new TreeSet<String>();
Iterator<OneStudentResult> itrDeptList = nameList.iterator();
while(itrDeptList.hasNext()){
String deptName = itrDeptList.next().getDeptName();
if(!uniqueDeptList.contains(deptName)){
uniqueDeptList.add(deptName);
}
}
uniqueDeptList.add(" Select a Department ");
model.addAttribute("uniqueDeptList", uniqueDeptList);
}
model.addAttribute("nameList", nameList);
return "nameResult";
}
I'm afraid there is no simple solution to your problem. You should consider doing this server-side with ajax updates. Client side filtering would either require you to parse the data from the HTML generated by your studentList or it would require you to inject the data as a JSON formatted array. In both cases you would end up with doubled data (server & client). Having the data on the client-side would only allow you to disable some of the option values, not hide them. So if you want real filtering in terms of not-showing some of the options then you should filter your lists on the server. To do so you should post the selected option from your first dropdown "byCollege" to your backend in order to retrieve a filtered "uniqueDeptList" that you use to rebuild the "byDept" checkbox. You might want to use jQuery for both tasks.
Steps:
1. Handle the change-event of the "byCollege" dropdown
2. Post the selected option value to your servlet
3. Filter the data in your servlet and return the filtered data as POST response (omitted in this example)
4. Remove the old select options and recreate them from the filtered data
$("#byCollege").change(function() {
$("select option:selected").first().each(function() {
// Get and convert the data for sending
// Example: This variable contains the selected option-text
var outdata = $(this).text();
// Send the data as an ajax POST request
$.ajax({
url: "yourjsonservlet",
type: 'POST',
dataType: 'json',
data: JSON.stringify(outdata),
contentType: 'application/json',
mimeType: 'application/json',
success: function(data) {
// Remove old select options from the DOM
$('#byCollege')
.find('option')
.remove()
.end();
// Parse data and append new select options
//(omitted here; e.g. $('#byCollege').append($("<option>").attr(...))
},
error: function(data, status, er) {
alert("error: " + data + " status: " + status + " er:" + er);
}
});
});
});
i am using jquery to get values from database via servlet. callback function in my script gives me raw information from database.how can i append these values to select option in jsp.
here is my Retrive_country servlet code:
String sql1 = "SELECT * FROM state WHERE country_ref="+countryref+"
PreparedStatement pst1 = db.getConnection().prepareStatement(sql1);
ResultSet j = pst1.executeQuery();
while (j.next()) {
state_id = j.getString(1);
state = j.getString(2);
country_ref = j.getString(3);
location.setState(state);
location.setState_id(state_id);
location.setcountry_ref(country_ref);
pw.println(state_id);
pw.println(state);
pw.println(country_ref);
}
here is my script:
<script>
$(document).ready(function(){
$("#country_id").change(function() {
var xyz = $("option:selected").val();
alert(xyz)
$.get("../Retrive_country?countryREF="+xyz",
{countryREF : xyz },
function(data){
console.log(data);
alert("Data: " + data);
});
});
});
</script>
here is my jsp:
<div class="span2 clear">
<select name="country_id" id="country_id">
<option>-select-</option>
<option id="blabbb">1</option>
<option id="blabbb">2</option>
<option id="blabbb">3</option>
</select></div>
<div class="span2 clear">
<select name="state_ref" id="state_ref">
<option ></option>
</select></div>
here is my output in console:
all the strings are state values and integers are stateid.
i want them to be used separately in jsp.
You should better use a backend JSON encoder. But this manual encode should work, too:
Backend code:
pw.println("[");
while (j.next()) {
state_id = j.getString(1);
state = j.getString(2);
country_ref = j.getString(3);
pw.println("{stateId: " + state_id + ", stateName: \"" + state +"\"},");
}
pw.println("]");
(I'm assuming your state_id is integer)
Client code:
$("#country_id").change(function() {
var xyz = $("option:selected").val();
$.get("../Retrive_country?stateadd_1=none", {countryREF : xyz }, function(data){
var states = eval(data);
$('#state_ref').empty();
$.each(states, function(index, state){
$("<option></option>")
.attr("value", state.stateId).text(state.stateName)
.appendTo('#state_ref');
});
}, 'text');
});
Cheers, from La Paz, Bolivia
Assuming you can send data as json. You can do this:
var Myselect = $('#state_ref');
$.getJSON("../Retrive_country?stateadd_1=none",
{countryREF : xyz } ,function(data){
$.each(data, function(key, value) {
Myselect
.append($("<option></option>")
.attr("value",key)
.text(value));
});//end each
});//end get
If not in json format, can you show what your data looks like?
DO NOT USE + in the PreparedStatement query!!
It's intended for using things like
String sql1 = "SELECT * FROM state WHERE country_ref=?"
PreparedStatement pst1 = db.getConnection().prepareStatement(sql1)
pst1.setInteger(0,country_ref);
ResultSet j = pst1.executeQuery();
It is because of SQL injection. As described, the easiest way to escape that injection type is using prepared statements properly. Please read more about using PreparedStatement
I have been finding it difficult to understand where I am going wrong. I understand that we should move with the times but I am not sure how to replace a scriptlet, that I can get to do the job, with the JSTL taglibrary functions.
I have a Model class called Ranges.class which contains a rangeName (String) and a startRange (BigDecimal) and an endRange (BigDecimal) value. I have a DAO class that handles all the db queries (crud type methods). I have a method in RangesDao.class called getAllRanges() which will get all the potential ranges from a mysql db and return a List. This will fetch all the Range objects which include the rangeName, startRange and endRange.
Q: So basically what I want to do is from my jsp page when a text input is selected I want to check if it is between the start and end value of each Range object (that was returned in the List) and when I have a match I want to update a different text input with that objects rangeName value.
This is what I have so far.
Range.class
package za.co.zs6erb.model;
import java.math.BigDecimal;
public class Range {
private int range_id;
private String rangeName;
private BigDecimal startRange;
private BigDecimal endRange;
//...getters and setters for each of the above variables ...
#Override
public String toString() {
return "Ranges [range_id=" + range_id + ", Range Name=" + rangeName + ", Start Range=" + startRange
+ ", End Range=" + endRangeBand + "]";
}
}
DAO Class: This is the getAllRanges() method
public List<Range> getAllRanges() {
List<Range> rangeList = new ArrayList<Range>();
try {
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery("select * from ranges order by range_id");
while (rs.next()) {
Range lRange = new Range();
lRange.setID(rs.getInt("range_id"));
lRange.setRangeName(rs.getString("rangeName"));
lRange.setStartRange(rs.getBigDecimal("start_range"));
lRange.setEndRange(rs.getBigDecimal("end_range"));
rangeList.add(lRange);
}
} catch (SQLException e) {
e.printStackTrace();
}
return rangeList;
}
Controller: This class has a doGet() and a doPost() method the piece I am busy with is the doGet(). The doPost() is used when adding a "plannedRoute" object (just an object that has several other attributes that need to be added to a different table. - not the issue here) From the doGet() I list all the "plannedRoute" objects which all have one Range associated with each. When adding a new route I launch a jsp page from the doGet() method. The following part should make things a little clearer.
doGet():
private static String LIST_PLANNEDROUTES = "plannedroutes.jsp";
private RangeDao rDao;
//Constructor
public PlannedRouteController() {
super();
rDao = new RangeDao();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String forward = "";
String action = request.getParameter("action");
if (action.equalsIgnoreCase("new")) {
forward = LIST_PLANNEDROUTES;
request.setAttribute("rd", rDao);
}
RequestDispatcher view = request.getRequestDispatcher(forward);
view.forward(request, response);
}
So now we have the crux of the issue ...
plannedRoutes.jsp
<%# page language="java" contentType="text/html; charset=EUC-KR" pageEncoding="EUC-KR"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>MyTest</title>
<script src="sj/jquery.js"></script>
<script type="text/javascript">
//<!--
$(document).ready(function(){
$("#range").change(function() {
alert("A Range was entered");
<c:forEach var="entry" items="${rd}">
alert( "HERE>" + ${entry.rangeName});
</c:forEach>
document.getElementById("testName").value = $("#range").val();
});
});
//-->
</script>
</HEAD>
<BODY>
<form method="POST" action='<form method="POST" action='ContactController' name="frmAddContact">' name="frmAddRoute">
Range: <input type="text" id="range" name="range" />
Name: <input type="text" id="testName" name="testName" readonly />
<!-- a whole bunch of other stuff here -->
</form>
</BODY>
</HTML>
Q: So when the value in the range input text field changes (I call the method in the tag and there I want to step through the List and match what was typed in to see if it falls between the start and end range of any of the Range Objects. When I find a match I want to be able to fetch the rangeName attribute of that object and add that to the testName input text area.
I hope this is clear enough. I have tried the without success and am not sure where to go from here without using scriptlets ... Any help would be appreciated.
Kind Regards
Sean
First, you're putting the DAO object into the request, but in the jsp you want to access the list that the DAO method would return. Call the method in your controller and put the resulting list into the request.
request.setAttribute("rd", rDao.getAllRanges());
The rest all needs to be client-side code unless you want to change your design to use ajax. Try serializing the range list, in the controller, into a JSON string. Then in your jsp, you'll be giving javascript access to the data. Let's say you're using Gson to serialize in your servlet:
request.setAttribute("rd", new Gson().toJson(rDao.getAllRanges(), List.class));
So when you access ${rd} in the jsp, it will be a String in the following form:
[{"range_id":1,"rangeName":"Range 1", "startRange":10.0, "endRange":19.99},{"range_id":2,"rangeName":"Second Range", "startRange":18.75, "endRange":29.5}]
In the jsp, you set that as a javascript variable that can be accessed by your change function.
$("#range").change(function() {
var rdArray = ${rd};
alert("A Range was entered");
var floatVal = parseFloat($("#range").val());
var rangeFound = false;
var rdSize = rdArray.length;
var index = 0;
while (index < rdSize && !rangeFound)
{
var rangeObject = rdArray[index++];
if (floatVal >= rangeObject.startRange && floatVal <= rangeObject.endRange)
{
rangeFound = true;
$('#testName').val(rangeObject.rangeName);
}
}
});
I can't figure out why i can't get an input value from a jsp. I'm using for cycle to make several input fiels for "choices", but when i'm trying to get values from a mvcportlet, it get nothing.
<aui:form action="<%=addPollURL%>">
<aui:fieldset>
<%
int optionCount = Integer.parseInt(optionCountS);
for (int i = 0; i < optionCount; i++) {
%>
<aui:input label="<%=Integer.toString(i + 1)%>" name="choice<%=i%>"
type="text" />
<%
}
%>
<aui:button-row>
<aui:button value="Add poll" type="submit" />
</aui:button-row>
</aui:fieldset>
</aui:form>
Here goes mvcportlet method
List<String> choices = new ArrayList<String>();
int count = Integer.parseInt(actualChoiceCount);
for (int i = 0; i < count; i++) {
System.err
.println("another choice"
+ ParamUtil
.getString(
actionRequest,
("choice" + i)));
choices.add(new String(ParamUtil.getString(actionRequest,
("choice" + i))));
}
Its really weird... but some ideas or tests
Is AddPollUrl an Action URL with named action and so your action is executed in your generic portlet?
Are you sure text fields are populated with values in the UI (there is no no explicit value in tag)? ParamUtil output would be the same without value that with a blank value
Try without type=text and write it as a single line (input tags)
Try aui:submit instead of aui:button type submit
Try adding an id to form or fields (Ive seen some problems with repeated forms if they dont have namespace)
Why new String(ParamUtil...)?
the most important... whats the output of your System.outs?
That happens because your input field has no value. Or at least it seems so.
You should modify the input to have the value parameter set to "choiceX" like:
<aui:input label="<%=Integer.toString(i + 1)%>" name="choice<%=i%>"
type="text" value="choice<%=i%>" />
Then you'll find it in actionRequest, like Jonny said:
request.getParameter("choice"+i);
This will return you the value of the input field, searching by it's name. So you can have your choice in the processAction method.
Regards !
Try using:
actionRequest.getParameter("choice" + i);
That's not the standard way of getting POST params from the request.