Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enforce subclass to add @Schedule to a method in super abstract class in Java Spring

I have a super abstract class that has some common implemented methods and other abstract methods to be implemented by a subclass. One of the common implemented methods is a method to be annotated as @Scheduled, but I want the subclass to define how this schedule should be defined (fixed delay, fixed rate or cron .. etc). How to implement such behaviour ?

One approach I thought of is to override the method to be scheduled in the subclass such that it just call its corresponding method in the super class and add the @Scheduled on it with the desired definition, but I don't know how to enforce the subclass to do so as this method is not abstract.

Super Abstract Class

public abstract class SuperClass {
       public abstract void x();
       public void y() { 
              // Some implementation
       } 
    
       // Method to be scheduled. 
       public void scheduledMethod() {
              x();
              y();
       }
}

Subclass

public class Subclass extends SuperClass {
       @Override
       public void x() { 
              // Some implementation
       }

       // How to enforce the developer to add this ? 
       @Scheduled(cron = "0 0 0 * * ?")
       public void scheduledMethod(){
              super.scheduledMethod();
       } 
}
like image 971
Yomna Hesham Avatar asked Sep 20 '25 22:09

Yomna Hesham


2 Answers

I couldn't get my head around how you could use @Scheduled but, I've an alternative:

  1. In your abstract class, require a method to be implemented by subclasses to return the schedule:
public String getCronString();
  1. Programmatically schedule the task using Scheduler using the method getCronString() that's implemented in your subclasses, to return the cron schedule. Few examples on how to programmatically schedule tasks with Spring boot:
  • https://www.baeldung.com/spring-task-scheduler
  • SO Question

Basically, if your subclasses are not implementing public String getCronString(); your code won't compile.

like image 193
Hasan Can Saral Avatar answered Sep 22 '25 13:09

Hasan Can Saral


One option would be to check that the @Scheduled annotation is present (or meta-present) at bean creation time. This can be easily achieved using reflection in a @PostConstruct method on the superclass:

import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ClassUtils;

public abstract class SuperClass {
    ...

    @PostConstruct
    public void enforceScheduling() {
        boolean annotationPresent = AnnotationUtils.getAnnotation(ClassUtils.getMethod(getClass(), "scheduledMethod"), Scheduled.class) != null;
        if (!annotationPresent) {
            throw new IllegalStateException("@Scheduled annotation missing from scheduledMethod");
        }
    }
}

This will cause an exception to be thrown at application start-up time when Spring attempts to create the bean, failing fast and making it very obvious what is missing.

like image 24
M. Justin Avatar answered Sep 22 '25 12:09

M. Justin