restlet / restlet-framework-java

The first REST API framework for Java
https://restlet.talend.com
Other
654 stars 284 forks source link

[Restlet GAE][2.3.6] Getting HTTP Status code 204 instead of 200 #1217

Open Atrix1987 opened 8 years ago

Atrix1987 commented 8 years ago

For the 1st request, I get the JSON response. From the next request onwards I start getting this log and HTTP Status Code 204, even though the ServerResource is successfully returning a representation. I even ran it in debug mode to verify if my server resources was returning the right repreentation or not.

Log Message that I see

org.restlet.engine.adapter.ServerAdapter commit
WARNING: A response with an unavailable and potentially non empty entity was returned. Ignoring the entity for resource http://localhost:8888/xyz?abc=def

Application class for wiring routes

public Example extends Application {
    @Override
    public Restlet createInboundRoot() {
        router = new Router(getContext());
        CorsService corsService = new CorsService();         
        corsService.setAllowedOrigins( new HashSet<String>(Arrays.asList("http://xyz.com")));
        corsService.setAllowedCredentials(true);
        getServices().add(corsService);

         router.attach("/xyz", XYZ.class);
    }
}

Server Resource which handles and returns a JSON Representation

public class XYZ extends ServerResource {

    private static final Logger logger = Logger.getLogger("API:Xyz");

    @Get(":json")
    public Representation handleGetRequest() {
         ..
         return API_RESPONSE.SUCCESS; //Where SUCCESS is a JsonRepresentation
    }
}
Atrix1987 commented 8 years ago

After a lot of debugging, I figured it out what was happening.

In ServerResource class handle method it checks for fresh content in the representation.

    @Override
    public Representation handle() {
           ...
            } finally {
                if (Status.CLIENT_ERROR_METHOD_NOT_ALLOWED.equals(getStatus())) {
                    updateAllowedMethods();
                } else if (Status.SUCCESS_OK.equals(getStatus())
                        && (getResponseEntity() == null || !getResponseEntity()
                                .isAvailable())) {
                    getLogger()
                            .fine("A response with a 200 (Ok) status should have an entity. "
                                    + "Changing the status to 204 (No content).");
                    setStatus(Status.SUCCESS_NO_CONTENT);
                }
            }
        }
        return result;
    }

In my case, I was returning a static JsonRepresentation instead of a new JsonRepresentation every time. After the 1st API response, the Representation#release() is called which calls setAvailable(false);

Is it required to return a new JsonRepresentation for every API request ? I added a method which sets the available to true before returning every response. This was I am able to avoid the issue.