问题
I am struggling to access a JSON Representation of a Restlet Client Response when a 400 is expected.
Any 400 response returns as an exception. I cannot get the JSON from an exception. Any ideas?
Code:
public def run(Object testCaseData) {
ClientResource clientResource = RestAPIUtils.setClientResource(GroovyUtils.getDataValue(testCaseData, 'command').toString(), partnerAPICredential)
def JSONData = JSONUtils.createJSONObject(testCaseData)
Representation representation = RestAPIUtils.getRepresentation(JSONData)
try {
clientResource.post(representation).getText()
}
catch (Exception ex) {
println ex
}
}
For example, if I run the same request via SoapUI, I see the following for the JSON representation:
{"errors": [{
"code": "VALUE_INVALID",
"field": "type",
"description": "Field value is invalid."
}]}
I can't get this from my current code.
回答1:
After looking around, I noted that the clientResource object does contain the JSON Representation. Below is the updated code:
public def run(Object testCaseData) {
ClientResource clientResource = RestAPIUtils.setClientResource(GroovyUtils.getDataValue(testCaseData, 'command').toString(), partnerAPICredential)
def JSONData = JSONUtils.createJSONObject(testCaseData)
Representation representation = RestAPIUtils.getRepresentation(JSONData)
try {
clientResource.post(representation).getText()
}
catch (Exception ex) {
clientResource.response.entityAsText
}
}
In this case, I need to return 'clientResource.response.entityAsText' For all the java users who may come across this someday you need to return: 'clientResource.getResponse().getEntityAsText()'
回答2:
Edited: you can have a look to the following link for more details: https://templth.wordpress.com/2015/02/27/exception-handling-with-restlet/.
In fact since the version 2.3, Restlet introduces the concept of annotated exceptions for this. This comes along with classical annotated interfaces of Restlet.
For example, if you want to map a request that returns a contact into a bean Contact
. You can use something like that:
public interface MyService {
@Post
Contact addContact(Contact contact);
}
You can use custom exceptions in this context and throws these, as described below:
public interface ContactResource {
@Post
Contact addContact(Contact contact) throws MyValidationException;
}
This exception can use the annotation Status
. As described below:
@Status(value = 400, serialize = true)
public class MyValidationException extends RuntimeException {
public ServiceValidationException(String message, Exception e) {
super(message, e);
}
}
This exception can be thrown on the server side and serialized in the response as a bean (using its fields) thanks to the converter feature of Restlet. You can notice that we can add user fields to the custom exception.
For example, here, we could have a JSON content like this:
{
"message": "my validation message"
}
On the client side, when the response is received, this exception will be thrown and the content of the response (our JSON content for example) deserialized within the fields of the exception.
So we will have the following code:
ClientResource cr = new ClientResource("http://...);
ContactResource contactResource = cr.wrap(ContactResource.class);
try {
Contact newContact = new Contact();
newContact.setName("my name");
Contact addedContact = contactResource.addContact(newContact);
} catch(MyValidationException ex) {
String errorMessage = ex.getMessage();
}
In your context, the code of the exception would something like that:
@Status(value = 400, serialize = true)
public class MyValidationException extends RuntimeException {
private List<ValidationError> errors;
public ServiceValidationException() {
this.errors = new ArrayList<ValidationError>();
}
public ServiceValidationException(String message, Exception e) {
super(message, e);
this.errors = new ArrayList<ValidationError>();
}
public List<ValidationError> getErrors() {
return errors;
}
public void addError(String code, String field, String description) {
ValidationError error = new ValidationError();
error.setCode(code);
error.setField(field);
error.setDescription(description);
this.errors.add(error);
}
(...)
}
public class ValidationError {
private String code;
private String field;
private String description;
// Getters and setters
(...)
}
Note
You can also choose note to use annotated interfaces / exceptions and work on representations directly, as described below:
ClientResource clientResource = (...)
JSONObject jsonObj = (...)
try {
Representation repr = clientResource.post(new JsonRepresentation(jsonObj));
(...)
}
catch (ResourceException ex) {
Representation responseRepresentation = clientResource.getResponseEntity();
JsonRepresentation jsonRepr
= new JsonRepresentation(responseRepresentation);
JSONObject errors = jsonRepr.getJsonObject();
(...)
}
Hope it helps, Thierry
来源:https://stackoverflow.com/questions/28589877/json-representation-of-a-http-400-for-restlet-client