1

I'm using Struts2-json-plugin-2.3.16 with the same version of the framework. I get an empty response from JSON.

The JavaScript/jQuery function.

var timeout;
var request;

function getUsers()
{
    if(!request)
    {                    
        request = $.ajax({
            datatype:"json",
            type: "GET",
            contentType: "application/json; charset=utf-8",
            url: "testJsonAction.action",
            success: function(response)
            {
                var user= response.user;
                alert(user);
            },
            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 is called, when a button is clicked.

<s:form namespace="/admin_side" action="Test" validate="true" id="dataForm" name="dataForm">

    <input type="button" name="btnUser" id="btnUser" value="Click" onclick="getUsers();"/>

</s:form>

The action class:

@Namespace("/admin_side")
@ResultPath("/WEB-INF/content")
@ParentPackage(value = "json-default")
public final class TestAction extends ActionSupport {

    private User user;
    private static final long serialVersionUID = 1L;

    public TestAction() {
    }

    @JSON(name = "user")
    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Action(value = "testJsonAction",
    results = {
        @Result(type = "json", name = ActionSupport.SUCCESS, params = {"enableSMD", "true", "enableGZIP", "true", "excludeNullProperties", "true"})})
    public String executeAction() throws Exception {
        try {
            user = new User();
            user.setName("Tiny");
            user.setDob(new SimpleDateFormat("dd-MMM-YYYY").parse("29-Feb-2000"));
            user.setLocation("India");
        } catch (ParseException ex) {
            Logger.getLogger(TestAction.class.getName()).log(Level.SEVERE, null, ex);
        }

        return ActionSupport.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 {
        return ActionSupport.SUCCESS;
    }
}

The User class:

public class User
{
    private String name;
    private Date dob;
    private String location;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getDob() {
        return dob;
    }

    public void setDob(Date dob) {
        this.dob = dob;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }
}

The executeAction() method in the TestAction class is invoked, when the given button is clicked but I do not get a user object as a JSON response. It always seems to be empty.

What is missing here? Does it require other libraries in addition to the the Struts2-json-plugin-2.3.16 library?


Using a direct link like in this case, http://localhost:8080/TestStruts/admin_side/testJsonAction.action, I get the following string.

{"methods":[],"serviceType":"JSON-RPC","serviceUrl":"\/TestStruts\/admin_side\/testJsonAction.action","version":".1"}
Roman C
  • 49,761
  • 33
  • 66
  • 176
Tiny
  • 27,221
  • 105
  • 339
  • 599
  • Do you want to use JSON-RPC with the request? – Roman C Jan 25 '14 at 19:46
  • Sorry, I do not understand that. I have seen `JSON-RPC` first time! – Tiny Jan 25 '14 at 19:48
  • `enableSMD=true` used for [JSON-RPC](http://en.wikipedia.org/wiki/JSON-RPC) requests. It allows to pass objects to the action to execute methods and return results, so the same object could be used on the client and on the server, everything seems transparent. – Roman C Jan 25 '14 at 19:56
  • It only worked, when I removed `"root", "stateTables", "enableSMD", "true",` from the list of parameters, `params`. Otherwise, the response was empty. I did not understand. – Tiny Jan 25 '14 at 21:33
  • `enableSMD` parameter to the json result doesn't serialize root object to the output, instead it returns a JSON-RPC service definition that could be used by the client to call this service methods. But you didn't used `@SMDMethod` annotation on a method that should return an object you can get on the client. – Roman C Jan 25 '14 at 21:48
  • ... in other words to use JSON-RPC services, which you can define on the server, but seems only version 1.0, current is 2.0. However 2.0 client can handle 1.0 service, depends on implementation. – Roman C Jan 25 '14 at 21:57
  • ... There're so many implementations, but there's [one](https://plugins.jquery.com/jsonrpcclient/) that registered on jquery site. Also possible to make JSON-RPC requests via `$.ajax`. – Roman C Jan 25 '14 at 22:06
  • Thank you for these comments. I indeed need to study more about these things. Would you like to answer this question? I do not have a canonical answer. JSON works somehow now. – Tiny Jan 25 '14 at 22:48

1 Answers1

1

What should you do if you need to use JSON-RPC with Struts2:

Configure action that returns JSON-RPC service

@Action(value = "testJsonAction",
  results = @Result(type = "json", params = {"enableSMD", "true"}),
  interceptorRefs = @InterceptorRef(value="json", params={"enableSMD", "true"}))
public String executeAction() throws Exception {
  return SUCCESS;
}

create a method

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

Now, you need a JSON-RPC client to make a request, or try $.ajax

<s:url var="testJsonUrl" action="testJsonAction"/>
<script type="text/javascript">
  $(document).ready(function(){
    $("#btnUser").click(function(){
      $.ajax({
        type:"POST",
        url: "<s:property value='#testJsonUrl'/>",
        dataType:"json",            
        data: JSON.stringify({jsonrpc:'2.0', method:'getUser', id:'jsonrpc'}),  
        contentType: "application/json-rpc; charset=utf-8",
        success: function(response) {
          var user= response.result;  
          alert(JSON.stringify(user));
        }
      });
    });
  });
</script>
Roman C
  • 49,761
  • 33
  • 66
  • 176
  • I have tried exactly the same thing but the response is always empty. May be, I will have a next question :). It works without `JSON-RPC`. – Tiny Jan 26 '14 at 17:24
  • Today morning I updated the code with working solution, I didn't check that `ParseException` related to `User` initialization. – Roman C Jan 26 '14 at 17:32
  • The parse exception is not thrown. I receive this string as a response, `{"methods":[{"name":"getUser","parameters":[]}],"serviceType":"JSON-RPC","serviceUrl":"\/TestStruts\/admin_side\/testJsonAction.action","version":".1"}` with a direct link in the address bar. – Tiny Jan 26 '14 at 17:35
  • check the `contentType` property, I've changed that, also `serviceUrl` looks strange why it has escaped slash? I have not such escapes. The urls should be equal in the request and service. – Roman C Jan 26 '14 at 17:41
  • The `getUser()` method annotated with `@SMDMethod` is not invoked. When I add `"root", "user"` to the list of parameters - `param`, the `getUser()` method is invoked but the response is empty then. – Tiny Jan 26 '14 at 17:42
  • The `contentType` property is the same as mentioned, `contentType: "application/json-rpc; charset=utf-8"`. – Tiny Jan 26 '14 at 17:43
  • When you pressed the button has `getUser()` invoked? Did you remove `onclick` attribute of the button? – Roman C Jan 26 '14 at 17:58
  • No it is not invoked, when the button is clicked. It is invoked, when I use a direct link in the address bar like, `http://localhost:8080/TestStruts/admin_side/testJsonAction.action` provided that `"root", "user"` is added to `params` of `@Result`. – Tiny Jan 26 '14 at 18:01
  • You should not add "root" parameter. Check the javascript is valid and ajax is invoked, also the `json` interceptor does intercept it. – Roman C Jan 26 '14 at 18:04
  • I do not use the `root` parameter now. This line, `alert(JSON.stringify(user));` inside the `success` handler always alerts `undefined`. – Tiny Jan 26 '14 at 18:08
  • I have removed the `onclick` attribute of the button. `alert(JSON.stringify(user));` alerts `undefined`. – Tiny Jan 26 '14 at 18:17
  • Using the `POST` request alerts in the error handler that says, *forbidden* (403). – Tiny Jan 26 '14 at 18:26
  • what is the jquery version, I used struts2-jquery-plugin 3.6.1 also jqueryui="true" if it make sense. – Roman C Jan 26 '14 at 18:27
  • No, there is no `struts2-jquery-plugin` on the classpath. I removed it because it did not work throwing some exceptions on application start up. Does it require for `JSON-RPC` to work? – Tiny Jan 26 '14 at 18:30
  • no, but it setups jquery 10.x.x and it would probably required, I didn't test it on other jquery versions. – Roman C Jan 26 '14 at 18:33
  • I have downloaded `struts2-jquery-plugin-3.7.0` and added it to the classpath but it did not make a difference. The problem still remains stationary. – Tiny Jan 26 '14 at 18:54
  • Strange, but do you have a security framework in front of Struts2, also what if you change method POST to GET? – Roman C Jan 26 '14 at 20:15
  • The `GET` method alerts `undefined` in the `success` handler of jQuery. I use Spring Security but I access those resources after login. Therefore, there should not be security harm. By the way, I have asked a separate [question](http://stackoverflow.com/q/21368194/1391249). – Tiny Jan 26 '14 at 20:24
  • I have imported `org.apache.struts2.json.annotations.SMDMethod` but in the [documentation](http://struts.apache.org/release/2.2.x/docs/json-plugin.html) (at the end), they are using `com.googlecode.jsonplugin.annotations.SMDMethod`. Am I using the right annotation? – Tiny Jan 26 '14 at 21:29
  • yes, I still think you have a security restrictions, don't know which one without project sources. Try without it, I also forgot to add your namespace to the action url because I used "/" namespace, however I tried with namespace it also works, except parsing date. – Roman C Jan 26 '14 at 21:47
  • I have tried removing all security constraints still the problem remained unchanged. (commented all XML tags from `spring-security.xml` and security related tags from `web.xml`). – Tiny Jan 26 '14 at 22:04
  • May be you share a link to some github project, so I can see. However, the first thing I'd done at your place is remove security at all and tried on blank project. – Roman C Jan 26 '14 at 22:09