Skip to content

Latest commit

 

History

History
81 lines (65 loc) · 2.5 KB

README.adoc

File metadata and controls

81 lines (65 loc) · 2.5 KB

Simple JEL

Java Expression Language evaluator generators. It generates java class from expressions in custom annotations.

Define A custom annotation

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
}

Classpath

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>