retrieve data from database in struts - java

I am retrieving all databases data with struts framework,code is working good.
i just put list(Array list) of data in request for JSP(as above code).i know we can get data with logic tag library but i don't have much idea of that.and is it okay to put data in request?and how we can retrive data with logic library?or any other way?
HashMap hm =null;
List list = new ArrayList();
String uname="";
int no=0;
while(rs.next())
{
uname=rs.getString(1);
no = Integer.parseInt(rs.getString(2));
hm=new HashMap();
hm.put("name", uname);
hm.put("number", no);
list.add(hm);
}
request.setAttribute("myList",list);
jsp page.
<%
try
{
DataForm d= new DataForm();
HashMap hm;
List list = new ArrayList();
if(request.getAttribute("myList")!=null)
list=(List)request.getAttribute("myList");
else
out.print("No Data Found..");
for(int i=1;i<list.size();i++)
{
hm=(HashMap)list.get(i);
%><tr> <td><%out.println(hm.get("name"));%></td>
<td><%out.println(hm.get("number"));%></td></tr><%
}
}
catch(Exception e){e.printStackTrace();}
%>

The logic tags are not used to retrieve the data: They're used to implement some logic in the JSP without using scriptlets, which are considered bad practice.
It's indeed the job of the controller (the Struts action), not to retrieve the data from the database, but to call objects that will, and to put the list of objects in the request in order for the view to display them.
The struts logic tag, however, are almost all deprecated in favor of the JSP EL and the JSTL. Your scriptlet code could be replaced by the following lines:
<c:choose>
<c:when test="${myList == null}">
No Data Found.
</c:when>
<c:otherwise>
<c:forEach var="element" items="${myList}">
<tr>
<td><c:out value="${element.name}"/></td>
<td><c:out value="${element.number}"/></td>
</tr>
</c:forEach>
</c:otherwise>
</c:choose>
Which is much more readable and escapes the data correctly.
I would also use objects instead of HashMaps to hold your data. Java is an OO language. Use objects and encapsulation.

If I correctly understand what you are trying to do, I must say that you are not making effective use of a HashMap.
A Hashmap is used to store pairs so that you are able to retrieve the values using a key fast ~ O(1). Keys are unique in a hashmap. If you try to store multiple pairs one after the other using the same key, the data will be be overwritten and in the end you will see only the last pair.
In this example, you are using a HashMap just as a container to hold "name" and "number" and hence I don't see a real need for the hashMap at all.
This is what you can do:
Define a class that holds name and number:
class Data
{
private String name;
public int uNo;
public Data(String name, int uNo)
{
this.name = name;
this.uNo = uNo;
}
public getName()
{
return this.name;
}
public getUNo()
{
return this.uNo;
}
}
Your Java Code :
List<Data> list = new ArrayList<Data>();
while(rs.next())
{
String uname=rs.getString(1);
int no = Integer.parseInt(rs.getString(2));
list.add(new Data(uname, no));
}
request.setAttribute("myList",list);
Your Jsp Code:
<%
try
{
DataForm d= new DataForm();
List<Data> list = new ArrayList<Data>();
if(request.getAttribute("myList")!=null)
{
list = (List<Data>)request.getAttribute("myList");
for(Data data in list)
{
%><tr><td><%out.println(data.getName());%></td>
<td><%out.println(data.getUNo());%></td></tr><%
}
}
else
{
out.print("No Data Found..");
}
}
catch(Exception e){e.printStackTrace();}
%>
Now, coming to the Logic Tag Library.
This is what you will need to make the following modifications:
i) In your jsp, you may do this:
Add these lines in the beginning of your jsp:
<%# taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%# taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%>
Use these to write your data:
<logic:present name="myList">
<logic:iterate name="myList" id="myListId">
<tr>
<td><bean:write name="myListId" property="name"/></td>
<td><bean:write name="myListId" property="uNo"/></td>
<tr>
</logic:iterate>
</logic:present>
<logic:notPresent name="myList">
No Data found.
</logic:notPresent>
Ideally, I would have used JSTL to show the list of User/No.
I have not tested this code. But it delivers what I have in mind.

Related

In Spring MVC - model.addAttribute usage for dynamic data and how to place the data in jsp file

Hi I am new to Java world and I am trying to make my own web application with Spring MVC. Now, I am going to read a text file in my local directory, for example, the text file like this:
TestData_FileOne.txt
1,100
2,200
3,300
4,400
5,500
The result I would like to present in a browser page like this (in a table) :
1 2 3 4 5
100 200 300 400 500
so I implemented 1) Controller , 2) Model , and 3)View(.jsp file).
**1) My Controller and 2)Model ([Q1] [Q2]) **
#Controller
public class TestController {
#RequestMapping("/testMVC")
public String testmvc(Model model){
String dirString = "C:/Users/Me/Documents/Test/";
Path testFile;
List<String> testData;
testFile = Paths.get( dirString + "TestData_FileOne.txt");
try {
testData = Files.readAllLines(testFile, StandardCharsets.UTF_8);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
//return "unable to read...";
return "unable to read...";
}
// ====== changes from here based on Aeseir's answer========
List<String> dataNum = new ArrayList<String>();
List<String> data = new ArrayList<String>();
for(int i=0; i<testData.size()-1;i++){
dataNum.add(testData.get(i).split(",")[0]);
data.add(testData.get(i).split(",")[1]);
}
model.addAttribute("dataNum", dataNum);
model.addAttribute("data", data);
// ======= changes until here ==============
return "testMVC";
}
}
(Read the text file works fine when I checked System.out.println part)
2) testMVC.jsp file
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<%# taglib uri="http://www.springframework.org/tags" prefix="spring" %>
<table>
<thread>
<tr>
<th>Table with dynamic data from model</th>
</tr>
</thread>
<tbody>
<c:forEach var="dataNumValue" items="${dataNum}"> [items added but.. Q5]
<tr>
<td>
${dataNumValue}
</td>
</tr>
</c:forEach>
<c:forEach var="dataValue" items="${data}"> [items added but.. Q5]
<tr>
<td>
${dataValue} --- [Q2']
</td>
</tr>
</c:forEach>
</tbody>
</table>
So..I know Q1/Q1' should be match, and Q2/Q2' as well.
1) however, I am confused about the object in model.addAttribute("", object); in Q1, Q2? and addAttribute is the right choice among model attributes?
2) Do I need var="dataNum" and var="data" in Q3, Q4 and did I do correctly?
I appreciate any advice if I made mistake.
Extra Question
so I have updated Controller code and jsp file like the above after Aeseir's answer (Thanks!!) but I have warning in jsp file after I added items then warning (Q5) and of course, the page is not presented.
[Q5]: warning : "items" does not support runtime expressions
I searched for the warning, then advices like check the jstl version - should be above version 1.0 - My jstl version is 1.2. so shouldn't be any problem....
Can you check my changes part? and What else could cause this warning except jstl version?.
Solution for extra question 5
#taglib directive should be like this in jsp file:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> => /jsp was missing in the middle
This #taglib correction + code changes the above based on Aeseir's answer works all fine!
Q1 and Q2
You were almost there. Model will pass most data you put into it. Its up to your rendering page to determine how to display it.
And you will need to change the types to arrays since you want to output multiple strings.
List<String> dataNum = //populate accordingly
List<String> data = // populate accoridngly
model.addAttribute("dataNum", dataNum);
model.addAttribute("data", data);
Q3 and Q4
Yes you do but you need to complete it this way:
<c:forEach var="dataNumValue" items="${dataNum}">
<tr>
<td>
${dataNumValue}
</td>
</tr>
</c:forEach>
<c:forEach var="dataValue" items=${data}>
<tr>
<td>
${dataValue}
</td>
</tr>
</c:forEach>
Hope that helps

Iterating and setAttribute on a request Scope

I've got a List of Products obtained from a database query.
In each Product there is a Date_in and a Date_out variable of Calendar type.
What I want to do is pass these Products to a jsp view, so that I can build a table with all their informations. To do so I need to convert the Calendar dates to a more suitable format (like a String), and I've got an utility for this.
My problem is: How can I pass each converted date_in/date_out to the request.setAttribute, for each Product in the List?
Here's what I've got.
in ProductAction:
List<Product> products = service.viewActiveProducts();
for(Product product: products) {
String date_inToString = DateConversionUtility.calendarDateToString(product.getDate_in());
String date_outToString = DateConversionUtility.calendarDateToString(product.getDate_out());
}
request.setAttribute("products", products);
in the jsp:
<table>
<tr class="index">
<td>Id</td>
<td>Date IN</td>
<td>Date OUT</td>
</tr>
<c:forEach items="${requestScope.products}" var="product">
<tr>
<td>${product.oid}</td>
<td>${product.date_in}</td>
<td>${product.date_out}</td>
</tr>
</c:forEach>
</table>
(Right now product.date_in and product.date_out are in a Calendar format. I want them in a String format).
You can create a custom JSTL function and use it directly in your JSP EL tags.
<td>${product.oid}</td>
<td>${nspace:formatDate(product.date_in)}</td>
<td>${nspace:formatDate(product.date_out)}</td>
Where nspace is the xml namespace assigned to your library and formatDate your method. A couple of links:
http://www.noppanit.com/how-to-create-a-custom-function-for-jstl/
http://anshulsood2006.blogspot.com.es/2012/03/creating-custom-functions-in-jsp-using.html
You can pass entire list to jsp by request.setAttribute(String,Object);
List<Product> products = service.viewActiveProducts();
request.setAttribute("products", products);
Your Product class should be implementing Serializable interface
To get your properties date_in and date_out in string format, convert them into string and have two more properties in Product class with names say dateInString and dateOutString and set their values like
for(Product product: products) {
product.setDateInString(DateConversionUtility.calendarDateToString(product.getDate_in()));
product.setDateOutString(DateConversionUtility.calendarDateToString(product.getDate_out()));
}
In jsp, you can user JSTL to get the properties or field of Products object iterating list
<c:forEach items="${products}" var="product">
<tr>
<td>${product.oid}</td>
<td>${product.dateInString}</td>
<td>${product.dateOutString }</td>
</tr>
</c:forEach>
Make a getDate_inString() and getDate_outString methods in Product bean that will print what you want. Then, in the jsp you can use ${product.date_inString}

More concise way to iterate this treemap data structure in JSTL

I am using the following data structure to store JDBC results in a Servlet controller prior to displaying in a JSP view using JSTL.
TreeMap
- TreeMap
- String[]
Four columns of data are returned per row.
"CATEGORY","OSDIRECTORY","FILENAME","DESCRIPTION"
"CATEGORY","OSDIRECTORY","FILENAME","DESCRIPTION"
"CATEGORY","OSDIRECTORY","FILENAME","DESCRIPTION"
etc.
The goal is to store the results in the data structure as
Category
- FILENAME
- OSDIRECTORY
- DESCRIPTION
And to display the final results in the View as
Category A
Hyperlink
Hyperlink
Hyperlink
Category B
Hyperlink
Hyperlink
etc.
Relevant Servlet Controller Code Snippet
...
TreeMap treeMap = new TreeMap();
rs = stmt.executeQuery(query);
// Gather raw data
while(rs.next()){
if(!treeMap.containsKey(rs.getString("CATEGORY"))){
treeMap.put(rs.getString("CATEGORY"), new TreeMap());
}
String[] tmp = { rs.getString("OSDIRECTORY"), rs.getString("DESCRIPTION") };
((TreeMap)treeMap.get(rs.getString("CATEGORY"))).put(rs.getString("FILENAME"), tmp);
}
request.setAttribute("filemap", treeMap);
RequestDispatcher rd = request.getRequestDispatcher(VIEW_URL);
rd.forward(request, response);
...
Relevant JSP View JSTL Snippet
<c:forEach var="f" items="${filemap}">
<h1><c:out value="${f.key}"/></h1>
<c:forEach var="g" items="${filemap[f.key]}">
<a href="TBD">
<c:out value="${filemap[f.key][g.key][0]}"/>
<c:out value="${filemap[f.key][g.key][1]}"/>
</a>
</c:forEach>
</c:forEach>
I am wondering of there is a more concise way to express some of the JSTL expressions.
For example ${filemap[f.key][g.key][0]} just seems too verbose to me.
I would make objects to represent your data instead of using a map of maps. Since you have categories that contain files, make a category and file objects that look something like this:
public class Category {
private String name;
private List<DbFile> files = new ArrayList<DbFile>();
// getters & setters for each property go here
}
public class DbFile {
private String filename;
private String osDirectory;
private String description;
// getters & setters for each property go here
}
Then in your data access code you can iterate over the result set and build up a list of categories objects like this:
Map<String, Category> categoryMap = new TreeMap<String, Category>();
while(rs.next()){
String categoryName = rs.getString("CATEGORY");
Category category = categoryMap.get(categoryName);
if(!categoryMap.containsKey(categoryName)){
category = new Category();
category.setName(categoryName);
}
DbFile file = new DbFile();
file.setFilename(rs.getString("FILENAME"));
file.setOsDirectory(rs.getString("OSDIRECTORY"));
file.setDescription(rs.getString("FILENAME"));
category.getFiles().add(file);
categoryMap.put(categoryName, category);
}
request.setAttribute("categories", Arrays.asList(categoryMap.values()));
Then the code on your page is much more straightforward:
<c:forEach var="category" items="${categories}">
<h1><c:out value="${category.name}"/></h1>
<c:forEach var="file" items="${category.files}">
<a href="TBD">
<c:out value="${file.osDirectory}"/>
<c:out value="${file.description}"/>
</a>
</c:forEach>
</c:forEach>
After some later investigation and experimentation, I found this to be a cleaner approach than the JSTL posted in the question.
<c:forEach var="f" items="${filemap}">
<h1><c:out value="${f.key}"/></h1>
<c:forEach var="g" items="${f.value}">
<a href="TBD">
<c:out value="${g.value[0]}"/>
<c:out value="${g.value[1]}"/>
</a>
</c:forEach>
</c:forEach>

Convert a List to String to populate webpage in JSP

I have DAO bean rows retrieved in a List. In my JSP I am accessing the List to iterate thru to populate my page. My JSP can't access the List because it says it must be a String when I execute a request.getParameter. How I convert this to String eventually populate my page?
public List getAccessRequest()
{
List accessRequesttList = new ArrayList()); // parse List to string
//AccessRequest accessrequest = null;
AccessRequest accessRequest = new AccessRequest());
try
{
System.out.println("Try statement begins AccessRequestDAO");
PreparedStatement accrqststmt = super.getConnection().prepareStatement(AccRqstSqlStmt);
ResultSet resultSet = accrqststmt.executeQuery();
while (resultSet.next())
{
// Creating an instant of job follows
accessRequest = new Accessrequest();
accessRequest.setJOB_NAME(resultSet.getString("job_name"));
accessRequest.setRequest_ts(resultSet.getTime("request_ts"));
accessRequestList.add(accessRequest);
Iterator iterator = accessRequestList.iterator();
while (iterator.hasNext())
{
accessRequest = (Accessrequest) iterator.next();
}
}
return (accessRequestList);
My JSP look like below:
<%
List jobList = request.getParameter("acccessrequests"); // parse List to String
Iterator iterator = jobList.iterator();
while (iterator.hasNext())
{
accessRequest = (AccessRequest) iterator.next());
%>
<tr>
<td><input type="checkbox" name="<%accessRequest.getApproval_ind(); %>"></td>
<td><input type="text" id="jobname' name="accessRequests" value="job_name"></td>
HttpServletRequest#getParameter() returns a String, not a List. So the compiler is right.
I am not sure how you have ever set the List as a request parameter, there's no such method like HttpServletRequest#setParameter(). So you're probably misinterpreting something. The normal approach is to set the list as request attribute by HttpServletRequest#setAttribute() and access it in JSP by EL (expression language) like as ${attributeName}. You also normally iterate over the list using JSTL <c:forEach> tag.
Assuming that you've set the list in the request scope using a Servlet like follows...
request.setAttribute("list", list);
...here's a kickoff example how to iterate over the list:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
...
<table>
<c:forEach items="${list}" var="item">
<tr>
<td>${item.property1}</td>
<td>${item.property2}</td>
<td>${item.property3}</td>
</tr>
</c:forEach>
</table>
Alhamdulillah, thanks God!
This help me a lot. I try to build my own java Web framework.
Before reading this QA, I don't know how to access an object (say, row of table) from a JSP.
I just redirect it, and leave the database code in JSP, generated by DreamWeaver. Now I know how to do it. For example, this is a BiroController, which display data from Biro Table :
public void index() throws IOException, ServletException {
List list=new ArrayList();
list.add(BiroModel.create("1", "SDM"));
list.add(BiroModel.create("2", "Keuangan"));
request.setAttribute("list", list);
super.index();
}
firstly, I populate an array (subsequently, this will come from database table). and then set request attribute, then call superclass index method :
public void index() throws IOException, ServletException {
RequestDispatcher rd = request.getRequestDispatcher(viewPage);
if(rd!=null){
rd.forward(request, response);
}else{
PrintWriter out = response.getWriter();
out.print("can not dispatch to " + viewPage);
}
//OLD Code : response.sendRedirect(ServletUtil.getBaseUrl(request) + viewPage)
}
And, I did as you instructed in the JSP :
<c:forEach items="${list}" var="item">
<tr>
<td>${item.idbiro}</td>
<td>${item.biro}</td>
</tr>
</c:forEach>
I use Netbeans, so I can easily pick JSTL library from the list of available library
It works charmingly.. :) tq

Capture multiple check box selection JSP Parameters

I found this post that shows how to pass multiple check box selections to another JSP page, but it's not working for me. When I try to get the selected values I get:
checked boxes: [Ljava.lang.String;#3f3fbd
Here are my two pages (be gentle, this is my first attempt at JSP!)
createSHAREfile.jsp basically runs a query to find all the terms that have not been processed and show each term with a check box next to it:
<title>Create SHARE Files</title>
</head>
<body>
<jsp:include page="../menu/header.jsp" flush="false" />
<form name='SelectSHARETerms' method='post' action="SHAREProcessing.jsp">
<fieldset><legend>Select Terms to Process for SHARE</legend>
<table align='left'>
<% String termDetail = "", currDate = "";
currentDateTime datetime = new currentDateTime();
datetime.setCurrDate();
currDate = datetime.getCurrDate();
java.sql.Date todayDate = java.sql.Date.valueOf(currDate);
Terms terms = new Terms();
ArrayList<Terms.termsTable> termsObjList = new ArrayList<Terms.termsTable>();
terms.setTermsSql("Select * from Terms where TermDate <= '" + currDate + "' AND VoucherProcessDate Is Null");
boolean indicator = terms.setListOfTerms();
if (indicator == true) {
int size = terms.getListSize();
termsObjList = terms.getTermsList();
for (int i=0; i<size; ++i) {
Terms.termsTable eachTerm = (Terms.termsTable)termsObjList.get(i);
java.sql.Date termDate = eachTerm.TermDate;
%>
<tr><td><input type=checkbox name=SelectedTermDate id='SelectedTermDate<%=i%>' value="<%=i%>"><%=termDate %></td></tr>
<%
}
}
%>
<tr><td align='center'><input type='submit' value='Submit'></input></td></tr>
</table>
</fieldset>
</form>
</body>
</html>
When the submit button is pressed I call SHAREProcessing.jsp. Right now all i'm trying to do on this page is show which termdates the user has selected so I can use them as parameters to a Java Class that will create the files for the selected terms:
<title>SHARE Processing</title>
</head>
<body>
<jsp:include page="../menu/header.jsp" flush="false" />
<table width='50%' align='center' border='1'>
<% String[] SelectedValues = request.getParameterValues("SelectedTermDate");
System.out.println("checked boxes: " + SelectedValues);
%>
</body>
</html>
Here's where I'm trying to use the code shown in the other post but it's not working :(
Thanks for any help!
Leslie
You're trying to print the whole string array with System.out.println, and so you get that. It's probably working fine.
Try this:
System.out.println("checked boxes:");
for (int i = 0; i < SelectedValues.length; ++i)
System.out.println(" " + SelectedValues[i]);
Also, I beg you: in your spare time, find out about a modern web framework (there are zillions for Java) and strive to escape from the painful world of coding Java inside JSP files.
You're just facing the default value of Object#toString().
Either just loop over it and print each item, or use Arrays#toString(). Here's an SSCCE:
package com.stackoverflow.q2426380;
import java.util.Arrays;
public class Test {
public static void main(String... args) {
String[] array = {"foo", "bar" , "waa"};
System.out.println(array); // [Ljava.lang.String;#addbf1
String arrayAsString = Arrays.toString(array);
System.out.println(arrayAsString); // [foo, bar, waa]
}
}
That said, this problem has actually nothing to do with JSP. It's just a view technology. The problem is rather in the basic Java code --which you wrote at the wrong place, in a JSP file instead of a Java class. I strongly agree with the comments that writing raw Java code in JSP files is a bad practice. Start learning Servlets.

Categories

Resources