Reputation: 2441
I have a Controller that receives accepts http file uploads and responds with a JSON confirmation. If there is is any sort of problem with the procsessing of the upload I want to return an HTTP error status code (e.g. 403 for malformed requests or 500 for a general processing error), but I also want to send a JSON list of detailed error messages. I know how to return a 500 error (thanks to this post) but I don't know how to return the 500 code and still send content.
Here's a snippit of my code (which doesn't do what I want it to):
@Action(value = "upload", results = {
@Result(name = SUCCESS, type = "freemarker", location = "results.ftl", params = { "contentType", "text/plain" }),
@Result(name = ERROR, type = "freemarker", location = "error.ftl", params = { "contentType", "text/plain" }),
@Result(name = ERROR, type = "httpheader", params = { "status", "500" })
})
public String upload() {
//do stuff
if(CollectionUtils.isEmpty(getActionErrors()) {
return SUCCESS;
} else {
return ERROR;
}
}
Upvotes: 4
Views: 13045
Reputation: 559
In case someone is looking for the struts.xml version of the accepted answer, I'm going to leave it here:
<action name="upload"
class="...">
<exception-mapping exception="java.lang.Exception" result="error"/>
<result name="error" type="json">
<param name="statusCode">418</param>
</result>
<result name="Success" type="json" />
</action>
Upvotes: 2
Reputation: 2441
Update 2/24/15: ty-danielson's answer is the correct one. It applies to JSON responses, which is what I wanted even though I was using freemarker templates to generate them (another bad idea).
If you really want a freemarker template with error status code: My original answer is still the wrong approach because it's bad form to access the ServletResponse from inside an action method. Struts' built-in FreemarkerResult does not accept a status code parameter, but you can easily add this functionality by subclassing it (example taken from GBIF project)
/**
* Same as FreemarkerResult, but with added 'statusCode' parameter.
* (don't forget to register this result type in struts-config.xml)
*/
public class FreemarkerHttpResult extends FreemarkerResult {
private int status;
public int getStatusCode() {
return status;
}
public void setStatusCode(int status) {
this.status = status;
}
@Override
protected void postTemplateProcess(Template template, TemplateModel data) throws IOException {
super.postTemplateProcess(template, data);
if (status >= 100 && status < 600) {
HttpServletResponse response = ServletActionContext.getResponse();
response.setStatus(status);
}
}
}
Then declare your action mapping like so:
@Action(value = "myAction", results = {
@Result(name = SUCCESS, type = "freemarker", location = "results.ftl"),
@Result(name = ERROR, type = "freemarkerhttp", location = "error.ftl", params = { "statusCode", "500"})
})
public String myAction() {
//do stuff, then return SUCCESS or ERROR
}
So, I'm not sure if this is "proper" from a struts2 perspective, but here's a solution that acomplishes my goal of returning the http error code while still being able to render a freemarker template. I'll mark this as the answer until a better one comes along.
@Action(value = "upload", results = {
@Result(name = SUCCESS, type = "freemarker", location = "results.ftl", params = { "contentType", "text/plain"}),
@Result(name = ERROR, type = "freemarker", location = "error.ftl", params = { "contentType", "text/plain"})
})
public String upload() {
try {
//do stuff
} Catch(SomeExceptionType ex) {
addActionError("you did something bad");
HttpServletResponse response = ServletActionContext.getResponse();
response.setStatus(400);
}
}
Upvotes: 2
Reputation: 669
This is an old post, but if you are using the Struts-JSON which I suggest using you can simply return an error object with what you want and attach the status code like below:
@Result(name = ERROR, type="json",
params = {"root","errorResponse", "statusCode", "500"}
)
Upvotes: 3
Reputation: 22425
I don't have time to setup a test Struts2 application, but maybe have a single error result:
@Result(name = ERROR, type = "freemarker", location = "error.ftl",
params = { "contentType", "text/plain", "status", "500" })
Upvotes: -1