Background job dependencies

Use any IoC container to inject dependencies into your background job service classes.

TLDR;

If you are using either the JobRunr Spring Boot Starter, Micronaut Integration or Quarkus Extension, you can just have beans or services injected into your background job (e.g. the service class that you are calling) and JobRequestHandler.

A long, long time ago…

There was a background job that needed a certain dependency to fulfill it’s work…

In almost every job you’ll want to use other classes of your application to perform different work and keep your code clean and simple. An example:

@Component
public class MailService {
    
    private EmailRenderer emailRenderer;
    private UserRepository userRepository;
    private Environment environment;
    
    public MailService(EmailRenderer emailRenderer, UserRepository userRepository, Environment environment) {
        this.emailRenderer = emailRenderer;
        this.userRepository = userRepository;
        this.environment = environment;
    }
    
    public void sendMail(UUID userId, String templateId) {
    	User user = userRepository.getById(userId);
        String htmlEmail = emailRenderer.renderEmail(user, templateId);
        sendMail(user.getEmailAddress(), htmlEmail);
    }
    
    private void sendMail(String to, String htmlContent) {
    	Session session = Session.getInstance(prop, null);
    	Message message = new MimeMessage(session);
      message.setFrom(new InternetAddress(env.getProperty("mail.from")));
      message.setRecipients(
        Message.RecipientType.TO, InternetAddress.parse(to));
      message.setSubject(env.getProperty("mail.subject"));

      MimeBodyPart mimeBodyPart = new MimeBodyPart();
      mimeBodyPart.setContent(htmlContent, "text/html");
      Multipart multipart = new MimeMultipart();
      multipart.addBodyPart(mimeBodyPart);
      message.setContent(multipart);
      Transport.send(message);
    }
    
    private Properties getSmtpProperties() {
    	Properties prop = new Properties();
        prop.put("mail.smtp.host", env.getProperty("smtp.host"));
        prop.put("mail.smtp.port", "25");
        return prop;
    }
    
}
An example of a background job (mailService.sendMail()) with three dependencies
Let’s call these classes as dependencies. How to pass these dependencies to methods that will be called in background?

JobRunr supports the following patterns to inject dependencies intro background job services:

IoC containers

JobRunr supports all IoC containers via a simple abstraction layer - the JobActivator. The JobActivator is a Java 8 Functional Interface and gives JobRunr an abstraction over all kinds of IoC containers, including Spring Framework, Micronaut, Quarkus ARC dependency injection and Guice.

The interface is as follows:

@FunctionalInterface
public interface JobActivator {

    <T> T activateJob(Class<T> type);

}

When a certain background job needs to be executed, JobRunr will try to resolve the actual service instance via the JobActivator. This allows JobRunr to resolve a fully wired service bean that is ready to invoke it’s background method.

The JobActivator is automatically created by the JobRunr Spring Boot Starter, the Micronaut Integration and the Quarkus Extension - there is no need for you to create it normally.

If you do need to create it manually, this can be done as follows (a Spring framework example):

@Bean
public BackgroundJobServer backgroundJobServer(StorageProvider storageProvider, JobActivator jobActivator) {
    BackgroundJobServer backgroundJobServer = new BackgroundJobServer(storageProvider, jobActivator);
    backgroundJobServer.start();
    return backgroundJobServer;
}

@Bean
public JobActivator jobActivator(ApplicationContext applicationContext) {
	return applicationContext::getBean;
}

The JobActivator is nothing more than a simple method reference to the ApplicationContext::getBean method.