Spring AOP with type parameter with annotation Collection<#SomeAnnotation> - spring

I want to advice methods which arguments are annotated. The exact designator I am trying is args(Collection<#SomeAnnotation *>) but it says "error wildcard type pattern not allowed, must use type name".
The poincut looks like this :
execution(public * someMethod(..)) && args(java.util.Collection<#SomeAnnotation *>)
Example signatures :
#SomeAnnotation * - any type marked with #SomeAnnotation annotation
Collection<#SomeAnnotation *> - collection type, with a type parameter marked with #SomeAnnotation annotation
Could someone help if this is possible at all.
Thanks

Collection<#SomeAnnotation *> is not a valid Java expression for generics. In AspectJ, you need to stick to Java syntax for generic types. You cannot describe generic type parameters in the same way as you can describe regular types. The only syntax extension I know of and found in the documentation is the + syntax designating subtypes, e.g. List<? extends Object+>.
You want to read chapter "Generics in AspectJ 5" from the AspectJ documentation and probably the whole generics section.
This Java question also is related. Some workarounds and tools are discussed there.

Related

How to configure the pointcut expressions dynamically

I am looking for a solution for the problem where I can configure the pointcut expressions dynamically by reading from a properties file or database.
for example:
#Around("execution(* com.example.updateUser(..))")
in above example, we have hardcoded the expression.
I am looking for the solution where I can read
execution(* com.example.updateUser(..))
and then use it in #Around annotation.
I did not come across similar problem on web.
Any solution for such problem is highly appreciated.
Thank you!!
You can use schema-based AOP and define the pointcut in classical, old-school XML style. Spring XML config is a text file being read while starting up the application and thus would satisfy your requirement.
If you like to manually wire your pointcut into an aspect, you can do that, too. Whether you define a string variable or field containing the pointcut directly in your application or read the pointcut from a text file, is completely up to you. Search for the terms DefaultPointcutAdvisor and AspectJExpressionPointcut in my answer here, somewhere inside the "update 2" and "update 3" parapgraphs. There you will also find a link to a complete sample project.

List<List<String>> mapped to List<String>

I'm learning how to use Mapstruct in a Spring Boot and Kotlin project.
I've got a generated DTO (ThessaurusDTO) that has a List and I need this mapped into a List on my model (Vocab).
It makes sense that MapStruct can't map this automatically, but I know for a fact that the first list will always be size = 1. I have no control on the API the DTO model belongs to.
I found on the documentation that I can create define a default method implementation within the interface, which would loosely translate to a normal function in Kotlin
My mapper interface:
#Mapper
interface VocabMapper {
#Mappings(
// ...
)
fun thessaurusToVocab(thessaurusDTO: ThessaurusDTO): Vocab
fun metaSyns(nestedList: List<List<String>>): List<String>
= nestedList.flatten()
}
When I try to do a build I get the following error:
VocabMapper.java:16: error: Can't map collection element "java.util.List<java.lang.String>" to "java.lang.String ". Consider to declare/implement a mapping method: "java.lang.String map(java.util.List<java.lang.String> value)".
It looks like mapStruct is still trying to automatically do the mapping while ignoring my custom implementation. Am I missing something trivial here?
I found on the documentation that I can create define a default method implementation within the interface, which would loosely translate to a normal function in Kotlin
From my understand of what I found online, Kotlin does not properly translate an interface function into a default method in Java, but actually generates a class that implements the interface.
If that's the problem, you can annotate metaSyns with #JvmDefault:
Specifies that a JVM default method should be generated for non-abstract Kotlin interface member.
Usages of this annotation require an explicit compilation argument to be specified: either -Xjvm-default=enable or -Xjvm-default=compatibility.
See the link for the difference, but you probably need -Xjvm-default=enable.
I've seen to have fixed this by relying on an abstract based implementation, instead of using an interface.
From my understand of what I found online, Kotlin does not properly translate an interface function into a default method in Java, but actually generates a class that implements the interface.
https://github.com/mapstruct/mapstruct/issues/1577

Spring AOP pointcut expression by argument name

Is it possible to have a pointcut expression match based on the method argument name?
For example, I want to match all methods with employeeId as an argument.
public Employee findById(Integer employeeId);
I can't match by data type because it would be too broad.
I know I can use the wildcards to match anything i.e. "execution(* * (..))" and check for the argument name in the method body, but that seems excessive?
NO. You can not match based on arg names; but it's possible to match based on the arg TYPEs.
To solve your problem, you can use the nearest pointcut expression to catch the target methods, and then filtering these methods programmatically in your aspect.
Point Cut based on argument name is not supported in Spring AOP.
Supported Point Cut Designators are listed here: Supported Pointcut Designators

Ignore S00107 with #JsonCreator annotated constructor

I'm using SQ 6.0 and I have some POJOs which are (de)serialized by Spring/Jackson. For immutability reasons all members are passed to the constructor, so SQ complains with "Constructor has X parameters, which is greater than 7 authorized".
Since the constructor is annotated with #JsonCreator the number of arguments should imho be ignored, is there a way to configure this?
In your case would indeed make sense to have a way to exclude those constructors the same way constructors with #RequestMapping annotation are automatically excluded : https://jira.sonarsource.com/browse/RSPEC-2415. The short answer is no, there is no way. I'm going to open a thread on the SonarQube mailing list on this subject to see what we could do at mid-term.

Calling static methods from Spring Security Expressions?

I'm looking for a way to extend Spring Security Expressions to support an existing security infrastructure. I'm aware you can extend the MethodSecurityExpressionRoot as described here, but I also found reference to directly calling static methods through Spring Expression Language (Spring EL or SpEL). Unfortunately the official page on Spring Expression methods doesn't directly describe how to do this.
How can I invoke a static method through Spring Expression methods?
By using the T(fully.qualified.name).methodName() syntax:
You can use the special T operator to specify an instance of java.lang.Class (the type). Static methods are invoked by using this operator as well. The StandardEvaluationContext uses a TypeLocator to find types, and the StandardTypeLocator (which can be replaced) is built with an understanding of the java.lang package. This means that T() references to types within java.lang do not need to be fully qualified, but all other type references must be.
The T element returns a reference to the type instead of an instance. For example, the equivalent of Collections.singleton("Hello") is
T(java.util.Collections).singleton('Hello')

Resources