Thanks for the suggestion, Jamie. Your idea is an interesting one because it means using the Pre Advices as a sort of firewall, which I believe is how cbSecurity works.
If I used preHandler() as you suggest, I would need to give more logic to the preHandler() to make sure it is smart enough to know when rc.id is required, and when it is not.
For example, let’s say I had a typical handler like this:
/**
function show( event, rc, prc ) {
param name=“rc.id” default=“0”;
//… show the post
}
/**
function delete( event, rc, prc ) {
param name=“rc.id” default=“0”;
//… delete the post
}
/**
function list( event, rc, prc ) {
//… list all posts
}
If I added a preHandler() method to look for missing ID’s that preHandler would need to know whether the action was a “show”, “delete”, or “list” because list() doesn’t need rc.id.
In other words, it would need to look something like this:
/**
function preHandler( event, rc, prc ) {
if (
rc.keyExists( “id” ) && // is there an id in the RC scope?
!postService.doesExistById( rc.id ) // does the record not exist?
{
announceInterception( “onInvalidEvent**” );**
}
}
– interceptor:
/**
function onInvalidEvent ( event, interceptData ) {
event.overrideEvent( “error.onMissingPage” );
}
The above should work, but it feels like a code smell to require the PreHandler to know whether rc.id is needed or not. I’ve always looked at preHandler() as something that should apply to all actions in a given handler. Once we start making exceptions to the rules for a particular action, it could cause preHandler() to get complicated rather quickly. That’s just my opinion though as your suggestion of solving the problem seems to work.
Another way I am looking at solving the issue is to not use interceptors at all. Instead, I’m using onError() functionality which does let you hijack the current event and override it with something else. It would be great if interceptors would let you do the same thing, but I think they behave differently at their core.
Here’s an example of how I am accomplishing what I want with the onError() method:
/**
function show( event, rc, prc ) {
param name=“rc.id” default=“0”;
prc.post = getOrFail( rc.id ); // return the entity or fail to a 404 page.
//… show the post
}
/**
- Get Or Fail
- Gets an entity or redirects to the 404 missing template page
*/
private function getOrFail( required id ) {
var entity = postService.getById( arguments.id );
if ( !entity.isLoaded() ) {
// throw an error which will be caught by onError()
throw( “entity not found”, “EntityNotFound” );
}
return entity;
}
/**
- OnError
-
I exist in a base handler!
*/
function onError( event, rc, prc, faultaction, exception ) {
// log exception
log.error( “The action: #arguments.faultaction# failed when requesting resource: #arguments.event.getCurrentRoutedURL()#” );
switch ( exception.type ) {
// hijack the current event and run a friendly 404 event.
case “EntityNotFound”:
runEvent(
event = “error.onMissingPage”
);
break;
// if this is an actual exception error, blow up as normal.
default:
throw( exception );
break;
}
}