Is it possible to parametrize an Aspect? Right now I have an #Integration Aspect and my pointcuts are like:
#AfterReturning(pointcut = "#annotation(Integration)",returning = "result")
So, wherever it finds #Integration, it will call this method. Can I implement something like this:
#Integration("new") or #Integration("deleted"),
to avoid to create new annotation for every case?
Also, if this is possible, how to access this provided value ("new" or "deleted").
Thanks in advance :)
Yes it's possible
Here is description of how to add a value to your annotation
Here is the article full of examples of annotation processing with AspectJ; e.g. Listing 8 shows how to access your annotation value inside of aspect
Related
I have created a custom annotation
annotation class UserControl(
val userIdentifier: String
)
I wan to apply this annotation on query parameters, and path variables in different controllers.
fun userWithMobile(
#UserControl("PhoneNumber")
#RequestParam mobile: String
): RegisteredUser {
return userManager.getUserWithPhoneNumber(mobile))
}
How can i check if the query parameters have the UserControl annotation or not, and do some processing on that. Is there standard way to write a global handler , or a processor for that?
Would appreciate any help
AspectJ can directly match parameter annotations, but not bind them to advice method values like class or method annotations. So if you only want to match them, a simple pointcut is enough. If you want to access the annotations and maybe their parameter values, you need a little bit of reflection magic. I have answered related questions many times already, which is why I am going to close this one as a duplicate. But first, here are the resources you want to read. They all related to your question, showing examples of how to handle different specific situations:
https://stackoverflow.com/a/38162279/1082681
https://stackoverflow.com/a/10595712/1082681
https://stackoverflow.com/a/50540489/1082681
https://stackoverflow.com/a/49872132/1082681
https://stackoverflow.com/a/61284425/1082681
https://stackoverflow.com/a/16624766/1082681
Basically, the pointcut you want the following or some variation of it:
execution(* *(.., #my.package.UserControl (*), ..))
The naive, less efficient approach without matching the parameter in the pointcut, using only relfection:
https://stackoverflow.com/a/27784714/1082681
https://stackoverflow.com/a/42561014/1082681
I am wondering if there is a pattern that forces the user of my component to set a property after it is autowired. For example i have this:
#SpringComponent
#PrototypeScope
public class MyAutowiredClass {
private String myVariabeThatTheUserShouldSet;
public MyAutowiredClass(someOtherStuff ...(not my StringVariable)){
}
}
In this example how to i force myVariabeThatTheUserShouldSet to be set from the user of this component?
Well it's a bit complicated. If it wasn't in spring context you could just add that variable to the constructor and make it "required" like that. So to achieve that in a Spring context I would advise the following:
If possible pass that value as part of the dependency injection instead of trying to work around it. I understand it is something dynamic but still usually it would have business meaning and there is a way to do it. For example if you want the current user email you can add some Service that retrieves that value and pass that service to your component and extract that value from there. Or if you want some company configuration you can add a Service that gives you that value etc. It is the "Spring" way and I would lean towards that.
A simpler solution would be to add that required field to the methods signature of the methods that actually need it. It will overload the signatures by one field but it would force the users to pass a value. If you need that field for a couple of methods and not for the correct work of the component then it would be the easiest to implement/understand solution.
Add a setter for that value and throw exception if it is not set. That would be the worse though because will require try/catches if the exception is checked and if it is not people will forget to set the field so I would avoid that solution.
I fear title is bad, but could not formulate it better. So, I have this code:
#javax.interceptor.Interceptors({EjbSecurityServerInterceptor.class,PermissionInterceptor.class})
Is there a way to create annotation like #SecuredAsHell, that will be an equivalent to aforementioned annotation? Smth like macros, I suppose.
Thanks
No. Sorry, but the fact is that whatever reflection that is used to locate annotations of type javax.interceptor.Interceptors will only locate annotations of that type. There is not way to indicate that another annotation is somehow equivalent.
I understand, in Java we have parameters validation solution. I believe JAX-RS has various annotations both for validation and data extraction. My question is, if I want to implement my own parameter validation class for a standalone Java application, how would I make sure that a method is executed only when its parameters have been validated? I am using Reflection to spot parameters with #LowerCaseCheck and then performing validation on it, but not sure where to place this validation code.
public void print(#LowerCaseCheck String lowerCaseString) {
....
}
You need to change the byte code of the method to perform the check (or call a method which performs the check) The simplest way to do this might be to use an Aspect orientated library like AspectJ.
Look at gag for an example of a library that does what you're looking for. It uses the asm bytecode manipulation library to insert validation checks at the start of annotated methods.
Cant'you use Bean Validation (JSR-303) to solve your problem ?
the #Pattern(regexp) annotation seems to do just what you need.
public void print(#Pattern(regexp = "^[a-z]*$") String lowerCaseString) {
....
}
I'm using Oval to do validations, so we have code that looks like this:
#NotNull(errorCode = "NumberInvalid")
#NotNegative(errorCode = "NumberInvalid")
#Range(errorCode = "NumberInvalid", min=1, max=10)
protected Integer dollarAmount;
I want to be able to update the range dynamically if needed, say if we have a config file that changes every month or so, I want to be able to reflect those changes in the validation.
Is there a way I can do this with reflection so that I don't have to subclass every annotation in Oval?
As far as I'm aware this is not possible. Assuming your annotation retention is set to RUNTIME (which it would have to be for the validation to work) then what you will effectively have is a proxy class that implements the annotation interface, you won't be able to amend the values through reflection.
Though annotations looks cleaner with static codes :) but ...there is a way.. Did you tried using reflection ? can you post the approach . You can have a look at this
The purpose of reflection is to access class members (including setting fields), but it does not cover adding new members or modifying existing declarations. What you want is more similar to bytecode editing or code refactoring.