I’m having trouble getting JSON results working with Struts 2.2.1.1.
Does anyone have a simple working example that returns a JSON result to a JSP using Struts 2.2.1.1 and is ready to run in Eclipse as a dynamic web project?
Please include the struts.xml, action class and JSP code. Also, note dependencies. Thank you.
Here’s how to create a simple JSON example using the Struts 2 jQuery plugin.
Go to Struts2 jQuery Plugin Showcase
Navigate to Ajax Forms > Buttonset / Checkboxes
Review the code for Buttonset that was populated from AJAX JSON Result. This is code I selected to create a simple example.
Create dynamic web project in Eclipse
Create a Java package and name it test.
Download the Struts 2 jQuery plugin showcase source (struts2-jquery-showcase-x.x.x-sources.jar) and extract the JAR file.
Import Echo.java, JsonSample.java, and ListValue.java into the test package and move the code into the package with quick fix.
Change the class annotation in Echo.java and JsonSample.java to #ParentPackage(value = "test")
In addition to the standard Struts 2 libraries, ensure that the struts2-json-plugin-x.x.x.jar, struts2-jquery-plugin-x.x.x.jar, and struts2-convention-plugin-x.x.x.jar files are in your classpath.
Create a struts.xml file and add the following XML:
<struts>
<constant name="struts.devMode" value="true" />
<constant name="struts.convention.action.packages" value="test" />
<package name="test" extends="json-default” namespace="/">
</package>
</struts>
Create an index.jsp file and insert the following code:
<s:form id="form2" action="echo" theme="xhtml">
<s:url id="remoteurl" action="jsonsample" />
<sj:checkboxlist href="%{remoteurl}" id=“remoteCheckboxlist” name="echo" list="languageList" label="Language" />
<sj:submit targets="formResult" value="AJAX Submit" indicator=“indicator” button="true"/>
</s:form>
Run the example.
Must see : struts2-x.x.x-all.zip /apps/struts2-showcase-2.2.1.war
Struts 2 and JSON example
Struts 2 autocompleter + JSON example
It is very simple to get Json work with struts2.
For this,
you need to add struts-json plugin*(jsonplugin-0.32.jar)* to classpath.
Your struts.xml file should extends json-default
<package name="base" namespace="/" extends="json-default">
Your action result be like this.
<result type="json"><param name="root">jsonData</param></result>
Inside action class, declare json as
private LinkedHashMap<K, V> jsonData new LinkedHashMap<k, V>();
and then add the result list to json like
jsonData.put("result", anyList or object);
Thats all we have to do. Then we can access the result using javascript.
Try this, will help you in Struts 2.0.14 with jsonplugin-0.32.jar.
struts.xml:
<struts>
<package name="example" extends="json-default">
<action name="HelloWorld" class="example.HelloWorld" >
<result type="json" />
</action>
<action name="HelloWorld1" class="example.HelloWorld" >
<result name="success" >example/HelloWorld.jsp</result>
</action>
</package>
</struts>
action class Helloworld.java:
package prabhakar;
import glb.DB;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Prabhakar
*/
public class HelloWorld {
private List<StateMaster> stateList= new ArrayList<StateMaster>();
private List<RegnMaster> regnList= new ArrayList<StateMaster>();
private Integer stateId;
public Integer getStateId()
{
return this.stateId;
}
public void setStateId(Integer stateId)
{
this.stateId=stateId;
}
public List<StateMaster> getStateList() {
return stateList;
}
public void setStateList(List<StateMaster> stateList) {
this.stateList = stateList;
}
public void setRegnList(List<RegnMaster> regnList) {
this.regnList = regnList;
}
public List<RegnMaster> getRegnList() {
return regnList;
}
public String execute() throws Exception {
stateList=DB.getStateData()//
if(stateId !=null)
{
regnList=DB.getRegnByStateId(stateId);
}
//setMessage(getText(MESSAGE));
return "success";
}
/**
* Provide default valuie for Message property.
*/
}
You can directly call HelloWorld.action to view the JSON data or else you can bind the JSON data to a form element below.
JSP page HelloWorld.jsp:
/*
Prabhakar
*/
<%# page contentType="text/html; charset=UTF-8" %>
<%# taglib prefix="s" uri="/struts-tags" %>
<script>
<%#include file="../js/jquery-1.7.1.min.js"%>
</script>
<html>
<!-- JavaScript Plugins -->
<script>
function getLoad(){
var stateId = $('#state').val();
$.getJSON('HelloWorld.action', {'stateId': stateId},
function(data) {
var divisionList = (data.regnList);
var options = $("#regn");
options.find('option')
.remove()
.end();
options.append($("<option />").val("-1").text("--Select--"));
$.each(divisionList, function() {
options.append($("<option />").val(this.regnId).text(this.regnName));
});
}
);}
</script>
<!-- jQuery-UI Dependent Scripts -->
<body>
State List <s:select name="stateId" list="stateList" id="state" listKey="stateId" onchange="getLoad()" listValue="stateName" headerKey="0" headerValue="--select--" />
Regn List <s:select name="regnId" list="regnList" listKey="regnId" id="regn" listValue="regnName" headerKey="0" headerValue="--select--" />
</body>
</html>
Happy coding :)
Related
I need to call the service and retrieve the resulted data in call back function from it but I am getting js error:
Uncaught ReferenceError: InvoiceHTMLService is not defined.
Please help - below are my pages and class
My Aspx page
<%# Page Language="vb" AutoEventWireup="false" CodeBehind="InvoiceHTML.aspx.vb" Inherits="WebApplication2.InvoiceHTML" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Web Service call from client-side JavaScript</title>
<script type="text/javascript">
function SendRequest() {
debugger;
InvoiceHTMLService.GetBillInvoiceHtmlData();
}
function OnComplete(arg) {
alert(arg);
}
function OnTimeOut(arg) {
alert("timeOut has occured");
}
function OnError(arg) {
alert("error has occured: " + arg._message);
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="~/Service/InvoiceHTMLService.asmx" />
</Services>
</asp:ScriptManager>
<div>
<input type="text" value="" id="MyTextBox" />
<input type="button" value="Send Request to the Web Service"
id="RequestButton" onclick="return SendRequest()" />
</div>
</form>
</body>
</html>
my asmx page
Imports System.Web.Script.Services
Imports System.Web.Services
Imports System.Collections.Generic
Imports System.Text
Imports System.Drawing
Imports System.Web.Services.Protocols
Imports System.ComponentModel
Imports System.IO
Imports ClassLibrary1
' To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
' <System.Web.Script.Services.ScriptService()> _
<WebService()> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ScriptService()> _
Public Class InvoiceHTMLService
Inherits System.Web.Services.WebService
<WebMethod()> _
Public Function GetBillInvoiceHtmlData() As Object
Dim objDAOBill As DAOInvoice
Dim Obj As Object
objDAOBill = New DAOInvoice()
Obj = objDAOBill.GetBillInvoiceHtmlData()
Return Obj
End Function
End Class
I got the answer for it thanks everyone, I am posting the answer so it may can help others the service call from client side can be done by using the complete class name present in .asmx page.In my Case
<%# WebService Language="vb" CodeBehind="InvoiceHTMLService.asmx.vb" Class="App.InvoiceHTMLService" %>
So I have to call the service in following way:
function SendRequest() {
App.InvoiceHTMLService.GetBillInvoiceHtmlData(callback);
}
I wanna use appsettings value from web.config file on html page in javascript or jquery. The content from my web.config file is:
<configuration>
<appSettings>
<add key="ServiceURL" value="http://localhost:16917/Service1.svc"></add>
</appSettings>
</configuration>
I have tried with
var serviceUrl='<%=ConfigurationManager.AppSettings["ServiceURL"].ToString() %>'
alert(serviceUrl);
Instead of showing value from webconfig it is showing <%=ConfigurationManager.AppSettings["ServiceURL"].ToString() %> on alert.
Can anybody help me please.
I think you are missing closing tag '>'
<configuration>
<appSettings>
<add key="ServiceURL" value="http://localhost:16917/Service1.svc"> </add>
</appSettings>
</configuration>
1. Change WebConfig UI
<pages pageBaseType="Main.Web.ViewPage">
Create an abstract class that implement from the WebViewPage.
public abstract class ViewPage<T> : WebViewPage<T>
{
public ViewPage()
{
}
public JSSettings UISession
{
get
{
var appSettingsFileBasedSettings = new JSSettings()
{
SessionTimeoutMinutes = ConfigurationManager.AppSettings["SessionTimeoutMinutes"]
};
return appSettingsFileBasedSettings;
}
}
}
In the html page just do something like.
<script type="text/javascript">
var show = {
Settings : #Html.Raw(Json.Encode(this.UISession))
};
console.log(show);
</script>
Hope it help.
This should work:
var test = {
ServiceURL: <%=ConfigurationManager.AppSettings["ServiceURL"] %>
}
You can't do that with static HTML file, at least not in any good way.
Instead, use the power of ASP.NET and work with a Web Form, where you have Code Behind.
In the code behind, send the value from the server to the client as JS variable:
protected void Page_Load(object sender, EventArgs e)
{
Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), "ServiceURL_JS",
string.Format("var serviceUrl = \"{0}\"; ",
ConfigurationManager.AppSettings["ServiceURL"]), true
);
}
Now you can access the variable serviceUrl in the client side JS.
I'm currently trying to call a JS script in order to export chart from primefaces chart component.
The problem is that the base64str variable seem to be null, and the responsible script for filling this value is not called for some reason :
xhtml code :
<p:chart id="chart" type="line" widgetVar="chart" model="#{cont.lineModel}" style="height:550px;width:1800px">
<p:ajax event="itemSelect" listener="#{cont.itemSelect}" update="growl" />
</p:chart>
<p:commandButton id="exp" value="Export" icon="ui-icon-extlink"
onclick="exportChart();" actionListener="#{cont.submittedBase64Str}"
/>
<h:inputHidden id="b64" value="#{cont.base64Str}" />
<script type="text/javascript">
function exportChart() {
img = chart.exportAsImage();
document.getElementById('hform:b64').value = img.src;
}
</script>
Controller :
public void submittedBase64Str(ActionEvent event){
// You probably want to have a more comprehensive check here.
// In this example I only use a simple check
if(base64Str.split(",").length > 1){
String encoded = base64Str.split(",")[1];
byte[] decoded = org.apache.commons.codec.binary.Base64.decodeBase64(encoded);
// Write to a .png file
try {
RenderedImage renderedImage = ImageIO.read(new ByteArrayInputStream(decoded));
ImageIO.write(renderedImage, "png", new File("D:\\out.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
Thanks
Change your onclick attribute to onstart.
<p:commandButton id="exp" value="Export" icon="ui-icon-extlink"
onstart="exportChart();" actionListener="#{cont.submittedBase64Str}" />
That should call the JS function.
EDIT
Also, you need to define img and chart in your function.
chart object is the PrimeFaces JS widget. You define widgetVar:
<p:chart ... widgetVar="chart"
And then you can get the chart object in your JS code like this:
PF('chart')
You need to use the PF function to get widgets since PrimeFaces 4.0.
As a side note, it's better to make your img variable local instead of global:
var img = chart.exportAsImage();
Now img is defined only in the scope of the function.
i've wrote a code for uploading file from jsp to mysql database using jquery-ajax on selecting a file from file browser. on selecting a file the JavaScript passes the file and id as parameter to action class, but i'm getting null value for the file in action class.
can anyone please tell me how to solve this problem.
index.jsp
<%#taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<script src="js/jquery-1.7.2.min.js"></script>
<script src="js/jquery-ui-1.8.21.custom.min.js"></script>
<script>
function filebrowse(toolid){
document.getElementById("toolidforimg").value=toolid;
$("#filetochange").trigger('click');
return false;
}
function changeFile(var3)
{
var param="filetochange="+(document.getElementById("filetochange").value)+"&toolidforimg="+document.getElementById("toolidforimg").value;
var resultStringX = $.ajax({
type: "POST",
url:"getFileChange.action",
enctype: 'multipart/form-data',
data: param,
async: false
}).responseText;
resultStringX=$.trim(resultStringX);
return false;
}
</script>
</head>
<body>
<s:hidden value="" name="toolidforimg" id="toolidforimg"/>
Change File
<input style="opacity:0;" type="file" onchange="changeFile(this.value)" id="filetochange" name="filetochange" >
</body>
</html>
struts.xml
<action name="getFileChange" class="com.MyactionClass" method="getFileChange">
<result name="success">browseFiles.jsp</result>
</action>
MyactionClass.java
class MyactionClass
{
File filetockhange;
String toolidforimg;
public File getFiletochange() {
return filetochange;
}
public void setFiletochange(File filetochange) {
this.filetochange = filetochange;
}
public String getToolidforimg() {
return toolidforimg;
}
public void setToolidforimg(String toolidforimg) {
this.toolidforimg = toolidforimg;
}
public String getFileChange()
{
HERE I AM GETTING filetochange VALUE AS NULL
return SUCCESS;
}
}
Put an HTML Form element around the fields you want to send (File, Hidden, etc).
That should be enough.
Some hints:
always specify a DTD, or you will fall in the odd world of the Quirks Mode. In your case, the HTML5 DTD should fit because you can upload files through AJAX only with HTML5: change <html> with <!DOCTYPE html>
always use Struts2 Tags instead of HTML tags when possible, like <s:form>, <s:file> and <s:a>.
only the accessors (getters) should begin with get, not other methods and for sure not an Action name;
Friends,
I am trying to use DyGraph in my application. Please look at the code below -
<head>
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7; IE=EmulateIE9">
<title>crosshairs</title>
<script type="text/javascript" src="dygraph-combined.js"></script>
<script type="text/javascript" src="data.js"></script>
</head>
The code uses data.js file containing function to get some static data.
I want data.js to be generated using a controller method so that it will generate data using database.
Can anybody help me out to resolve this issue.
Thanks for sharing your valuable time.
You could define a controller action:
public ActionResult Data()
{
// Obviously this will be dynamically generated
var data = "alert('Hello World');";
return JavaScript(data);
}
and then:
<script type="text/javascript" src="<%= Url.Action("Data", "SomeController") %>"></script>
If you have some complex script that you don't want to generate in the controller you could follow the standard MVC pattern by defining a view model:
public class MyViewModel
{
... put required properties
}
a controller action which would populate this view model and pass it to the view:
public ActionResult Data()
{
MyViewModel model = ...
Response.ContentType = "application/javascript";
return PartialView(model);
}
and finally a view which in this case will be the javascript representation of the view model (~/Views/SomeController/Data.ascx):
<%# Control
Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<MyViewModel>" %>
alert(<%= new JavaScriptSerializer().Serialize(Model.Name) %>);
Full Disclosure
This answer is copy/pasted from another question:
Dynamically generated Javascript, CSS in ASP.NET MVC
This answer is similar to other answers here.
This answer uses cshtml pages rather than ascx controls.
This answer offers a View-Only solution rather than a Controller-Only solution.
I don't think my answer is 'better' but I think it might be easier for some.
Dynamic CSS in a CSHTML File
I use CSS comments /* */ to comment out a new <style> tag and then I return; before the closing style tag:
/*<style type="text/css">/* */
CSS GOES HERE
#{return;}</style>
Dynamic JS in a CSHTML File
I use JavaScript comments // to comment out a new <script> tag and then I return; before the closing script tag:
//<script type="text/javascript">
JAVASCRIPT GOES HERE
#{return;}</script>
MyDynamicCss.cshtml
#{
var fieldList = new List<string>();
fieldList.Add("field1");
fieldList.Add("field2");
}
/*<style type="text/css">/* */
#foreach (var field in fieldList) {<text>
input[name="#field"]
, select[name="#field"]
{
background-color: #bbb;
color: #6f6f6f;
}
</text>}
#{return;}</style>
MyDynamicJavsScript.cshtml
#{
var fieldList = new List<string>();
fieldList.Add("field1");
fieldList.Add("field2");
fieldArray = string.Join(",", fieldList);
}
//<script type="text/javascript">
$(document).ready(function () {
var fieldList = "#Html.Raw(fieldArray)";
var fieldArray = fieldList.split(',');
var arrayLength = fieldArray.length;
var selector = '';
for (var i = 0; i < arrayLength; i++) {
var field = fieldArray[i];
selector += (selector == '' ? '' : ',')
+ 'input[name="' + field + '"]'
+ ',select[name="' + field + '"]';
}
$(selector).attr('disabled', 'disabled');
$(selector).addClass('disabled');
});
#{return;}</script>
No Controller Required (using Views/Shared)
I put both of my dynamic scripts into Views/Shared/ and I can easily embed them into any existing page (or in _Layout.cshtml) using the following code:
<style type="text/css">#Html.Partial("MyDynamicCss")</style>
<script type="text/javascript">#Html.Partial("MyDynamicJavaScript")</script>
Using a Controller (optional)
If you prefer you may create a controller e.g.
<link rel="stylesheet" type="text/css" href="#Url.Action("MyDynamicCss", "MyDynamicCode")">
<script type="text/javascript" src="#Url.Action("MyDynamicJavaScript", "MyDynamicCode")"></script>
Here's what the controller might look like
MyDynamicCodeController.cs (optional)
[HttpGet]
public ActionResult MyDynamicCss()
{
Response.ContentType = "text/css";
return View();
}
[HttpGet]
public ActionResult MyDynamicJavaScript()
{
Response.ContentType = "application/javascript";
return View();
}
Notes
The controller version is not tested. I just typed that off the top of my head.
After re-reading my answer, it occurs to me it might be just as easy to comment out the closing tags rather than use the cshtml #{return;}, but I haven't tried it. I imagine it's a matter of preference.
Concerning my entire answer, if you find any syntax errors or improvements please let me know.