Using EJB interceptors after a method call - ejb-3.0

I know one can use interceptors before a method call by using the #AroundInvoke annotation.
What I would like to do is execute certain code after the method call, so that I can for example create a log entry before and after a method execution.
Is this possible with EJB3, or do I need to use AOP?

#AroundInvoke interceptor is passed InvocationContext, and proceed() must be called to advance the method. Thus:
#AroundInvoke
public Object log(InvocationContext ic) throws Exception {
logEntry();
try {
return ic.proceed();
} finally {
logExit();
}
}
Depending on your needs, you could also log the return value or exceptions, filter the methods being logged, etc.

Related

Spring AOP: execute code before validation in a controller

I have the following code:
class OrderController {
#AllowedScopes({ORDER_CREATE})
#PostMapping("/create")
public CreateOrderResponse createOrder(#Valid #RequestBody OrderRequest request){
}
}
#Aspect
#Component
public class AllowedScopeAspect {
#Pointcut("#annotation(allowedScopes)")
private void callAtAllowedScopes(AllowedScopes allowedScopes) {
// just a pointcut signature
}
#Before(value = "callAtAllowedScopes(allowedScopes)", argNames = "jp,allowedScopes")
public void validateScope(JoinPoint jp, AllowedScopes allowedScopes) {
...
}
}
Aspect code validates if user have required scope.
The problem is Aspect code is executed after request body validation. If validation is not OKAY, it is returning validation error. if passes, returning 403 error.
How can I execute aspect code before data binding and validation or control handler stage?
You seem to misunderstand how the JVM works. Method parameters always need to be evaluated before calling the method, otherwise the JVM cannot put the parameters on the stack for the method to get access to them. Therefore, also validation takes place before calling the method.
Spring AOP can only intercept method execution, i.e. an aspect is necessarily triggered after validation. The whole point of parameter validation is to not execute the corresponding method, if any parameter is invalid. But if the method is not executed in the first place, there is nothing to intercept for the aspect. 😉

How to write a pointcut to get an operation on a class method?

I have a class named PersonDAOImpl, where I use Hibernate to persist data on my data base.
In order to audit the class, I created another class using the #Aspect annotation, where I declared some Pointcuts and Advices. Everytime I insert, update or delete a person, I'm able to store on a table proper information about the operation executed.
However now I have more DAO classes, and I don't want to create more Aspects classes or more Advices for every method on every DAO. Instead, I want to "capture" the operations of persist(), update() or delete() in a single pointcut.
For example I have this method on my DAO:
#Override
#Transactional
public void addPerson(Person p) {
Session session = this.sessionFactory.getCurrentSession();
session.persist(p);
session.flush();
logger.info("Person saved successfully, Person Details="+p);
}
And this is how I audit the insertions:
#Pointcut("execution(* com.dacasals.raspertwo.dao.PersonDAOImpl.addPerson(..))")
public void addNewPerson() {
}
#After("addNewPerson()")
public void aP() {
System.out.println("added a new person");
operation = "Insert";
date = Calendar.getInstance().getTime();
register(operation, date);
}
But I want something like #Pointcut("execution(*com.dacasals.raspertwo.dao.anydaoclass.anymethod.persist(..))")
I mean a pointcut for any method on any of my DAO classes where persist() is called. Same thing for update() and delete().
How can I achieve this? I've tried with 'within' and 'withincode' but nothing happens. Thanks in advance.
Instead of execution expression you might want to use the within expression something like this.
within(com.yourpackage..*)
For this you will have to make sure that all your DAO's are within this package. The above expression will match all the methods defined in classes inside package com.yourpackage and classes sub-packages.
Here is a short doc if you would like to configure it some other way,
Pointcut Expressions in Spring
I would use the 'AroundAdvice'.
Quote for documentation:
Around advice runs "around" a matched method execution. It has the opportunity to do work both before and after the method executes, and to determine when, how, and even if, the method actually gets to execute at all.
Around Advice Spring documentation
So, in your example, you would have a method:
#Around("com.dacasals.raspertwo.dao.*.persist(..)")
public Object doSomething(ProceedingJoinPoint pjp) throws Throwable {
}
This way every time someone on 'com.dacasals.raspertwo.dao' calls persist method, Spring Aspect will invoke doSomething method. Around advice works both before and after the method executes, so you should take care to don't do the same thing twice.
I would create a specific method for every operation (one for insert, another for update and delete) but you could use the same method using short-circuit operators. That way, your #Around annotation would be like:
#Around("com.dacasals.raspertwo.dao.*.persist(..) || com.dacasals.raspertwo.dao.*.update(..) || com.dacasals.raspertwo.dao.*.delete(..)")
public Object doSomething(ProceedingJoinPoint pjp) throws Throwable {
}

spring security - How can I modify the return object of #PostAuthorize in a custom SPEL method?

I wish to filter a collection returned by a service method. This filtering would involve calling another service method and hence I am not going for #PostFilter as it calls the SPEL expression inside the annotation for each element of the collection. Instead, I am using #PostAuthorize as follows :
#PostAuthorize("canAssignToUser(returnObject)")
List<UserInfo> getUsers(int userId);
In the canAssignToUser, I am trying to remove users from the return list passed to it. Apparently, this is a problem, and there is some restriction on modifying the returned list. How can I modify the returned list from a method using method-level annotations and without the SPEL expression being called for each element of the list.
The #PostAuthorize is used for evaluating a boolean value, so the interceptor does not pass the return value to the expression, (look here).
What's your method of removing the elements without checking every element? (like the #PostFilter does)
I think you don't have a choice, if you want to use Spring Security for the filtering
You can modify the returned object as you like. Even though the interceptor does not return the object you passed, it gets notified with the changes to the object. Eventually the returnedObject is modified. (Note: custom security method inside #PostAuthorize can only return boolean.)
public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {
public CustomMethodSecurityExpressionRoot(Authentication authentication) {
super(authentication);
}
public boolean canAssignToUser(Object returnObject) {
// do modifications to returnObject
return true;
}
getUsers() method returns the modified list after evaluating#PostAuthorize("canAssignToUser(returnObject)") .

Implementing #Before/#Post something with Spring AOP

I need to intercept all the methods of type writer.write(myObj) , and if and only if myObj contains a method annotated with #BeforeWrite, execute this method.
I am kind of confused because I can intercept a method call on the writer, but I don't know how to provide a pointcut that looks if there is a method annotated with #BeforeWriter, this looks similar to how probably a #PostLoad annotation is handled in JPA...
In your interceptor handling method you have the argument of type ProceedingJoinPoint, which has method getArgs(). You can check your argument (myObj) methods reflections and make your decision whether to proceed. Example (call is of type ProceedingJoinPoint):
boolean proceed = false;
for (Method method : call.getArgs()[0].getClass().getMethods()) {
if (method.isAnnotationPresent(BeforeWriter.class)) {
proceed = true;
break;
}
}

Need help creating a specific pointcut inside of a method

I started with an original question on
Need help creating a specific pointcut that utilizes a value from a method annotation
I decided I wanted to ask another question to change the approach I was taking.
I have a method (navigation), that has a call inside of that method to another method which I would like to have #Around advice.
#RequestMapping(method = RequestMethod.GET)
public String navigation(ModelMap model) {
...
// Call Auto Handling
logger.info("Call AutoHandling");
this.processAutoHandling(callSession, FunctionalArea.PRE_MAIN_MENU);
}
...
return forward(returnView);
}
Is this possible as I cannot seem to get this to work if the method is inside of the same class.
This work if it was not on the object itself:
#Around("execution(* *.processAutoHandling(..)) &&" +
"args(callSession, functionalArea) && " +
"args(functionalArea) && " +
"target(bean)"
)
public Object processAutoHandlingCall2(ProceedingJoinPoint jp,
CallSession callSession,
FunctionalArea functionalArea,
Object bean)
throws Throwable {
logger.debug("processAutoHandleCall");
return jp.proceed();
}
With this call in my controller:
autoHandlingComponent.processAutoHandling(callSession, FunctionalArea.PRE_MAIN_MENU);
instead of
this.processAutoHandling(callSession, FunctionalArea.PRE_MAIN_MENU);
It seems that you are using Spring's proxy-based AOP. If so, this is a known limitation. See Understanding AOP Proxies from Spring documentation for more details. You have two ways to solve this issue:
Use the AopContext.currentProxy() approach outlined in the documentation. I will discourage this approach, since your code will now be tied to Spring AOP quite explicitly.
Use AspectJ's byte-code weaving. Since there is no proxy involved with it, you won't have the issue with 'this' pointing to original object and proxy is transparently available only to external objects.

Resources