I use the following JavaScript/jQuery function to make a remote procedure call.
<script src="../js/jquery-1.8.0.min.js" type="text/javascript"></script>
<s:url var="testJsonUrl" action="testJsonAction"/>
var timeout;
var request;
$(document).ready(function(){
$("#btnUser").click(function(){
if(!request)
{
request = $.ajax({
datatype:"json",
type: "GET",
data: JSON.stringify({jsonrpc:'2.0', method:'getUser', id:'jsonrpc'}),
contentType: "application/json-rpc; charset=utf-8",
url: "<s:property value='#testJsonUrl'/>",
success: function(response)
{
var user = response.result;
alert(JSON.stringify(user)); //Always alerts "undefined".
},
complete: function()
{
timeout = request = null;
},
error: function(request, status, error)
{
if(status!=="timeout"&&status!=="abort")
{
alert(status+" : "+error);
}
}
});
timeout = setTimeout(function() {
if(request)
{
request.abort();
alert("The request has been timed out.");
}
}, 30000);
}
});
});
The above function is called, when a button is clicked as follows.
<s:form namespace="/admin_side" action="Test" validate="true" id="dataForm" name="dataForm">
<input type="button" name="btnUser" id="btnUser" value="Click"/>
</s:form>
The action class in which the method is to be invoked is as follows.
import com.opensymphony.xwork2.ActionSupport;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.InterceptorRef;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.ResultPath;
import org.apache.struts2.json.annotations.SMDMethod;
import util.User;
@Namespace("/admin_side")
@ResultPath("/WEB-INF/content")
@ParentPackage(value = "json-default")
public final class TestAction extends ActionSupport
{
private User user;
public TestAction() {}
@SMDMethod
public User getUser()
{
user = new User();
user.setName("Tiny");
user.setLocation("India");
try {
user.setDob(new SimpleDateFormat("dd-MMM-YYYY").parse("29-Feb-2000"));
} catch (ParseException ex) {
Logger.getLogger(TestAction.class.getName()).log(Level.SEVERE, null, ex);
}
return user;
}
public void setUser(User user) {
this.user = user;
}
@Action(value = "testJsonAction",
results = {
@Result(type = "json", params = {"enableSMD", "true", "excludeNullProperties", "true"})},
interceptorRefs = {
@InterceptorRef(value = "json", params = {"enableSMD", "true"})})
public String executeAction() throws Exception {
return SUCCESS;
}
@Action(value = "Test",
results = {
@Result(name = ActionSupport.SUCCESS, location = "Test.jsp"),
@Result(name = ActionSupport.INPUT, location = "Test.jsp")},
interceptorRefs = {
@InterceptorRef(value = "defaultStack", params = {"params.acceptParamNames", "", "params.excludeMethods", "load", "validation.validateAnnotatedMethodOnly", "true"})})
public String load() throws Exception {
//This method is just needed to return a view on page load.
return ActionSupport.SUCCESS;
}
}
The User
class:
public class User
{
private String name;
private Date dob;
private String location;
//Setters & getters.
}
The getUser()
method (in the action class TestAction
) annotated with @SMDMethod
is expected to be invoked, when the given button is clicked but it does not.
This line alert(JSON.stringify(user));
in the success
handler of the jQuery function always alerts undefined
.
Using a direct link in the address bar like,
http://localhost:8080/TestStruts/admin_side/testJsonAction.action
returns the following string.
{
"methods": [{
"name": "getUser",
"parameters": []
}],
"serviceType": "JSON-RPC",
"serviceUrl": "\/TestStruts\/admin_side\/testJsonAction.action",
"version": ".1"
}
What is missing here? Why does not JSON-RPC
work?
PS : I'm using Struts2-json-plugin-2.3.16
with same version of the framework.