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
Related
I have written a MapStruct mapper which has two methods with the #AfterMapping annotation. Depending on the context, I want only one of these methods to be executed before the end of the mapping.
With regard to this, the MapStruct documentation states:
All after-mapping methods that can be applied to a mapping method will
be used. #Qualifier / #Named can be used to filter the methods to use.
Regarding #Named, the documentation contains a good example on how to use this annotation in order to perform two different kinds of mappings for a bean property. But I do not understand how to adapt this kind of distinction to my two after-mapping methods.
You can specify the qualifier in the #BeanMapping annotation in order to make it applicable to life cycle method. Note: I recently fixed an issue in this area on the master. Don't think that's released already. Forgot the exact issue (not able to look it up currently)
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.
We are facing issue related with making a path parameter optional.
original URL /expire/{token}
What we are trying to do is have the same service work for the URL's below.
1. /expire/{token}
2. /expire
Ex:- #Path("/expire/{token}")
We have already applied other solutions from SO,but no luck so far.
What about adding another method annotated with only:
#Path("/expire")
And let this method pass a null value into the original method.
Logically, it doesn't seem to make sense to have it optional. Your URI should handle the type of request it's supposed to do. But, I came across a post to make the #PathParam to be optional with a small hack using regular expressions.
http://www.nakov.com/blog/2009/07/15/jax-rs-path-pathparam-and-optional-parameters/
I would go with having separate endpoint method in Controller where it can pass the call to your services with optional parameter.
We can use regular expressions,
"#Path("/add/{a:([0-9.]*)}/{b:([0-9.]*)}{p:/?}{c:([0-9.]*)}")"
here path can be
add/2/3
add/2/3/4
my case I am using regular expressions for allowing only numbers
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) {
....
}
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