Search code examples
javaspringspring-securityspring-el

Spring expression cannot resolve type


I have a service method annotated with @PostAuthorize

@PostAuthorize("hasPermission(returnObject, new ReadUserPermission())")
public Optional<User> find(String email) {
    // implementation
}

As soon as the method gets called, spring throws the following exceptions:

Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1003E:(pos 28): A problem occurred whilst attempting to construct an object of type 'ReadUserPermission' using arguments '()'
    at org.springframework.expression.spel.ast.ConstructorReference.findExecutorForConstructor(ConstructorReference.java:190) ~[spring-expression-4.0.0.RELEASE.jar:4.0.0.RELEASE]
    at org.springframework.expression.spel.ast.ConstructorReference.createNewInstance(ConstructorReference.java:151) ~[spring-expression-4.0.0.RELEASE.jar:4.0.0.RELEASE]
    at org.springframework.expression.spel.ast.ConstructorReference.getValueInternal(ConstructorReference.java:94) ~[spring-expression-4.0.0.RELEASE.jar:4.0.0.RELEASE]
    at org.springframework.expression.spel.ast.MethodReference.getArguments(MethodReference.java:147) ~[spring-expression-4.0.0.RELEASE.jar:4.0.0.RELEASE]
    at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:79) ~[spring-expression-4.0.0.RELEASE.jar:4.0.0.RELEASE]
    at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:113) ~[spring-expression-4.0.0.RELEASE.jar:4.0.0.RELEASE]
    at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:105) ~[spring-expression-4.0.0.RELEASE.jar:4.0.0.RELEASE]
    at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:11) ~[spring-security-core-3.1.2.RELEASE.jar:3.1.2.RELEASE]
    ... 86 common frames omitted
Caused by: org.springframework.expression.AccessException: Failed to resolve constructor
    at org.springframework.expression.spel.support.ReflectiveConstructorResolver.resolve(ReflectiveConstructorResolver.java:121) ~[spring-expression-4.0.0.RELEASE.jar:4.0.0.RELEASE]
    at org.springframework.expression.spel.ast.ConstructorReference.findExecutorForConstructor(ConstructorReference.java:181) ~[spring-expression-4.0.0.RELEASE.jar:4.0.0.RELEASE]
    ... 93 common frames omitted
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1005E:(pos 0): Type cannot be found 'ReadUserPermission'
    at org.springframework.expression.spel.support.StandardTypeLocator.findType(StandardTypeLocator.java:81) ~[spring-expression-4.0.0.RELEASE.jar:4.0.0.RELEASE]
    at org.springframework.expression.spel.support.ReflectiveConstructorResolver.resolve(ReflectiveConstructorResolver.java:61) ~[spring-expression-4.0.0.RELEASE.jar:4.0.0.RELEASE]
    ... 94 common frames omitted

ReadUserPermission looks like this:

@Component
public class ReadUserPermission implements Permission<User> {

    @Override
    public boolean hasPermission(User user, User target) {
        // implementation
    }
}

At first, neither the class ReadUserPermission nor the interface Permission was annotated with @Component. I thought maybe springs needs the annotation to find the type but it does not matter if I annotate the interface or the class or both. The exception is always the same.


Solution

  • I overlooked this part of the documentation:

    Constructors can be invoked using the new operator. The fully qualified class name should be used for all but the primitive type and String (where int, float, etc, can be used)