Muhammad Danish Khan
Muhammad Danish Khan

Reputation: 459

Returning response in Struts2 RESTful plugin POST request

I have implemented Struts2 REST API from getting info from here

Struts2 Rest Plugin

Is there any way to return custom response in in restful plugin in Struts2. I did all the required changes like

struts.rest.content.restrictToGET = false

Got from This Question. Still I'm getting this error

No result defined for action `com.web.Controller.RestDemoController` and result create, 

If I don't add the above line I still get the same response.

This is the action i have provided in struts.xml:

<action name="restdemo" class="com.web.Controller.RestDemoController">
    <interceptor-ref name="customRestStack"></interceptor-ref>
</action>

This serves all the request GET,POST,PUT,UPDATE.

After Changing return type of post method from HttpHeader to String I'm still getting the same error

Error 404: No result defined for action com.web.Controller.RestDemoController and result <?xml version="1.0" encoding="UTF-8"?> <Status><code>200</code><message>Success</message></Status>

This is the code i have written for POST:

public HttpHeaders create(){
    System.out.println(envision2Data.toString());
    return new DefaultHttpHeaders("create").withStatus(200);
}

this is the POST request method with return type String:

public String create(){
    System.out.println(envision2Data.toString());
    return "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <Status><code>200</code><message>Success</message></Status>";
}

I'm getting perfect response for get either if i send request for xml or json, I do get xml and json based on extension. like http://localhost:8080/restdemoapplication/restdemo.xml, http://localhost:8080/restdemoapplication/restdemo.json

for POST request i do post request like enter image description here

and you can see the response i get. The method i have written for post is written above with name create. I do have data in body and I do get the data in create method perfectly.

Now in post as i have seen in multiple example like

struts-rest, stuts2-rest-sample, struts2-rest-shopping-list

I don't want to return response for post request like these applications do. I want to return my own response, It will be a status code and a message like this

<?xml version="1.0" encoding="UTF-8"?> <Status><code>200</code><message>Success</message></Status>

After some debugging I found that DefaultContentTypeHandlerManager in struts2-rest-plugin consider xhtml as default template. While it should be either XML or JSON.

I want to return

 code : 1xx,2xx,4xx
 message: Success, Fail

in either XML or JSON when a POST request is entertained.

(This is application entertains both non-restful request and restful requests. I can make xml or json as default template but I don't want as it will effect non-restful requests.)

Upvotes: 4

Views: 2821

Answers (2)

Roman C
Roman C

Reputation: 1

You misunderstood the concept of content types used with struts2-rest-plugin.

Content Types

In addition to providing mapping of RESTful URL's to Controller ( Action ) invocations, the REST plugin also provides the ability to produce multiple representations of the resource data. By default, the plugin can return the resource in the following content types:

  • HTML
  • XML
  • JSON

There is nothing configure here, just add the content type extension to your RESTful URL. The framework will take care of the rest. So, for instance, assuming a Controller called Movies and a movie with the id of superman, the following URL's will all hit the

http://my.company.com/myapp/movies/superman
http://my.company.com/myapp/movies/superman.xml
http://my.company.com/myapp/movies/superman.xhtml
http://my.company.com/myapp/movies/superman.json

Note, these content types are supported as incoming data types as well. And, if you need, you can extend the functionality by writing your own implementations of org.apache.struts2.rest.handler.ContentTypeHandler and registering them with the system.

The plugin servers request by content type, either provided as action extension or by providing a data type. Incoming data type is defined by "Content-Type" header, and outgoing data type defined by "Accept" header.

To make POST request returning data you need to add a constant to Struts configuration file struts.xml:

<constant name="struts.rest.content.restrictToGET" value="false"/>

Demo application is provided with the Struts distro named struts2-rest-showcase. After adding a constant above you can test the application with some http client.

POST http://localhost:8080/orders
Accept: application/json
Content-Type: application/json
{
  "id":"23423423",
  "clientName":"Roman C",
  "amount": 1000
}
 -- response --
201 
Content-Language:  en-US
Content-Length:  54
Content-Type:  application/json;charset=UTF-8
Date:  Sat, 07 Oct 2017 20:44:39 GMT
ETag:  -735433458
Location:  http://localhost:8080/orders/23423423

{"amount":1000,"clientName":"Roman C","id":"23423423"}

Upvotes: 2

Muhammad Danish Khan
Muhammad Danish Khan

Reputation: 459

So here is the solution which I needed. What I did is

@Override
public Object getModel() {
        <!-- Changed name of the object overhere to mainObject-->
    if (mainObject == null) {
        if (responseObject != null) {
            return responseObject;
        } else if (mainObject != null) {
            return mainObject;
        }
        mainObject = new mainObject();
    }
    return mainObject;
}

and then in content type handler. Content-Type handler is custom as I have used Jackson for conversion from JSON to object and vice versa.

if (paramObject instanceof MainObject) {
        MainObject mainObject = (MainObject) paramObject;
        writer.write(mapper.writeValueAsString(mainObject));
} else if (paramObject instanceof ResponseObject) {
        ResponseObject responeObject = (ResponseObject) paramObject;
        writer.write(mapper.writeValueAsString(responeObject));
} 

Upvotes: 0

Related Questions