Accessing servlet generated objects (JSONObjects) via AJAX and JQuery - ajax

I am new to using AJAX and JQuery with Java Servlets. I want to produce a search page that produces a list of search results (like a google page listing). My database query works and returns a JSONObject or a JSONArray.
My code is not working for the JQUERY. I have tried a lot of different versions. The basic error is that the new page after the search just shows the data in the form of an array print. It does not recognise the HTML.
I have shown my code below with the db query removed. The different versions I tried were with various forms of JSON syntax, with and without GSON, and nothing has worked.
The system is Linux.
Any comments would be appreciated, or even a link to a comprehensive example.
search.js
$(document).ready(function(){
$('#searchbutton').submit(function)
{
var inputdata = searchText:$("#searchtext").val();
};
$.ajax({
type:"POST",
datatype: "json",
url:"search",
data:inputdata,
success: function(data){
$("#searchResults").append("<b>data.linkresult</b>")
});
});
});
});
});
search.java
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException
{
PrintWriter out = response.getWriter();
// reading the user input
String searchword= request.getParameter("search");
String Tmsg = "";
Map<String, Object> data = new HashMap<String, Object>();
data.put("searchresult", searchword);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(new Gson().toJson(data));
search.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Search for a word</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<script type="text/javascript" src="./js/jquery-1.9.1.js"></script>
<script type="text/javascript" src="./js/search.js"></script>
<script type="text/javascript" src="./js/jquery-1.9.1.min.js"></script>
</head>
<body>
<form action="search">
Search<br>
<div>Word -
<input id="searchtext" type="text" name="search" size="40px">
</div>
<div>
<input id="searchbutton" type="submit" value="Submit">
</div>
</form>
<div id="searchresults">
</div>
Result (just this one line is displayed):
{"searchresult":"search example"}

To parse the Json message received from the servlet, you can achieve this by doing something like this. Lets assume that you have received the following message from the servlet
{"key1":"val1","key2":"val2","key3":"val3"}
And you want it to be displayed in a table.
success: function(data){
var output = '<table>';
for ( var key in data) {
if (data.hasOwnProperty(key)) {
output += "<tr>";
output += "<td>" + key + "</td>";
output += "<td>" + data[key] + "</td>";
output += "</tr>";
}
}
output += "</table>";
$("#searchResults").empty();
$("#searchResults").append(output);
});

Related

struts2 onblur server side ajax validation

How would I implement AJAX validation in struts2 which lets you know if a username is available onblur? This is what I've managed so far but the docs aren't clear:
JSP:
<%# page
language="java"
contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib
prefix="s"
uri="/struts-tags"%>
<%# taglib
prefix="sj"
uri="/struts-jquery-tags"%>
<!DOCTYPE html>
<html>
<head>
<sj:head jqueryui="true" />
<!-- Don't forget these 2 files!! -->
<script
src="${pageContext.request.contextPath}/struts/utils.js"
type="text/javascript"></script>
<script
src="${pageContext.request.contextPath}/struts/css_xhtml/validation.js"
type="text/javascript"></script>
<script
type="text/javascript"
src="js/register.js"></script>
<title>Register</title>
</head>
<s:url
action="loginLink"
var="loginHREF" />
<s:url
action="forgotPasswordLink"
var="forgotPasswordHREF" />
<s:url
action="Register"
var="registerHREF" />
<body>
<s:form
theme="css_xhtml"
action="Register"
onsubmit="return myValidate()">
<s:textfield
name="user.username"
label="Username"
id="uname"
required="true"
pattern="[a-zA-Z0-9_-]{5,12}"
title="5-12 Alphanumeric characters required" />
<s:textfield
name="user.email"
label="Email"
required="true" />
<s:password
id="pass1"
name="user.password"
label="Password"
required="true"
pattern="{5,12}"
title="5-12 characters" />
<s:password
id="pass2"
label="Confirm Password"
required="true"
pattern="{5,12}" />
<s:textfield
name="user.firstName"
label="First Name"
required="true" />
<s:textfield
name="user.lastName"
label="Last Name" />
<sj:datepicker
yearRange='-90:-3'
changeYear="true"
name="user.birthDate"
readonly="true"
label="Date of Birth" />
<s:submit value="Register" />
</s:form>
<s:a href="%{loginHREF}">Login</s:a>
<s:a href="%{forgotPasswordHREF}">Forgot Password</s:a>
<script>
$("#uname").blur(function() {
var fieldData = $("#uname").serialize();
fieldData = fieldData.slice(5);
//do the POST thingies
$.ajax({
type : "POST",
url : "ValidateUsername",
cache : false,
data : fieldData,
dataType : "json",
complete : function(request) {
alert("In complete");
var form = $('form');
//clear previous validation errors, if any
//StrutsUtils.clearValidationErrors(form);
//get errors from response
var text = request.responseText;
alert(text);
var errorsObject = StrutsUtils.getValidationErrors(text);
//show errors, if any
if (errorsObject.fieldErrors) {
StrutsUtils.showValidationErrors(form, errorsObject);
}
}
});
return false;
});
</script>
</body>
</html>
Action:
#Action("ValidateUsername")
#Results(value = { #Result(name = "success", type = "json"), #Result(name = "input", type = "json") })
#ParentPackage("default")
#InterceptorRef("jsonValidationWorkflowStack")
public class ValidateUsername extends ActionSupport {
private String username;
#Override
public String execute() {
return SUCCESS;
}
#Override
public void validate() {
UserService service = new UserService();
User isTaken = service.findByUsername(username);
service.close();
if (isTaken != null)
addFieldError("user.username", "That username is taken");
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
The docs make it seem like struts2 will handle it for you if you simply add the json interceptor and set validate="true" in the sx:submit tag.
In register.js I check to see that password and confirmation password match.
Basically I would like it to validate even before submit is pressed. Right now On submit it validates it like any other normal form.
Edit: Also, is there a working method other than using dojo? It seems to block all my client side validation including the required attributes, js, etc.
Edit2:I ditched the dojo plugin, learnt some js and managed to put together what i have now. Now the only thing left is to display an error. Alerting the response text shows up a json string with only a username key value pair in it. Should i add another member to the action and process it to display an error message? because the StrutsUtils js is not working. addFieldError("user.username", "That username is taken"); does not modify the json result.
Basically, how can i add fielderrors to my json response?
Edit: I got my action to add my field errors to the json response by modifying the annotations as follows:
#Action("ValidateUsername")
#Results(value = {
#Result(name = "success", type = "json"),
#Result(name = "input", type = "json", params = { "ignoreHierarchy",
"false", "includeProperties",
"actionErrors.*,actionMessages.*,fieldErrors.*" }) })
#ParentPackage("default")
#InterceptorRef("jsonValidationWorkflowStack")
Now the only problem is in:
//clear previous validation errors, if any
**//StrutsUtils.clearValidationErrors(form);**
//get errors from response
var text = request.responseText;
alert(text);
**var errorsObject = StrutsUtils.getValidationErrors(text);**
//show errors, if any
if (errorsObject.fieldErrors) {
StrutsUtils.showValidationErrors(form, errorsObject);
}
None of the StrutsUtils functions are working. When i uncomment clearValidationErrors it does nothing and breaks the rest of the js code. errorsObject is empty and showValidation does nothing even though on printing my jon response i can see a field error with a message. How do i get StrutsUtils to work?
Also, is there a better way to implement my use case? I haven never learnt jquery/ajax and this is my first struts2 application.
Struts is available server-side. You are trying to call
var errorsObject = StrutsUtils.getValidationErrors(text); in the client-side.
StrutsUtils is a class and is not available on client-side/javascript.
There are various ways through which you can send errors.
Please refer my answer in the below link, on how to handle ajax request & response when using struts2.
How to get Ajax response in Struts2

issue with ajax send() function

<!DOCTYPE html>
<html>
<head>
<title>Lesson 18: Making AJAX Calls</title>
</head>
<body>
<h1>Lesson 18: Making AJAX Calls - Plain Text Response</h1>
<div>
<h2 id="myHeader">Click the button to call your data</h2>
<input type="button" value="Click Me!" onclick="getText('test.txt')" />
</div>
<script type="text/javascript">
var myRequest;
function getText(url)
{
if (window.XMLHttpRequest)
{
myRequest = new XMLHttpRequest();
}
else
{
myRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
myRequest.open("GET", url, true);
myRequest.send(null);
myRequest.onreadystatechange = getData;
}
function getData()
{
var myHeader = document.getElementById("myHeader");
if (myRequest.readyState ===4)
{
if (myRequest.status === 200)
{
var text = myRequest.responseText;
myHeader.firstChild.nodeValue = text;
}
}
}
</script>
</body>
</html>
This code is from this tutorial: http://www.html.net/tutorials/javascript/lesson18.php
Questions:
what does this mean: myRequest.send(null); what is the difference between it and myRequest.send();?
No difference. .send(null) is mean that you are sending "null" content in request body. .send() is mean that you are sending nothing in request body.
In case of GET requst there is no difference, becouse request body is not sending.
In case of POST request there will be none difference too.
See this :Why do we pass null to XMLHttpRequest.send?

How to call specific method of portlet.java class rather then overide serveResource method?

I want some help in liferay with ajax.
Right now I am calling the ajax method from my view.jsp page to submit some data.
Here is sample code I am using in view.jsp:
<%# include file="/init.jsp"%>
<portlet:actionURL name="AddTest" var="add1" />
<portlet:resourceURL id="AddTest" var="AddTest"></portlet:resourceURL>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script type="text/javascript">
function addToDo(addToDo){
var todo =document.getElementById('toDo').value;
$.ajax({
url :addToDo,
data: {"todo":todo,"CMD":"addToDo"},
type: "GET",
dataType: "text",
success: function(data) {
$("#toDoList").html(data);
}
});
}
</script>
</head>
<body>
<portlet:resourceURL var="addToDo" id="addToDo"></portlet:resourceURL>
<form>
<input type="text" name="toDo" id="toDo">
<button name="Add" type="button" onclick="addToDo('<%=addToDo%>')">Add</button>
<div id="toDoList">
</div>
</form>
</body>
</html>
and in my portlet.java class there is one method which is called by this ajax call:
#Override
public void serveResource(ResourceRequest request, ResourceResponse response){
if(request.getParameter("CMD").equals("addToDo")) {
System.out.println("came here for add");
mediatype userToDo = new mediatypeImpl();
//userToDo.setMediaId(12345);
try {
userToDo.setPrimaryKey((CounterLocalServiceUtil.increment()));
userToDo.setMedianame(request.getParameter("todo"));
mediatypeLocalServiceUtil.addmediatype(userToDo);
}
catch (SystemException e) {
e.printStackTrace();
}
}
}
So my question is that right now it is just caling by default #override method from any ajax class.
But how can I call specific method of portlet.java class on ajax call?
I am new bee in ajax. So please guide me anyways u can.....
I got following error when calling ajax with url of following
<portlet:actionURL name="ajax_AddAdvertise" var="addToDo" windowState="<%= LiferayWindowState.EXCLUSIVE.toString()%>"> </portlet:actionURL>
06:47:03,705 ERROR [http-bio-8080-exec-23][render_portlet_jsp:154] java.lang.NoSuchMethodException: emenu.advertise.portlet.RestaurantPortlet.ajax_AddAdvertise(javax.portlet.ActionRequest, javax.portlet.ActionResponse)
at java.lang.Class.getMethod(Class.java:1605)
my process action method as follows
#ProcessAction(name = "ajax_AddAdvertise")
public void ajax_AddAdvertise(ResourceRequest request,ResourceResponse response) {
}
how can I call specific method of portlet.java class on ajax call?
I think we can't have two different versions of serveResource methods like we do for action methods atleast not with the default implementation.
If you want different methods you would have to go the Spring MVC (#ResourceMapping) way to have that.
Still, you can define different logic in your serveResource method using the resourceId as follows (a full example):
In the JSP:
<portlet:resourceURL var="myResourceURL" id="myResourceID01" />
In the portlet class the serveResource method will contain the following code:
String resourceID = request.getResourceID();
if(resoureID.equals("myResourceID01")) {
// do myResourceID01 specific logic
} else {
// else do whatever you want
}
Please keep in mind [Important]
In a portlet you should not use <html>, <head>, <body> tags since portlets generate fragment of the page and not the whole page. Even if it is allowed your resultant page will not be well-formed and will behave differently on different browsers. And moreover the javascript which modifies DOM element will be totally useless.
Edit after this comment:
You can also use ajax with action methods:
People use <portlet:actionURL> with ajax generally for <form>-POST.
For this the actionURL is generated in a slightly different way in your jsp like this:
<portlet:actionURL name="ajax_AddAdvertise" var="addToDo" windowState="<%= LiferayWindowState.EXCLUSIVE.toString()%>">
</portlet:actionURL>
And in your portlet you can have (as in the question):
#ProcessAction(name = "ajax_AddAdvertise")
public void ajax_AddAdvertise(ActionRequest request, ActionResponse response) {
// ... your code
}

Ajaxified link in MVC3/JQuery not working in IE8 (missing header)

Consider the following code (it is based on a default EMPTY MVC3 project created in visual web developer express 2010sp1):
_Layout.cshtml:
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
</head>
<body>
<div id="header">header</div>
<div id="main">#RenderBody()</div>
</body>
</html>
Index method of HomeController:
public ActionResult Index()
{
if (Request.IsAjaxRequest())
{
ViewBag.Message = "partial";
return PartialView();
}
else
{
ViewBag.Message = "full";
return View();
}
}
Index.cshtml:
<script type="text/javascript">
$(function () {
$('#myLink').click(function () {
$.post(this.href, function (result) {
$('#main').html(result);
alert(result);
});
return false;
//$('#main').load(this.href);
//return false;
});
});
</script>
HomeController index. #ViewBag.Message
#Html.ActionLink("Index", "Index", new { controller = "Home" }, new { id = "myLink" } );
The problem is that in IE8 when the myLink link is clicked, it doesn't update the main div with only the partial html from Index.cshtml but the complete html including the layout. Ofcourse it works fine in FF, I mean why shouldn't it right? It seems Request.IsAjaxRequest() always evaluates to false in IE8. I understand that it is a result of a header X-Requested-With not being attached to a request in IE8. I don't have a lot of experience with web development -- is this a common issue and what is the (best) way to solve this?
UPDATE:
Yesterday I got it working normally in IE8, but when I tried it again this morning, the same problem was back. Now I don't think it has anything to do with the settings in IE8 anymore as I restored the settings to the default values. I tried examining the request with the fiddler tool. In order for me to be able to capture the traffic from localhost with fiddler, I added a period to the address: http://localhost.:3157/. So now the error occurs only when I use http://localhost.:3157/ (with period) and it works normally when I use http://localhost:3157/ (without period). I additionally tested the behavior in Chrome, Opera and Safari -- the ajax link works normally in these browsers. Note that I can get it working normally in IE8 when I attach a query parameter to the ajax link like so:
#Html.ActionLink("Index", "Index", new { controller = "Home", param = "param" }, new { id = "myLink" } )
I don't really want to do this. I'm running low on ideas here. I'm probably missing something that is blatantly obvious to a seasoned web developer =] Anybody recognize these symptoms?
You probably want to use the .live() method instead of .click():
$('#myLink').live('click', function () {
...
return false;
});
because you are replacing the DOM in the AJAX callback (the #main) which contains the link so you are killing the event handler you have assigned.
Also you have a typo in the jquery script inclusion in the <head>. You are missing a closing > after type="text/javascript":
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
So here's a complete working example:
_Layout.cshtml:
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
</head>
<body>
<div id="header">header</div>
<div id="main">#RenderBody()</div>
</body>
</html>
HomeController:
public class HomeController : Controller
{
public ActionResult Index()
{
if (Request.IsAjaxRequest())
{
ViewBag.Message = "partial";
return PartialView();
}
else
{
ViewBag.Message = "full";
return View();
}
}
}
Index.cshtml:
<script type="text/javascript">
$(function () {
$('#myLink').click(function () {
$.post(this.href, function (result) {
$('#main').html(result);
});
return false;
});
});
</script>
HomeController index. #ViewBag.Message
#Html.ActionLink("Index", "Index", new { controller = "Home" }, new { id = "myLink" } )
add
jQuery.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
}
});
to make sure the correct header is attached.

MVC Scorm sequencing Issue with regards to PartialView

I am working on a Scorm MVC project. Basically I need to update a partial view from a cs class file.
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Table of Contents Test</h2>
<br />
<div id="SCONavBar">
<% XElement item = (XElement) Model;
String rootID = (String) ViewData["courseRoot"];
String resource = (String) ViewData["resource"]; %>
<button id="prev" onclick="javascript:NavigationRequest('', '<%: resource %>', 'previous');">Previous</button>
<button id="cont" onclick="javascript:NavigationRequest('', '<%: resource %>', 'continue');">Continue</button>
<button id="start" onclick="javascript:NavigationRequest('', '<%: resource %>', 'start');">Start Course</button>
</div>
<div id="scoContainer">
<div id="treeContainter" style="display:inline-block; outline:black solid 1px; height:600px; width:300px; overflow:scroll; padding:2px;">
<ul id="treeview">
<% Html.RenderPartial("~/Views/Content/ActivityTreeUserControl.ascx", item); %>
</ul>
</div>
<div id="contentContainer" style="vertical-align:top; display:inline-block; outline:black solid 1px;">
<% Html.RenderPartial("~/Views/Content/ContentFrame.ascx"); %>
</div>
</div>
<script type="text/javascript" src="../../Scripts/TreeView/TOCControlScript.js"></script>
<script type="text/javascript" src="../../Scripts/TreeView/resizeFrame.js"></script>
<script type="text/javascript" src="../../Scripts/Scorm/loungeScormMethods.js"></script>
<script type="text/javascript">
$(document).ready(function () {
startTree();
});
</script>
</asp:Content>
Above is the code for my view. On first load it loads a table of contents partial view and an Iframe partial view. When clicking my personal Start, Cont and Prev buttons, an AJAX request goes through a sequencer and returns the link to the next piece of content and updates the source of the iframe in javascript. This works fine.
Javascript
function sendToFrame(source) {
window.frames.SCODisplay.location.href = source;
}
function NavigationRequest(id, resource, type) {
var result = null;
$.ajax({
type: 'POST',
url: '/Content/NavigationRequest/',
data: {type : type},
async: false,
success: function (data) {
result = data;
}
});
if (result != null && result != "") {
var source = "../Content/" + resource + "/" + result;
sendToFrame(source, id)
}
}
Now the content can sometimes be navigated via buttons internally to the content. The content calls an API wrapper which sends to a data model the fact that after it terminates a continue request must be followed. Which works ok.
Now my problem is that on terminate my systems knows that a continue request is needed, it figures out what the next piece of content is and its link. I need to find a way to update the source of iframe from here....
public static String Terminate() {
//set entry to "" or resume, available to next learner session in current learner attempt
//if exit is set to suspend via nav request suspend all then entry set to resume upon next attempt on activity
//if exit anything other than suspend or no value set entry to ""
//when exit = suspend - save cmi.suspend_data to session
//decide whether to persist data
//save info to db using entities then call commit()
cocdType cmi;
try {
cmi = (cocdType)HttpContext.Current.Session["cmi"];
} catch {
return "false";
}
if (cmi.adlNavRequest != "_none_") {
SeqObject seqObj = new SeqObject();
seqObj.currentRequestType = SeqObject.type.Navigation;
seqObj.data.Navigation = cmi.adlNavRequest;
seqObj = loungeScormSeqNavHandler.SequencingProcess(seqObj);
NEED TO FIRE OFF IFRAME CHANGE SOURCE FROM HERE
}
return "true";
}
Does this make sense, any help is appreciated.
I have come up with a work around.
My terminate function returns the full link required for the iframe and in the original ajax call I have a simple if that determines if the result isnt true or false, blank or null then it must be a link then play with it from there. Then set result to true or false after.

Resources