I have an inteface Foo with an implementation Bar. The interface Foo has a method "doMe()" with a method annotation #Secured. This is the only method that is secured.
Now I wrote the following code to go through classes and look for methods with #Secured on them. (This method is not finished yet, I'm trying to get the first unit tests passed.)
/**
* Determine if a method is secured
* #param method the method being checked
* #return true if the method is secured, false otherwise
*/
protected static boolean isSecured(Method method) {
boolean secured = false;
Annotation[] annotations = method.getAnnotations();
for(Annotation annotation:annotations){
if(Secured.class.equals(annotation.getClass())){
secured = true;
break;
}
}
if(secured){
return true;
}
return secured;
}
Methods besides doMe() return 0 members on getAnnotations() for both Foo and Bar. The problem is that doMe() also returns 0 members for both Foo and Bar.
I'm looking for someone that knows more about reflection than me, since that shouldn't be hard to find. :)
Thanks.
Have you ensured that the annotation is visible at runtime? You may need to annotate your annotation with #Retention(RetentionPolicy.RUNTIME). The default, CLASS, won't return the annotation in reflective methods.
See also: RetentionPolicy docs
Try using getAnnotation instead of getAnnotations, because getAnotations internally uses getDeclaredAnnotations.
More details at Method (Java Platform SE 6)
protected static boolean isSecured(Method method) {
Secured secured = method.getAnnotation(Secured.class);
return secured == null ? false : true;
}
Related
I have an Aspect:
#Aspect
#Component
public class BusinessAspect {
#Around("#annotation(Business)")
public Object getCorrespondingBusiness(ProceedingJoinPoint joinPoint, Business business) throws Throwable {
//BEFORE METHOD EXECUTION
Object data = joinPoint.getArgs()[0]; // gets first argument
int businessNumber = business.value(); // gets # in annotation
BusinessObj correspondingBusiness = getBusiness614(); // will make modular later
// This is where ACTUAL METHOD will get invoke
Object result = joinPoint.proceed( new Object[] { data, correspondingBusiness} );
// AFTER METHOD EXECUTION
System.out.println(result);
return result;
}
private BusinessObj getBusiness614() {
return valid business..
}
}
And here is the method that needs to access that correspondingBusiness object:
#Business(614)
public BusinessRule rangeFromGreaterThanRangeThrough(BusinessProfile businessProfile) {
return BusinessRule.businessRuleBuilder()
.withParameter("from", ...)
.withParameter("through", ...)
.withCrudOperationAction(...)
.withCrudOperationAction(...)
.setBusiness(correspondingBusiness) // not recognizing the parameter. compilation error?
).build();
}
Essentially, my issue is the correspondingBusiness object is not being recognized. I understand that you can manipulate and change parameters, but can you pass in extra parameters, or can you only change them? If I can only change them, how would I make it so I can call this method without having to pass in a second parameter? Creating an overload for each of these seems like a lot of unnecessary code.
Thank you!
Edit:
Here is the annotation interface for clarity:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface Business {
int value();
}
The solution can be found in Spring documentation:
The parameter binding in advice invocations relies on matching names used in pointcut expressions to declared parameter names in (advice and pointcut) method signatures.
Define your Around advice as shown below and business parameter will be passed to the advice method.
#Around("execution(* *(..)) && #annotation(business)")
I would like to intercept method after returning a value.
The method is the default method on the interface and I would like to have returning value of the default intf implementation and also overriding implementation in the concrete class.
this is my aspect:
#Aspect
#Configuration
public class ResAspect {
#AfterReturning(pointcut = "within(org.my.app.Strategy+) && execution(* shouldEnter(..))", returning = "res")
public void shouldOperate(JoinPoint jp, boolean res) {
System.out.println();
}
}
this is the default method:
default boolean shouldEnter(int i, Rec r) {
return !evaluate(i, r);
}
as you can guess it's not working. So can I achieve what I want with Spring AOP?
Can I access the implementing class instance and it's properties within the aspect?
EDIT: the interface I want to intercept is located in another module
You can access the instance on which the method is invoked, aka the target, inside the advice as follows:
YourInterface interfaceReference = (YourInterface) joinPoint.getTarget();
You can then access whatever you want using the retrieved object.
This code can check whether a class is deprecated or not
#Deprecated
public classRetentionPolicyExample{
public static void main(String[] args){
boolean isDeprecated=false;
if(RetentionPolicyExample.class.getAnnotations().length>0){
isDeprecated= RetentionPolicyExample.class
.getAnnotations()[0].toString()
.contains("Deprecated");
}
System.out.println("is deprecated:"+ isDeprecated);
}
}
But, how can be checked if any variable is annotated as deprecated?
#Deprecated
Stringvariable;
import java.util.stream.Stream;
Field[] fields = RetentionPolicyExample.class // Get the class
.getDeclaredFields(); // Get its fields
boolean isAnyDeprecated = Stream.of(fields) // Iterate over fields
// If it is deprecated, this gets the annotation.
// Else, null
.map(field -> field.getAnnotation(Deprecated.class))
.anyMatch(x -> x != null); // Is there a deprecated annotation somewhere?
You are checking the Class annotations. The reflection API's also give you access to Field and Method annotations.
See
Class.getFields() and Class.getDeclaredFields()
Class.getMethods() and Class.getDeclaredMethods()
Class.getSuperClass()
A couple of problems with your implementation
You are only checking getAnnotations[0] when there might be more than one annotation
You are testing toString().contains("Deprecated") when you should check .equals(Deprecated.class)
You could use .getAnnotation(Deprecated.class)
Here's my use case:
I need to do some generic operation before and after each method of a given class, which is based on the parameter(s) of the method. For example:
void process(Processable object) {
LOGGER.log(object.getDesc());
object.process();
}
class BaseClass {
String method1(Object o){ //o may or may not be Processable(add process logic only in former case)
if(o intstanceof Prcessable){
LOGGER.log(object.getDesc());
object.process();
}
//method logic
}
}
My BaseClass has a lot of methods and I know for a fact that the same functionality will be added to several similar classes as well in future.
Is something like the following possible?
#MarkForProcessing
String method1(#Process Object o){
//method logic
}
PS: Can AspectJ/guice be used? Also want to know how to implement this from scratch for understanding.
Edit: Forgot to mention, what I have tried.(Not complete or working)
public #interface MarkForProcessing {
String getMetadata();
}
final public class Handler {
public boolean process(Object instance) throws Exception {
Class<?> clazz = instance.getClass();
for(Method m : clazz.getDeclaredMethods()) {
if(m.isAnnotationPresent(LocalSource.class)) {
LocalSource annotation = m.getAnnotation(MarkForProcessing.class);
Class<?> returnType = m.getReturnType();
Class<?>[] inputParamTypes = m.getParameterTypes();
Class<?> inputType = null;
// We are interested in just 1st param
if(inputParamTypes.length != 0) {
inputType = inputParamTypes[0];
}
// But all i have access to here is just the types, I need access to the method param.
}
return false;
}
return false;
}
Yes, it can be done. Yes, you can use AspectJ. No, Guice would only be tangentially related to this problem.
The traditional aspect approach creates a proxy which is basically a subclass of the class you've given it (e.g. a subclass of BaseClass) but that subclass is created at runtime. The subclass delegates to the wrapped class for all methods. However, when creating this new subclass you can specify some extra behavior to add before or after (or both) the call to the wrapped class. In other words, if you have:
public class Foo() {
public void doFoo() {...}
}
Then the dynamic proxy would be a subclass of Foo created at runtime that looks something like:
public class Foo$Proxy {
public void doFoo() {
//Custom pre-invocation code
super.doFoo();
//Custom post-invocation code
}
}
Actually creating a dynamic proxy is a magical process known as bytecode manipulation. If you want to to do that yourself you can use tools such as cglib or asm. Or you can use JDK dynamic proxies. The main downside to JDK proxies are that they can only wrap interfaces.
AOP tools like AspectJ provide an abstraction on top of the raw bytecode manipulation for doing the above (you can do a lot with bytecode manipulation, adding behavior before and after methods is all aspects allow). Typically they define 'Aspect's which are classes that have special methods called 'advice' along with a 'pointcut' which defines when to apply that advice. In other words you may have:
#Aspect
public class FooAspect {
#Around("#annotation(MarkForProcessing)")
public void doProcessing(final ProceedingJoinPoint joinPoint) throws Throwable
{
//Do some before processing
joinPoint.proceed(); //Invokes the underlying method
//Do some after processing
}
}
The aspect is FooAspect, the advice is doProcessing, and the pointcut is "#annotation(MarkForProcessing)" which matches all methods that are annotated with #MarkForProcessing. It's worth pointing out that the ProceedingJoinPoint will have a reference to the actual parameter values (unlike the java.lang.reflect.Method)
The last step is actually applying your aspect to an instance of your class. Typically this is either done with a container (e.g. Guice or Spring). Most containers have some way of knowing about a collection of aspects and when to apply them to classes constructed by that container. You can also do this programmatically. For example, with AspectJ you would do:
AspectJProxyFactory factory = new AspectJProxyFactory(baseClassInstance);
factory.addAspect(FooAspect.class);
BaseClass proxy = factory.getProxy();
Last, but not least, there are AOP implementations which use compile-time "weaving" which is a second compilation step run on the class files that applies the aspects. In other words, you don't have to do the above or use a container, the aspect will be injected into the class file itself.
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
...
}