Send a specific response, or at least a specific HTTP status code, using an exception - exception

In Django, there are a couple of exceptions that are designed to be intercepted by the framework and turned into specific HTTP response codes, such as 404 Not Found and 403 Forbidden.
This is especially useful for request validation, because it allows you to factor out common validation logic into utility functions and cleanup your controller actions.
Whenever the utility functions decide that the current request must be aborted with a specific HTTP error code, they can do so by throwing the relevant exception, without any support code in the controller action, in the form of a return statement or a try/catch.
For example, given a tree of nested REST resources:
static mappings = {
"/authors" (resources: "author") {
"/sagas" (resources: "saga") {
"/books" (resources: "book") {
}
}
}
Then the URL pattern for the Book resource is /authors/$authorId/sagas/$sagaId/books/$id, which means that any of the show(), delete(), or update() actions in BookController have this signature and must include some boilerplate validation logic:
def actionName(int authorId, int sagaId, Book book) {
// -- common validation logic ----------
// fetch parent objects
def author = Author.get(authorId)
def saga = Saga.get(sagaId)
// check that they exists
if (author == null || saga == null || book == null) {
return render(status: NOT_FOUND)
}
// check consistency
if (book.author != author || book.saga != saga || saga.author != author) {
return render(status: BAD_REQUEST)
}
// -- end of commond code --------------
...
}
What is the Grails way of factoring this out into a common method, while still allowing it to terminate request processing whenever an exceptional condition occurs?
I would think the best way is a NotFoundException, ForbiddenException, BadRequestException, and so on, or maybe a generic exception that accepts a HTTP status code. Is there anything like it in Grails? If not, where is the best place to add it? A filter?
Edit: I see now that the standard method is to add an error controller with a matching URL pattern, such as:
"500" (controller: "error")
The problem with this is that Grails will still log full stacktraces for all exceptions, including those that are not programming errors. This spams log files with all sorts of useless tracebacks.
Is there a solution?

You catch the exception in the beforeInterceptor closure of your controller. I resolved this same problem by examining the exception thrown and then acting accordingly. For example:
class BaseController {
/**
* Define DRA exception handlers. This prevents the default Grails
* behavior of returning an HTTP 500 error for every exception.
*
* Instead the exceptions are intercepted and modified according to
* the exception that was thrown. These exceptions are not logged
* whereas application exceptions are.
*/
def beforeInterceptor = {
request.exceptionHandler = { exception ->
def cause = exception.cause
def exceptionBody = [:]
if(cause.class == BadRequestException) {
response.setStatus(HttpStatus.BAD_REQUEST.value()) // HTTP 400 BAD REQUEST
exceptionBody.httpStatus = HttpStatus.BAD_REQUEST.value()
exceptionBody.error = cause.message
}
// render the exception body, the status code is set above.
render exceptionBody as JSON
return true
}
}
}
In order to get this to work you will have to create an ErrorController or something where all server errors are processed and rendered. For example:
class ErrorController {
def serverError() {
def handler = request.exceptionHandler
if(handler) {
request.exceptionHandler = null
if(handler.call(request.exception)) {
return
}
}
}
I have tested this an it does work. I copied the code from a running project that I have been working on. You can build out the if statement in the beforeInterceptor to catch any type of Exception you wish.

Related

Hystrix/Feign to solely react on HTTP status 429

I'm using Feign from the spring-cloud-starter-feign to send requests to a defined backend. I would like to use Hystrix as a circuit-breaker but for only one type of use-case: If the backend responds with a HTTP 429: Too many requests code, my Feign client should wait exactly one hour until it contacts the real backend again. Until then, a fallback method should be executed.
How would I have to configure my Spring Boot (1.5.10) application in order to accomplish that? I see many configuration possibilities but only few examples which are - in my opinion - unfortunately not resolved around use-cases.
This can be achieved by defining an ErrorDecoder and taking manual control of the Hystrix Circuit Breaker. You can inspect the response codes from the exceptions and provide your own fallback. In addition, if you wish to retry the request, wrap and throw your exception in a RetryException.
To meet your Retry requirement, also register a Retryer bean with the appropriate configuration. Keep in mind that using a Retryer will tie up a thread for the duration. The default implementation of Retryer does use an exponential backoff policy as well.
Here is an example ErrorDecoder taken from the OpenFeign documentation:
public class StashErrorDecoder implements ErrorDecoder {
#Override
public Exception decode(String methodKey, Response response) {
if (response.status() >= 400 && response.status() <= 499) {
return new StashClientException(
response.status(),
response.reason()
);
}
if (response.status() >= 500 && response.status() <= 599) {
return new StashServerException(
response.status(),
response.reason()
);
}
return errorStatus(methodKey, response);
}
}
In your case, you would react to 419 as desired.
You can forcibly open the Circuit Breaker setting this property at runtime
hystrix.command.HystrixCommandKey.circuitBreaker.forceOpen
ConfigurationManager.getConfigInstance()
.setProperty(
"hystrix.command.HystrixCommandKey.circuitBreaker.forceOpen", true);
Replace HystrixCommandKey with your own command. You will need to restore this circuit breaker back to closed after the desired time.
I could solve it with the following adjustments:
Properties in application.yml:
hystrix.command.commandKey:
execution.isolation.thread.timeoutInMilliseconds: 10_000
metrics.rollingStats.timeInMilliseconds: 10_000
circuitBreaker:
errorThresholdPercentage: 1
requestVolumeThreshold: 1
sleepWindowInMilliseconds: 3_600_000
Code in the respective Java class:
#HystrixCommand(fallbackMethod = "fallbackMethod", commandKey = COMMAND_KEY)
public void doCall(String parameter) {
try {
feignClient.doCall(parameter);
} catch (FeignException e) {
if (e.status() == 429) {
throw new TooManyRequestsException(e.getMessage());
}
}
}

GET,POST,PUT Which should be used for receiving a json object to my rest api and send a json object in response?

I'm writing my first web API using MVC.
I'm aware that POST and PUT are usually implemented to define the HTTP methods for inserting or updating a database behind an API. But all I want to do is receive a JSON object from the caller, do some processing then return another JSON object in response. No database is involved.
I've tested using both POST and GET in my API controller method and they both work ok but which http method should I actually be using for best practice?
eg
public IHttpActionResult Get(ApiEquipment equipment)
{
// Convert equipment to a compatible buffer
return Ok(new ConvertToBuffer(equipment));
}
GET is useful for SAFE(*) operations where you do not need to pass many parameters to the server - all of the parameters must be in the URL as GET operations do not pass data in the HTTP body.
POST is useful for UNSAFE(*) operations or operations where you need to pass large amounts of data to the server as the data can be passed in the HTTP body.
Use GET for simple queries and calculations with few parameters. Use POST for large payloads or operations that change server state (such as updating something or performing complex bussiness operations).
See the HTTP method definitions in RFC 7231 for more in-depth information.
(*) SAFE operations are operations that do not change (visible) server state. UNSAFE operations do change (visible) server state.
GET
It seems that your just want to retrieve data in a meaningful representation (response after processing) from the raw data (request from the caller).
There is no modification / insertion of data, so GET should be use.
The POST verb seems to be what you want.
If I understand correctly, you want to send a JSON from the client to server. Then the server will modify the JSON and return it to the client.
In REST APIs, POST is commonly used to create a new resource. But it's also a catch-all verb for operations that should not be executed using the other methods.
For more details on using POST to invoke arbitrary processing, have a look at this answer.
I would suggest you to use 'HTTPPOST' if you require to process your JSON object else useGETmethod.
Consider this example for using HttpPost method since I process the JSON object to get some info from database.
[HttpPost]
public IHttpActionResult Masters([FromBody]Download_Config_UserInfo Info)
{
List<TestMaster> testMaster = null;
ResponseValidation objValidation = new ResponseValidation();
try
{
#region Validation
objValidation = base.ValidateRequest(Info);
if (!objValidation.isValid)
return base.JsonErrorResult(this.MasterName, objValidation.ErrorCode, objValidation.ErrorDesc);
#endregion
#region Initialization
this.Initialization();
#endregion
#region Functionality
//testMaster = this.GetTestMaster();
testMaster = this.GetTestDateMaster();
if (testMaster == null)
return base.JsonErrorResult(this.MasterName, "E19", "Data Not Available");
var result = (from a in testMaster
select new object[]
{
a.TestId,
a.TestName
});
#endregion
return base.JsonResult(this.MasterName, this.Fields, result);
}
catch (Exception ex)
{
loggerService.Error(Info.ToJSON(), this.MasterName, ex);
return base.JsonErrorResult(this.MasterName, "E20", "Internal Server Error", ex.Message + "_" + ex.StackTrace);
}
finally
{
testMaster = null; objValidation = null; base.UserMaster = null; base.UserPositionMapping = null;
}
}
#endregion
#region Functionality
[NonAction]
public List<TestMaster> GetTestMaster()
{
List<ADM_Retailer> testMaster = null;
try
{
testMaster = this.GetTest();
if (testMaster == null || (testMaster.Count == 0)) { return null; }
string weekNo = base.GetWeekNumber();
return (from a in testMaster
select new TestMaster
{
TestId = a.ARTR_Id,
TestName = a.ARTR_Name,
}).ToList();
}
finally { }
}

Can't get an implementation of Grails ObjectMarshaller<JSON> to work

I'm trying to implement a custom marshaller in Grails. Here's the marshaller:
class AdultPlanningMarshaller implements ObjectMarshaller<JSON> {
boolean supports(Object theObject)
{
return theObject instanceof AdultPlanning
}
void marshalObject(Object theObject, JSON theConverter)
{
AdultPlanning adult = (AdultPlanning)theObject
JSONWriter writer = theConverter.getWriter()
writer.object()
writer.key('id').value(adult.id)
...
writer.endObject()
}
}
I'm registering it in bootstrap.groovy and when I run my integration tests, the supports method fires correctly and the marshalObject method is called with the right object and a JSON object.
When I hit the:
writer.object()
call, an exception gets thrown:
org.codehaus.groovy.grails.web.json.JSONException: Misplaced object: expected mode of INIT, OBJECT or ARRAY but was DONE
So it looks like the writer has already done something to completion, but I have no clue what.
There's not a lot of documentation on JSON marshallers and examples are thin on the ground, but I think I've done this right but it sure isn't working. Any hints would be appreciated.
Further work with the debugger seems to indicate that the object marshaller is being called twice, although breakpoints only happen on the 2nd call for some reason. The first time through it seems to work just fine since the JSONWriter that I get via theConverter.getWriter() when the breakpoint DOES work has the JSON of the object correctly marshalled. It's the 2nd call that is blowing up since the object has ALREADY been marshalled and the JSONWriter is no longer in the "init" state. There's nothing obviously available to tell the difference between the two calls, but why it the marshaller being called twice?
As requested, here's the controller. It's the show action that's being triggered:
class PrimaryController extends RestfulController implements AlwaysRenderJsonException {
def springSecurityService
def familyService
static responseFormats = ['json']
PrimaryController() {
/*
* Tell the base class the name of the resource under management.
*/
super(Primary)
}
#Override
protected Primary createResource() {
//def instance = super.createResource()
//TODO: Should be able to run the above line but there is an issue GRAILS-10411 that prevents it.
// Code from parent is below, as soon as the jira is fixed, remove the following lines:
Primary instance = resource.newInstance()
bindData instance, this.getObjectToBind()
//Code from super ends here
def family = familyService.safeGetFamily(params.long('familyId'))
familyService.addAdultToFamily(instance, family) // Add the primary member to the family.
return instance
}
/**
* Deletes a resource for the given id
* #param id The id
*/
#Override
def delete() {
if(handleReadOnly()) {
return
}
Child instance = queryForResource(params.id)
if (instance == null) {
notFound()
return
}
/*
* Because of the multiple belongsTo relationships of events, you have to get rid of all
* the events and make the profiles consistent BEFORE deleting the person instance.
*/
instance.removePerson()
request.withFormat {
'*'{ render status: NO_CONTENT } // NO CONTENT STATUS CODE
}
}
#Override
protected List<Primary> listAllResources(Map params) {
if (params.familyId == null)
{
throw new ESPException("params.familyId may not be null")
}
def user = springSecurityService.loadCurrentUser()
return \
AdultPlanning.where {
family.id == params.familyId \
&& family.user == user \
&& typeOfPerson == PeopleTypeEnum.PRIMARY
}.list()
}
#Override
protected Primary queryForResource(Serializable id) {
def inst = familyService.safeGetAdult(Long.parseLong(id), params.long('familyId'))
/*
* It was safe to access the requested id, but the requested id may NOT be a primary
* so we need to check.
*/
return (inst instanceof Primary ? inst : null)
}
/**
* Show the primary for the specified family.
*
* #return
*/
#Override
def show() {
Primary primary = familyService.safeGetFamily(params.long('familyId'))?.primary
respond primary
}
}
And the Integration test that triggers it:
void "We should be able to show a primary."() {
given:
family.addToAdults(new Primary(firstName: "Barney"))
family.save()
family.adults.each { it.save() }
when:
controller.response.reset()
resetParameters(controller.params, [familyId: family.id])
controller.request.method = 'GET'
controller.show()
then:
1 * mSpringSecurityService.loadCurrentUser() >> user
controller.response.json
controller.response.json.firstName == "Barney"
}
Well, this is embarrassing.
I use IntelliJ as my Java/Groovy IDE. I had a work related thing to do this morning and quit IntelliJ. When I restarted IntelliJ, the problem described above that had been completely reproducible was no longer happening and the appropriate JSON was being produced under all circumstances.
So it appears that the IntelliJ state somehow got corrupted and the restart cleared it out.
Problem solved.
I guess.
Thanks for the help/suggestions.
As OP mentioned, this error can be triggered because of IntelliJ :
org.codehaus.groovy.grails.web.json.JSONException: Misplaced object: expected mode of INIT, OBJECT or ARRAY but was DONE
Indeed, when debugging the marshaller (for example), IntelliJ displays the "toString()" of the variable, which causes the change of the mode from INIT to DONE.
You may want to remove your breakpoints when facing this issue ;)
The only reason for this can be that where you have started writer.object() for some nested object or array response but missed to write writer.endObject() or you have wrote it two times.
So double check your custom marshaller for all write object.
Reference: https://github.com/grails/grails-core/blob/65b42b66821b32d4efb3a229da99691a00575d60/grails-web-common/src/main/groovy/org/grails/web/json/JSONWriter.java#L258
Hope This helps!
Thanks,
SA

How to know exception occurred within grails transaction?

I have a service method which does some operation inside a transaction.
public User method1() {
// some code...
Vehicle.withTransaction { status ->
// some collection loop
// some other delete
vehicle.delete(failOnError:true)
}
if (checkSomething outside transaction) {
return throw some user defined exception
}
return user
}
If there is a runtime exception we dont have to catch that exception and the transaction will be rolled back automatically. But how to determine that transaction rolled back due to some exception and I want to throw some user friendly error message. delete() call also wont return anything.
If I add try/catch block inside the transaction by catching the Exception (super class) it is not getting into that exception block. But i was expecting it to go into that block and throw user friendly exception.
EDIT 1: Is it a good idea to add try/catch arround withTransaction
Any idea how to solver this?? Thanks in advance.
If I understand you question correctly, you want to know how to catch an exception, determine what the exception is, and return a message to the user. There are a few ways to do this. I will show you how I do it.
Before I get to the code there are a few things I might suggest. First, you don't need to explicitly declare the transaction in a service (I'm using v2.2.5). Services are transactional by default (not a big deal).
Second, the transaction will automatically roll back if any exception occurs while executing the service method.
Third, I would recommend removing failOnError:true from save() (I don't think it works on delete()... I may be wrong?). I find it is easier to run validate() or save() in the service then return the model instance to the controller where the objects errors can be used in a flash message.
The following is a sample of how I like to handle exceptions and saves using a service method and try/catch in the controller:
class FooService {
def saveFoo(Foo fooInstance) {
return fooInstance.save()
}
def anotherSaveFoo(Foo fooInstance) {
if(fooInstance.validate()){
fooInstance.save()
}else{
do something else or
throw new CustomException()
}
return fooInstance
}
}
class FooController {
def save = {
def newFoo = new Foo(params)
try{
returnedFoo = fooService.saveFoo(newFoo)
}catch(CustomException | Exception e){
flash.warning = [message(code: 'foo.validation.error.message',
args: [org.apache.commons.lang.exception.ExceptionUtils.getRootCauseMessage(e)],
default: "The foo changes did not pass validation.<br/>{0}")]
redirect('to where ever you need to go')
return
}
if(returnedFoo.hasErrors()){
def fooErrors = returnedFoo.errors.getAllErrors()
flash.warning = [message(code: 'foo.validation.error.message',
args: [fooErrors],
default: "The foo changes did not pass validation.<br/>${fooErrors}")]
redirect('to where ever you need to go')
return
}else {
flash.success = [message(code: 'foo.saved.successfully.message',
default: "The foo was saved successfully")]
redirect('to where ever you need to go')
}
}
}
Hope this helps, or gets some other input from more experienced Grails developers.
Here are a few other ways I've found to get exception info to pass along to your user:
request.exception.cause
request.exception.cause.message
response.status
A few links to other relevant questions that may help:
Exception handling in Grails controllers
Exception handling in Grails controllers with ExceptionMapper in Grails 2.2.4 best practice
https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ExceptionUtils.html

Exceptions, return values, and contextual information

I know that this type of question has been asked over and over again, however, I have yet to find a definitive answer for the problem I am looking into.
From all the content on exception handling that I have read it appears that the general concensus is that exceptions should only be used for exceptional circumstances. I've also read in many places that one should use, where possible, return values to indicate problems or failures (such as login failure, validation failure of some sort). My problem is, when using these return values, how does one communicate the contextual information of the problem? With exceptions, one can add the contextual information to the exception and allow that to bubble up. Let me try and use a code example to explain:
Let's say we have a basic abstract class (I've left out some of the details) which represents some kind of format definition for a String. This class essentially dictates how the format of a given string should be.
public abstract class ADataEntryDefinition
{
public boolean isValid(String data);
}
let's say I extend this to perform some security validation on the string:
public class SecureDataEntryDefinition extends ADataEntryDefinition
{
public boolean isValid(String data)
{
//do some security checks on the format of the data
}
}
The validate method will take in a String and return true if the string matches the data definition defined by the class.
Moving along, let's say I have a class which manages several of these data definitions, and this class' responsibility is to validate each entry in a comma separated String against one of the data definitions it maintains.
public class DataSetDefinitions
{
private List<ADataEntryDefinition> dataDefinitions = ...
public boolean isValid(String dataValues)
{
//obtain each string in dataValues delimited by a ',' into String[]
//called dataEntryValues
int i=0;
for (ADataEntryDefinition dataEntry : dataDefinitions)
{
if (!dataEntry.isValid(dataEntryValues[i++])
{
return false;
}
}
return true;
}
}
Now, to me these methods seem way to general to throw exceptions in the event of invalid data (for one, invalid data may be expected in some cases). In this case, I like the approach of returning true/false to indicate validation failure and subsequently allowing the caller to judge how serious it is. So the caller does the following:
boolean success = false;
success = dataSetDefinitions.isValid(someString);
Suppose a specific caller like the above deems the failed validation to be critical, and hence, must subsequently throw an exception to prevent processing from continuing; where should it obtain the contextual information it needs to convey the problem... how should it know that 2 layers (calls) down the validation actually failed due to security problems in the SecureDataEntryDefinition class (or any other subclass for that matter).
I guess I could add a method like so:
public class DataSetDefinitions
{
private List<ADataEntryDefinition> dataDefinitions = ...
public boolean isValid(String dataValues)
{
....
}
public String getValidationErrorMsg() {...}
}
which would return the error message of the last failed validation. Then, the following could be done by the caller upon failed validation:
success = dataSetDefinitions.isValid(someString);
if (!success)
throw new SomeException(dataSetDefinitions.getValidationErrorMsg());
But to me this just seems like having the class (DataSetDefinitions in this case) know or maintain state about the previous validation which it shouldn't. Taking into account that this class may perform validation of several different, independent strings, it seems wrong having it maintain state about the validation of any given one of them.
I guess this question is essentially asking how one designs methods to be general - not taking the law into their own hands by throwing exceptions unnecessarily, but allowing callers to decide on the severity - but still allowing the callers to obtain detailed contextual information in the event that the caller needs to communicate the problem. Is there a better way of doing the above?
Apologies if this was very long-winded :/ Any responses will be appreciated.
Ciao.
Don't return a bool. Return a class that encapsulates the success/failure state, plus the associated information. That way, you can do something like:
DataEntryStatus status = isValid(...);
if (!status.isValid()) {
throw status.generateStatusException();
}
and the status object itself generates the appropriate exception, thus maintaining encapsulation.
You could return a user defined class instead of a simple bool in order to provide more contextual information.
It would be something similar to the strategy used with events. We have a EventArgs class from which other classes derive in order to provide more contextual information for a given type of event.
The way i solve it most of the time is defining several class constants and return these. Then in the business logic of my controllers i would just check against these values statically.
<?php
class Test
{
const SUCCESS = 1000;
const EMAIL_FAIL = 2001;
const SAVE_FAIL = 2002;
...
public function save($value)
{
if (!$this->writetodb($value)
return self::SAVE_FAIL;
elseif(!$this->sendMailToAdmin())
return self::EMAIL_FAIL;
else
return self::SUCCESS;
}
}
$test = new Test();
$result = $test->save('my value');
switch ($result) {
case Test::SUCCESS:
echo 'Yay!';
break;
case Test::SAVE_FAIL:
echo 'Error saving!';
break;
case Test::EMAIL_FAIL:
echo 'Error sending email!';
break;
}