How do I send data from Struts action to javascript? - java

I'm trying to create a webb application using Struts 2 and javascript and I'm having some trouble passing data from my action into my javascript.
This is the list I'm trying to send/access:
List<MarkerClass> markers;
MarkerClass is defined acoprding to belove:
final class MarkerClass
{
public Integer objectId;
public String street;
public String streetNumber;
public String zip;
public String city;
public Integer statusId;
public Float lattitude;
public Float longitude;
}
The action also includes a getter for markers:
public List<MarkerClass> getMarkers()
{
return markers;
}
In my jsp-file I have tried doing this:
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function initialize()
{
var titel = "";
for(var i, "${markers}")
{
titel = titel+ "${markers[i].street}";
}
}
The browser substitutes "${markers}" with "[se.fubar.test.MarkerClass#37a4, se.fubar.test.MarkerClass#9ad97c]"
I'm guessing there is a better and smarter way to do this but since I'm a bit new to Struts and is trying to code while under the influence of a migrane the answer elludes me.

You cannot just use a struts variable in a javascript function and expect it to work. Remember that the ${...} stuff gets processed before the HTML for the page is sent to the browser. By the time the javascript is rendered at the browser, you are only left with the textual representations. What you will need to do is something like (check the syntax, I haven't used this stuff i a while):
function initialize() {
var title = "";
<c:foreach var="marker" list="${markers}">
title = title + "${marker.street}";
</c:foreach>
}
Something along those lines anyway... Basically the Javascript seen by your browser will look like
function initialize() {
var title = "";
title = title + "Street1";
title = title + "Street2";
title = title + "Street3";
title = title + "Street4";
}
I hope that makes sense and is related to what you were asking.
By the way, there are usually better ways of accomplishing this functionality that building dynamic js etc. Probably there are built in Struts 2 components that you can use?

you would have to set that variable in request or in session and then access it using a <c:out jsp tag like so
var myVar= '<c:out value="${requestScope.myVar}"/>';
then use the var inside your js.
In case you set an object in request or session you have to use the get method to access the value of an attribute then use it like so:
var myVar= '<c:out value="${requestScope.myObj.attribute}"/>';
(assuming you getter method is getAttribute)
it is not possible to access data in session or request directly from js
hope this helps

You could convert the object to json on the server (see http://www.json.org/java/index.html ) and then call eval() on the string to get a javascript representation of your object.

you can try accessing it something like this.
but you have to use a loop to fetch each object from the list place it on the value stack and than fetch each object of it.else you can ask ognl to do it for you.something like
<script type="text/javascript">
function initialize()
{
var titel = "";
for(var i, "${markers}")
{
titel = titel+ <s:property value="%{markers.get(i).street}">;
}
}
just try it since OGNL has capacity to access the object on the value stack

Related

Is the standard library my best option for Java to load/read and edit/modify and save a html file with no reformatting?

I want to load/read and edit/modify and save a html file located on my hard drive. I tried JSOUP, but it kept reformatting the html file. I want to avoid reformating.
I'm wanting to inject some JavaScript after the <script> and before var deviceReady = false; in the html file.
Do I need to parse the file?
Should I use default Java? (BufferedReader, FileReader, Scanner)
<!DOCTYPE html>
<html lang="en">
<head>
<meta name='viewport' content='initial-scale = 1, minimum-scale = 1, maximum-scale = 1'/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="x-ua-compatible" content="IE=10">
<title>LX-XXX-KU</title>
<style type="text/css">#initialLoading{background:url(assets/htmlimages/loader.gif) no-repeat center
center;background-color:#ffffff;position:absolute;margin:auto;top:0;left:0;right:0;bottom:0;z-
index:10010;}</style>
"
<script>
var deviceReady = false;
var initCalled = false ;
var initialized = false;
function onBodyLoad()
{
if(typeof window.device === 'undefined')
{
document.addEventListener("deviceready", onDeviceReady, false);
}
else
{
onDeviceReady();
}
}
Javasacript I want to add after the <script> and before var deviceReady = false;
`//adds numbers to TOC
window.addEventListener( 'moduleReadyEvent', function ( e )
{
var myText = document.getElementsByClassName('tocText');
for ( var i = 0; i < myText.length; i++ )
{
var getText = myText[ i ].childNodes;
var str = ( i + 1 ) + ' ' + getText[ 0 ].innerHTML;
getText[ 0 ].innerHTML = str;
}
});`
This can be accomplished like so:
File f = ...;
String contents = new String(Files.readAllBytes(f));
int idx = contents.indexOf(insertBeforeStr);
contents = contents.substring(0, idx) + contentToBeAdded + contents.substring(idx + 1);
// write contents back to the disk.
If you turn off jsoup's pretty printing option, and use the XML parser instead of the validating HTML parser, the document and all of its text verbatim, including whitespace, is passed through pretty much unmolested, other than syntax fixes for attributes, missing end tags, and the like.
See for example your input on Try jsoup with pretty-printing off, and using the XML parser, is effectively the same as your original.
The code would be something like:
Document doc = Jsoup.parse("<script>\nSomething(); ", "", Parser.xmlParser());
doc.outputSettings().prettyPrint(false);
Element scriptEl = doc.selectFirst("script");
DataNode scriptData = scriptEl.dataNodes().get(0);
scriptData.setWholeData(scriptData.getWholeData() + "\nanotherFunction();");
System.out.println(doc.html());
Gives us (note that there's no HTML structure automatically created, due to using the XML parser):
<script>
Something();
anotherFunction()</script>
ControlAltDel's answer definitely works and means you can do it with just the Java base library. The benefit of using jsoup is (IMHO - as the author of jsoup) in this case is that you're not trying to string-match HTML, and won't get caught by e.g. a <script> in a comment, or in this case a missing close </script> tag, etc. But of course YMMV.
Incidentally, once jsoup 1.14.1 is released (soon!) with the change #1419 (which for script elements, proxies text settings into data without escaping), the code will simplify to:
Element scriptEl = doc.selectFirst("script");
scriptEl.appendText("\nanotherFunction()");

How do I send data from a Controller to a JSP page in Spring?

I have two JSP pages let's just called them 1 & 2. I'm passing a latitude and longitude value from page 1 to a method in my controller class via an AJAX query in a javascript function on JSP page 1. The method in the controller will use the latitude and longitude to query a database and provide an average house price of all houses in a 1km radius of the latitude and longitude passed into the controller. I have a debug print statement that confirms that the query is successful as it prints the average house price in the Eclipse console.
If you're still with me, how can I then pass this doubleaverage house price value (housePriceAverage) from the controller method to display on JSP page number 2? For some reason, the new JSP page (number 2) simply will not load when called, however the debug works to show the values are being passed to the controller and the query works? I would really appreciate any advice/tips anyone would have!
Here's an example of the method inside my Controller class. If you wanna see the other functionality I'll be happy to include it. Thank You!
#RequestMapping(value = "/parseHousePrice", method={RequestMethod.POST, RequestMethod.GET})
public #ResponseBody String parseHousePrice(#RequestBody HousePrice housePriceObject,
#RequestParam("latitude") double latitude,
#RequestParam("longitude") double longitude,
Model model) {
// This passes the lat & long into a method that will query the database
double housePriceAverage = parseHousePrice.ParseHousePrice(latitude, longitude);
// This print statement successfully prints the results fromt he query
System.out.println("The average house price for this area is: " + housePriceAverage);
model.addAttribute("houseprice", housePriceAverage);
// JSP Page I'm trying to pass the information above to
return "houseprice";
}
Code for JSP page 2 where I want to send the data (houseprice) to, from the controller
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%#page isELIgnored="false" %>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org">
<link href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js">
</script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>House Price</title>
<style>
I've excluded some CSS code here for conciseness
</style>
<script>
I've excluded Javascript code for a Navbar here for conciseness
</script>
</head>
<body>
<p style="display:none">${houseprice}</p>
<p style="display:none">${housepricelistsize}</p>
</body>
Javascript function in JSP 1 that sends the latitude and longitude data to the controller
function sendDataToParseHousePrice(){
// Calculates the latitude and longitude of the user
$('.search_latitude').val(marker.getPosition().lat());
var Lat = marker.getPosition().lat();
console.log(Lat);
$('.search_longitude').val(marker.getPosition().lng());
var Long = marker.getPosition().lng();
console.log(Long);
$.ajax({
type: "POST",
url: "/parseHousePrice",
data: { latitude: Lat,
longitude: Long
}, // parameters
datatype: 'json'
});
}
Because of #ResponseBody on your method, the text houseprice is returned to page 1 as an AJAX response. It is not resolved as a view. If you want to stick to your AJAX request you can return the housePriceAverage instead. Then when you get the AJAX response on page 1 use the value to navigate to page 2. In page 2 use #RequestParam to get the housePriceAverage supplied as a parameter
#RequestMapping(value = "/parseHousePrice", method={RequestMethod.POST, RequestMethod.GET})
public double parseHousePrice(#RequestBody HousePrice housePriceObject,
#RequestParam("latitude") double latitude,
#RequestParam("longitude") double longitude,
Model model) {
// This passes the lat & long into a method that will query the database
double housePriceAverage = parseHousePrice.ParseHousePrice(latitude, longitude);
// This print statement successfully prints the results fromt he query
System.out.println("The average house price for this area is: " + housePriceAverage);
return housePriceAverage;
}
If its possible to forgo AJAX then do a conventional POST to your Controller and use view resolution to navigate to page 2. You achieve this by removing #ResponseBody
#RequestMapping(value = "/parseHousePrice", method={RequestMethod.POST, RequestMethod.GET})
public String parseHousePrice(#RequestBody HousePrice housePriceObject,
#RequestParam("latitude") double latitude,
#RequestParam("longitude") double longitude,
Model model) {
// This passes the lat & long into a method that will query the database
double housePriceAverage = parseHousePrice.ParseHousePrice(latitude, longitude);
// This print statement successfully prints the results fromt he query
System.out.println("The average house price for this area is: " + housePriceAverage);
model.addAttribute("houseprice", housePriceAverage);
// JSP Page I'm trying to pass the information above to
return "houseprice";
}

Accessing SpringMVC model key value inside java code

#RequestMapping(value = "",method = RequestMethod.GET)
public String printWelcome(ModelMap model) {
model.addAttribute("message", doctorDetails);
return "doctorchannelling/index";
}
I have added this controller in my SpringMVC project now I need to access the element doctorDetails in a java code which is inside a jsp
how can I call this doctorDetails inside <% %> Mark
Something like below
<% String message = (String)request.getAttribute("message"); %>
or
<%
String message = ${message};
%>
You can simply use the EL to print them as,
${message}
If it is a String set in the request. For Model objects use ,
${message.fieldName}
See Also
How to avoid Java code in JSP files?
printing servlet request attributes with expression language

How to pass an array from servlet to jsp page?

I have achieved sending an integer variable to a jsp page using the following code:
resp.sendRedirect(("result.jsp?fibNum=" + fibNum));
But when I try the same to pass the array, int[] fibSequence I get the following passed to the address bar of the jsp page:
Does anyone have any advice on how I can output the array value passed over to the jsp page?`
This is how I sent the array across to the result jsp page within the doPost():
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
// read form fields
String fibNum = req.getParameter("fibNum");
try{
//Get reference from server's registry
Registry registry = LocateRegistry.getRegistry("127.0.0.1");
//Lookup server object from server's registry
IFibonacci fibonacci_proxy = (IFibonacci)registry.lookup("PowerObject");
int fibMax = Integer.parseInt(fibNum);
//Invoke server object's methods
//Get Fibonacci array.
int[] fibSequence = fibonacci_proxy.fibonacciArrayTest(fibMax);
for (int value : fibSequence) {
System.out.println(value);
}
//System.out.println(Arrays.toString(fibSequence));
}catch(NotBoundException nbe){
nbe.printStackTrace();
}catch(RemoteException re){
re.printStackTrace();
}
//send input to the result page using a redirect
//resp.sendRedirect(("result.jsp?fibNum=" + fibNum));
resp.sendRedirect(("result.jsp?fibSequence=" + fibSequence));
}
How I've tried to retrieve the array values on the jsp page and print them, but I'm getting a fibSequence cannot be resolved to a variable although this is the name of the array passed over:
Return to Main<br>
<%String[] var_array=request.getParameterValues("fibSequence");%>
<%System.out.print(""+fibSequence);%>
</form>
Trust the compiler. fiBSeq ist not defined. You defined fibSequence. But passing that array as an argument will not work, because you will pass (int[]).toString() which is probably not what you want. You can serialize and encode it, if it is not too big. Or post it.
EDIT 1
int [] array = {1,2,3,4,5,6,7,8,9};
System.out.print(""+array);//<-- print [I#15db9742 or similar
EDIT 2
Encoding the array on the sender side
int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
String param = Arrays.toString(array);
param = param.substring(1, param.length()-1);//removing enclosing []
String encArray = URLEncoder.encode(param, "utf-8");
// Send encArray as parameter.
resp.sendRedirect(("result.jsp?fibSequence=" + encArray));
Decoding the array on the receiver side
String encArray = request.getParameterValues("fibSequence");
String decArray = URLDecoder.decode(encArray,"utf-8");
//Now you can parse the list into an Integer list
String [] var_array = decArray.split(",");
In jsp, put the code between <% ... %>. If you get some unresolved symbol errors you have to import the missing libraries.
Can be one or more of the following, simply copy the statements at the top of the page.
<%# page import="java.io.*" %>
<%# page import="java.net.*" %>
<%# page import="java.util.*" %>
(maybe java.util is imported per default, I am not sure)
BUT ATTENTION
Be aware of not sending too much data in this manner! The size of an URL maybe is not unlimited. Also the data is visible in the URL, a 'nasty' user could simply copy and reproduce requests.
A better way to send data is using HTTP post.
Here is the better answer to transfer array variable from servlet to jsp page:
In Servelet:
String arr[] = {"array1","array2"};
request.setAttribute("arr",arr);
RequestDispatcher dispatcher = request.getRequestDispatcher("yourpage.jsp");
dispatcher.forward(request,response);
In Jsp:
<% String str[] = (String[]) request.getAttribute("arr"); %>
<%= str[0]+""+str[1] %>

Access java <List> from from jsp / jstl MVC app

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);
}
}
});

Categories

Resources