I have an interesting problem with me (at least it is a problem from my current point of view).
I have a RESTful web service that is exposing an interface. In our environment, we use annotation to decorate the request handlers, e.g. -
@RequiredTokenType("Binary")
public String getRecordInfo(HttpServletRequest request) {
String recordInfo = null;
final String methodName = "getRecordInfo()";
_log.debug("{}: received request", methodName);
// validate the request information
ValidationUtils.validateAcceptHeader(request, MimeConstants.getContentType());
. . .
. . .
return recordInfo;
}
We need to have a CXF interceptor/aspect (spring AOP) to execute before the handler (like the above), and check the HttpServletRequest for token type. If the token type (or any other attribute that is decorating the handler) is not of type specified in the annotation, stop the execution and return HTTP status 400 (bad request). There are about 20 request handlers like the above.
The problem I am facing here is that after writing a spring AOP based around aspect, (like below) I am able to catch the request before getRecordInfo() executes, but when I try to return 400 (or) throw an exception, the HTTP client still sees 200 -
public void validateRequest(ProceedingJoinPoint joinPoint,
HttpServletRequest httpRequest,
RequiredTokenType tokenType) throws Throwable {
final String methodName = "validateRequest()";
_logger.info("{}: Entered, Thread Id: {}", methodName, "" + Thread.currentThread().getId());
// Extract the *REQUIRED* headers from the request ...
final String tokenData = httpRequest.getHeader(HEADER_TOKEN_DATA);
if (tokenData == null || tokenData.trim().length() < MIN_POSSIBLE_TOKEN_SIZE) {
// Error condition .... return (400 Bad Request)
_logger.info("{}: Invalid token. The HTTP request is rejected in lack of a valid token.");
throw new MissingTokenException(HttpStatus.BAD_REQUEST,
ErrorCode.BAD_REQUEST,
"Token is missing from the request.");
}
ValidityToken extractedTokenFromRequest = ValidityToken.initializeFromBase64(tokenData);
// Get the type of the token this request must include ...
String decoratedTokenType = tokenType.value();
_logger.debug("{}: Token Type Required: ", methodName, decoratedTokenType);
if (! extractedTokenFromRequest.getTypeName().equals(decoratedTokenType)) {
// Error condition .... return (400).
_logger.info("{}: {}",
methodName,
"The token in the request mismatches the type specified in RequiredTokenType handler. 400 Bad Request.");
throw new TokenTypeMismatchException(HttpStatus.BAD_REQUEST,
ErrorCode.BAD_REQUEST,
"Token type doesn't match.");
}
// More validations on extractedTokenFromRequest
. . .
. . .
// Continue with the actual business logic if correct token is included ...
joinPoint.proceed();
}
I have checked the log file and I can see the following log entries that confirm that both the request handler and the aspect are being called -
getRecordInfo(): received request
. . .
. . .
validateRequest(): Entered, Thread Id: 792
. . .
. . .
validateRequest(): Invalid token. The HTTP request is rejected in lack of a valid token.
Despite the message, still the client see a 200 and server log shows evidence of other CXF based interceptors executing.
Here is the Spring context XML that is defining the pointcut -
<bean id="vGateKeeper" class="com....core.RequestValidator" />
<aop:config>
<aop:aspect id="methodInvocation" ref="methodInvocationProfiler">
<aop:around method="profileMethodInvocation"
pointcut="execution(* org.springframework.orm.jpa.JpaTransactionManager.commit(..))"/>
<aop:around method="profileMethodInvocation"
pointcut="execution(* org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(..))"/>
</aop:aspect>
<aop:aspect id="gateKeeper" ref="vGateKeeper">
<aop:pointcut expression="execution(* getRecordInfo(..)) and args(httpRequest) and @annotation(modPerms)" id="my"/>
<aop:around pointcut-ref="my" method="validateRequest"/>
</aop:aspect>
</aop:config>
How can Spring AOP aspect can be used to return HTTP 400 in this case, cancelling execution of any other interceptor ?
I was also looking at writing an Apache CXF interceptor to catch the call and return 400 before it reaches the request handler, but then I am not sure, How using an interceptor I can can know which request handler was suppose to execute and what annotation is decorating the request handler. Does CXF interceptor offer any way to know, which request handler will eventually execute ?
I was looking here, (https://cxf.apache.org/docs/interceptors.html) but didn't find anyway.
Any help is appreciated.
Regards,
(*Vipul)() ;