I use the following JavaScript/jQuery function to make a remote procedure call through JSON.
<s:url var="testJsonUrl" action="testJsonAction"/>
<script src="../js/jquery-1.8.0.min.js" type="text/javascript"></script>
var timeout;
var request;
$(document).ready(function(){
$("#countryComboBox").change(function(){
if(!request)
{
request = $.ajax({
datatype:"json",
type: "POST",
data: JSON.stringify({jsonrpc:'2.0', method:'getStateTables', id:'jsonrpc', params:[$("#countryComboBox").val()]}),
contentType: "application/json-rpc; charset=utf-8",
url: "<s:property value='#testJsonUrl'/>",
success: function(response)
{
alert(JSON.stringify(response.result));
},
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);
}
});
});
This function invokes the method getStateTables()
in an action class which is as follows.
@Namespace("/admin_side")
@ResultPath("/WEB-INF/content")
@ParentPackage(value = "json-default")
public final class TestAction extends ActionSupport
{
@Autowired
private final transient SharableService sharableService = null;
private static final long serialVersionUID = 1L;
List<StateTable> stateTables;
public TestAction() {}
@SMDMethod
public List<StateTable> getStateTables(@SMDMethodParameter(name="countryId")Long countryId) {
stateTables = sharableService.findStatesByCountryId(countryId);
return stateTables;
}
@Action(value = "testJsonAction",
results = {
@Result(name = ActionSupport.SUCCESS, type = "json", params = {"enableSMD", "true"})},
interceptorRefs = {
@InterceptorRef(value = "json", params = {"enableSMD", "true", "includeProperties", "result\\[\\d+\\]\\.stateId, result\\[\\d+\\]\\.stateName", "excludeNullProperties", "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 used to return an initial view on page load.
return ActionSupport.SUCCESS;
}
}
This method causes a list of states corresponding to the countryId
supplied by the jQuery function as a parameter to this method to be returned which is delegated to the jQuery function as a JSON response.
This works fine unless Spring Security comes into picture. While using Spring Security, the request is forbidden.
The header information can be viewed as follows.
Request URL:http://localhost:8080/TestStruts/admin_side/testJsonAction.action
Request Method:POST
Status Code:403 Forbidden
Request Headers
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Content-Length:73
Content-Type:application/json-rpc; charset=UTF-8
Cookie:JSESSIONID=0C4D7DFD269F1D5F7315A39971A75961; sbOverlayID=42887237
Host:localhost:8080
Origin:http://localhost:8080
Referer:http://localhost:8080/TestStruts/admin_side/Test.action
User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36
X-Requested-With:XMLHttpRequest
Request Payload
{jsonrpc:2.0, method:getStateTables, id:jsonrpc, params:[2]}
id: "jsonrpc"
jsonrpc: "2.0"
method: "getStateTables"
params: [2]
Response Headers
Content-Length:1149
Content-Type:text/html;charset=utf-8
Date:Tue, 28 Jan 2014 22:12:55 GMT
Server:Apache-Coyote/1.1
X-Content-Type-Options:nosniff
X-Frame-Options:DENY
X-XSS-Protection:1; mode=block
My Spring Security configurations are exactly the same as mentioned in this question.
Where to look into Spring Security?