Java Expression Language evaluator generators. It generates java class from expressions in custom annotations.
Tip
|
this part is highly inspired from Microprofile JWT Auth extension which uses Simple Jel module. |
A Simple JEL annotation must be marked with @MetaJel
.
It will enable you to define the evaluation context type, expected returned type and optional marker to put on the evaluator.
Here is an example:
import com.github.rmannibucau.jel.api.annotation.MetaJel;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@MetaJel(
expressionElementName = "value",
contextType = "com.custom.framework.SecurityContent",
returnType = "boolean",
evaluatorMarkers = "com.custom.framework.ApplicationScoped")
@Retention(RUNTIME)
@Target(METHOD)
public @interface SecuredBy {
String value();
}
The compilation - if the annotation processor is not excluded - will produce a file per method annotation with @SecuredBy
.
For example:
public class MyService {
@SecuredBy("return context.getPrincipal() != null && context.getPrincipal().getName().equals(\"admin\")")
public List<Data> findAdminData() {
// ...
}
}
If you have an IoC in place you can intercept the method and handle the validation with such a code:
// this part can be cached in general
final String prefix = MyService.class.getName() + "$findAdminData"; // from interception context in general
final ClassLoader loader = ...;
final Class<? extends Function<SecurityContext, Boolean>> evaluatorClass =
loader.loadClass(prefix + "$SimpleJelEvaluator").asSubclass(Evaluator.class);
// now either you just create a new instance as in this snippet or you lookup the bean from your
// spring context, CDI context etc...
final Function<SecurityContext, Boolean> evaluator = evaluatorClass.getConstructor().newInstance();
// runtime/interceptor evaluation
if (!evaluator.apply(getSecurityContext())) {
// fail
}
To generate the classes you must add simple-jel-proc
to your classpath.
Note that it is not needed at runtime so you can use scope provided
:
<dependency>
<groupId>com.github.rmannibucau.jel</groupId>
<artifactId>simple-jel-proc</artifactId>
<version>${simple-jel.version}</version>
<scope>provided</scope>
</dependency>