2

Question

Basically, I want to create a custom annotation for methods. When used, a method parameter and a line of code is added.

The question is: Is this possible and how?

Example

I want to simplify the following method:

@GetMapping("/thing")
public ResponseEntity getThing(@CookieValue("Session-Token") String sessionToken) {
    User user = authenticator.authenticateSessionTokenOrThrow(sessionToken);
    ... // user is successfully authenticated, get the "thing" from the database
}

to

@GetMapping("/thing")
@User
public ResponseEntity getThing() {
    ... // user is successfully authenticated, get the "thing" from the database
}

How can I implement the custom annotation @User so that the above two methods behave in the exact same way? For the sake of the example, please ignore the fact that the above code is for the Spring Boot framework.

3
  • You are looking for is annotation processing. Commented Mar 21, 2019 at 18:35
  • I don't think this is possible. The reason being is that you want to edit the method itself, so you want to edit the bytecode of the method depending on the annotation. According to this dzone.com/articles/how-annotations-work-java, this is not possible for custom annotations. Commented Mar 21, 2019 at 18:41
  • 1
    @PeterLawrey An important thing to note is the limitation of the annotation processing API — it can only be used to generate new files, not to change existing ones. baeldung.com/java-annotation-processing-builder Commented Mar 21, 2019 at 20:51

1 Answer 1

1

Say you have a class with methods like this

class MyHandlerClass implements Whatever {
    @GetMapping("/thing")
    @User
    public ResponseEntity getThing() {
        ... // user is successfully authenticated, get the "thing" from the database
    }

You can use annotation processing to generate a class like this

class AuthenticatingMyHandlerClass extends MyHandlerClass {

    @GetMapping("/thing")
    public ResponseEntity getThing(@CookieValue("Session-Token") String sessionToken) {
        User user = authenticator.authenticateSessionTokenOrThrow(sessionToken);
        ResponseEntity ret = super.getThing(sessionToken);
        doSomethingWith(ret);
        return ret;
    }

Then you use the generated class instead of the main class for handling requests and will have any code you added as well.

Sign up to request clarification or add additional context in comments.

2 Comments

It's a very smart move, but now comes the tricky bit... Not having two different handlers available in the end. (which is the Spring-Boot-specific thing I asked to ignore). I believe a compiler error will be generated because the same resource /thing in two endpoints makes it ambiguous. So now I need to find a way to disable the original method somehow when the new method is generated. Maybe I could define the original class without the @RestController annotation and generate the new class with it.. hmm...
@anddero you could use an annotation which is not picked up by the framework in your source (which is the default behaviour for an annotation)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.