Below is my code snippet:
ServiceImpl.java
#Service
public class ServiceImpl implements Service {
private Response worker(Audit send) throws ArgumentException {
System.out.println("STEP_1");
worker(send.getRequest(), send.getId());
}
private Response worker(Request request, String id) throws ArgumentException {
System.out.println("STEP_2");
try {
//throwing some exception
} catch (Exception e) {
System.out.println("STEP_3");
}
}
}
Now, what I want is whenever NullPointerException is being thrown from method worker(Request request, String id) as shown above I want to perform some specific task. For that I have written an Aspect class which is following:
MyAspect.java
#Aspect
#Component
public class MyAspect{
#Pointcut("com.xyz.myapp.ServiceImpl.worker() && args(request,..)")
private void someOperation(Request request) {}
#Before("someOperation(request)")
public void process(Request request) {
System.out.println("SUCCESS");
}
#AfterThrowing("com.xyz.myapp.ServiceImpl.worker() && args(request,..)")
public void doRecoveryActions() {
System.out.println("EXCEPTION_SUCCESS");
}
}
Current Output:
STEP_1
STEP_2
STEP_3
Desired Output:
STEP_1
STEP_2
STEP_3
SUCCESS
EXCEPTION_SUCCESS
As you can see MyAspect.java is not getting triggered hence NOT printing values.
What can be the reason for this?
Note:
I tried making worker as public classes too but it didn't work.
Also tried changing the name of the methods to eliminate any overloading issue that too didn't work.
Tried various other pointcut expressions all in vain as of now.
In my application there are other aspect classes working absolutely fine.
You made a typical Spring AOP beginner's mistake: You assume that it works for private methods, but as the documentation clearly says, it does not. Spring AOP is based on dynamic proxies, and those only work for public methods when implementing interfaces via JDK proxies and additionally for protected and package-scoped methods when using CGLIB proxies.
You should make the worker() method public if you want to intercept it from an aspect.
P.S.: Full-fledged AspectJ also works for private methods, but to switch to another AOP framework would be overkill here.
Update: You also have other problems in your code:
The first worker method, even if you make it public, does not return anything. The last statement should be return worker(send.getRequest(), send.getId());, not just worker(send.getRequest(), send.getId());.
Your pointcut com.xyz.myapp.ServiceImpl.worker() will never match because it has an empty argument list, but your method has arguments. The args() does not help you here.
The syntax of your pointcut is also wrong because it does not specify a return type for the method, not even *. Furthermore, the method name itself is not enough, it should be enclosed in an actual pointcut type such as execution(). I.e. you want to write something like:
#Pointcut("execution(* com.xyz.myapp.ServiceImpl.worker(..)) && args(request, ..)")
private void someOperation(Request request) {}
To intercept a method that throws an exception you can use this code (works only if methods are public):
#AfterThrowing(pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",throwing="ex")
public void doRecoveryActions(NullPointerException ex) {
// ...
}
Source: Spring AOP
Related
I'm trying to implement my #secured annotation similar to Spring's, but generalized to any project and I'm having problems.
I looked at a lot of documentation but my internet is really restringed and need an answer. My idea is that the code to use it is like this:
public class a {
#secured (access> 3)
private void a() {}
}
The controller:
public class SecuredProvider {
private void check () {
if (accessLevesOfMethod> registerUser.getAccesLevel ()) {
// execute method
} else {
throw new exception ();
}
}
in the main
new A (). a ();
And if the logged user have an access level < 3 throws an exception, any other case they method is executed normally.
Thanks in advance.
Solved with AOP, using Dependency injection with google's GUICE an intercepting every method with #Secure
Pointcut declaration:
#Pointcut(value="com.someapp.someservice.someOperation() && args(t,req)",argNames="t,req")
private void logOperationArg(final String t,final String req)
{
}
Advice Declaration not compiling:
#Before(value="logOperationArg(t,req)")
public void logBeforeOperationAdvice(JoinPoint jp, final String t, final String req){
...
}
When compiling Aspect with Aspectj-maven-plugin (1.5 version), have error "can not build thisJoinPoint lazily for this advice since it has no suitable guard [Xlint:noGuardForLazyTjp]"
But the same advice compiles without JoinPoint argument.
Advice Declaration compiling:
#Before(value="logOperationArg(t,req)")
public void logBeforeOperationAdvice(final String t, final String req){
...
}
Spring AOP only supports method join points because it is based on dynamic proxies which creates proxied object if it is needed (for example if you are using ApplicationContext, it will be created after beans are loaded from BeanFactory)
Use execution() statement to match join points which are methods execution.
For example:
class LogAspect {
#Before("execution(* com.test.work.Working(..))")
public void beginBefore(JoinPoint join){
System.out.println("This will be displayed before Working() method will be executed");
}
And now how to declare your BO:
//.. declare interface
then:
class BoModel implements SomeBoInterface {
public void Working(){
System.out.println("It will works after aspect");
}
}
execution() statement is a PointCut expression to tell where your advice should be applied.
If you like to use #PointCut, you can do something like this:
class LogAspect {
//define a pointcut
#PointCut(
"execution(* com.test.work.SomeInferface.someInterfaceMethod(..))")
public void PointCutLoc() {
}
#Before("PointCutLoc()")
public void getBefore(){
System.out.println("This will be executed before someInterfaceMethod()");
}
}
Part2:
Also,the Error shows that you haven't put a guard on your advice. Technically guard makes your code faster, because you do not need construct thisJoinPoint everytime you execute it. So, if it does not make sense you can try to ignore it
canNotImplementLazyTjp = ignore
multipleAdviceStoppingLazyTjp=ignore
noGuardForLazyTjp=ignore
I'm a little new to AOP, and got confused about the problem I'm facing. I have the Annotation #AuthorizeUser which acts on methods, on Presentation Layer. I need to check if User is authorized to execute that method or not. Here is the code for AuthorizeUserAspect:
#Aspect
public class AuthorizeUserAspect {
#AuthoWired
private UserService service;
#Before(value = "#annotation(com.company.annotation.AuthorizeUser)")
public void isAuthorized(JoinPoint jp) {
// Check if the user has permission or not
// executing some Service Layer services and
// Persistence Layer, corresponding to that
service.checkUser();
// Is there a way I can make this method Conditional. something like:
if ( /* User has permission */ ) {
// do nothing, so the method will be executed after this
}
else {
// 1) Prevent the Method to be executed [and/or]
// 2) Pass some Parameters to the method for checking [and/or]
// 3) Execute another method on that class [e.g showAccessDenied()]
}
}
}
It's a little bit similar to this question Spring MVC + Before Advice check security. But it suggested to return some String (ie. "Not OK"). There are two types of UI in my application (Struts and Jersey), so there would be two type of return type (String and Response respectively). So I guess that might not be the best way to do it.
I would be very glad if you could show me a workaround for this.
Is this even a good approach or not?
First of all, have you looked at Spring Security? It is completely declarative and does not require you to write aspects yourself. It secures methods by throwing an exception if the user is not authenticated or doesn't have the required privilege.
Regarding your problem with two different return types:
First option: Create two different kinds of advices, specific to the return type of the method:
#Before("#annotation(com.company.annotation.AuthorizeUser) && execution(String *.*(..))")
public void isAuthorizedString(JoinPoint jp) {
...
}
#Before("#annotation(com.company.annotation.AuthorizeUser) && execution(Response *.*(..))")
public void isAuthorizedResponse(JoinPoint jp) {
...
}
Second option: Find out the return type of the advised method via reflection and return a different value based on that:
#Before("#annotation(com.company.annotation.AuthorizeUser")
public void isAuthorized(JoinPoint jp) {
Class<?> returnType = ((MethodSignature)jp.getStaticPart()
.getSignature()).getReturnType();
if(returnType == String.class)
...
else
...
}
I'm trying to imitate Spring's AspectJ #Async support but with a message bus.
The issue is I need to know if my Message Bus (RabbitMQ MessageListener) is calling the method or a normal (all others) caller where the method will return instantly.
My annotation is called #MQAsync instead of Springs #Async.
package com.snaphop.mqueue;
import org.apache.log4j.Logger;
import com.snaphop.mqueue.MQAsync;
public aspect MQAsyncAspect {
//pointcut asyncTypeMarkedMethod() : execution(#MQAsync void *(..));
pointcut asyncTypeMarkedMethod() : call(#MQAsync void *(..));
private static final Logger log = Logger.getLogger("MQAsync");
Object around() : asyncTypeMarkedMethod() {
if (listenerIsCaller) {
return proceed();
}
//Send the method parameters to the message bus.
//this logic isn't here for brevity.
return null;
}
}
The call pointcut will get me the caller context but that will not work as I will be calling the method with my message listener through reflection. The execution pointcut (commented out) will not tell me who is calling the method.
Is there a way to determine the caller class maybe through some sort of stack dump analysis?
Actually cheeken's answer is nice, but for AspectJ call() pointcuts you can get the calling class much more easily and without ugly reflection:
thisEnclosingJoinPointStaticPart.getSignature().getDeclaringType()
Please consider to accept this answer if you think it is better than the other one, otherwise just enjoy the power of AspectJ. ;-)
You can determine which class is invoking the current method with the following call. Note that you'll have to catch ClassNotFoundException (unless you're satisfied simply retrieving the name as a String).
Class.forName(Thread.currentThread().getStackTrace()[2].getClassName());
Why the third element? Because the stack is ordered like so when the stack trace method is invoked:
Thread#getStackTrace()
CurrentClass.currentMethod()
ParentClass.parentMethod()
This is an alternative that seems more light since is native and commonly used by the SecurityManager. To use it we need a utility class because the the method we need is protected.
public class CallStackUtils extends SecurityManager {
static CallStackUtils sm = new CallStackUtils();
public Class[] getCallersClassesStack0() {
return getClassContext();
}
static public Class[] getCallersClassesStack() {
return sm.getCallersClassesStack0();
}
}
I'd like to set up my beans to use both Hibernate Validator (for validation) and Google Guice (for DI and method interception).
Ideally, I'd like to have a setup where any method that "fails" validation will cause a method interceptor to be called:
public class Widget {
#NotNull
public Fizz getFizz() {
return fizz;
}
}
public class FailedWidgetInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
// This gets executed if Widget's getFizz() returns null...
}
}
But it looks like Hibernate Validator only allows you to determine pass/fail status by explicitly passing an object T to a ClassValidator<T>'s getInvalidValues() method.
So I need a place to make such a call! The only viable solution I can think of is to create my own annotation (which I've never done before!) which might look like this:
#NotNull
public #interface AutoValidatingNotNull {
// ...??
}
And then in Guice Module:
public class WidgetModule implements Module {
public void configure(Binder binder) {
binder.bindInterceptor(
any(),
annotatedWith(AutoValidatingNotNull.class),
new ValidatingWidgetInterceptor()
);
}
}
public class ValidatingWidgetInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
ClassValidator<Widget> widgetValidator = new ClassValidator<Widget>();
InvalidValue[] badVals = widgetValidator.getInvalidValues(widget);
if(badVals.length > 0)
handleFailedValidationAndThrowRuntimeExceptionOrSomething();
}
}
Finally, to change getFizz():
#AutoValidatingNotNull
public Fizz getFizz() {
return fizz;
}
For one, this only almost works: inside the interceptor's invoke method, how do I get my hands on the widget instance (the one we wish to validate)?. Is there a way to pass the widget instance via annotations?
Edit:
Doesn't look like I can pass Object into annotations (as parameters)...
Second, this is kind of nasty. Perhaps I'm overlooking something that Hibernate Validator offers that takes care of all this for me? Is there a better way to go? Thanks in advance!
It seems like you're still using the Hibernate Validator 3.x API around ClassValidator et al.
I recommend to upgrade to 4.2 where an API for method validation was introduced which exactly does what you describe.
An example for the required glue code to integrate that API with Google Guice can be found in this project which I created a while ago on GitHub.