0

I have the following classes in different packages:

@EnableWebMvc
public class ActuatorConfig
{
    // empty
    // only needed to get REST so I can hit Actuator endpoints
}

@Component // REMOVE THIS LINE?
@EnableBatchProcessing
public class BatchConfig
{
    // empty
}

@Component
@Configuration
public class ScheduleJob
{
    @Autowired
    private JobBuilderFactory jobBuilder;

    @Bean
    protected JobExecutionListener scheduleJobListener()
    {
        return new ScheduleJobListener();
    }
}

(EDIT: Added Application class)

@SpringBootApplication
public class AfxApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(AfxApplication.class, args);
    }
}

The first class turns on Actuator features. I don't need any other annotations.

However, if I remove @Component from BatchConfig as noted above, Boot won't start because it can't find the dependency on JobBuilderFactory that it needs in order to populate the @Autowired ScheduleJob.jobBuilder.

The exception:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.batch.core.configuration.annotation.JobBuilderFactory] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE]
... 25 common frames omitted

When is @Component needed and when isn't it needed?

(I pulled out the @Enable* annotations because I'm trying to run unit tests that don't need all features enabled, and this way I can specify the features I want to enable by using @ComponentScan(basePackageClasses).)

arnaldop
  • 188
  • 5
  • 14
  • 1
    You are also aware that when specifing `@Enable*` yourself that that disables Spring Boot auto configuration for parts of your application... Leading to these kind of issues. – M. Deinum Jan 27 '16 at 07:29
  • I do understand that. I went that route when it seemed that I my unit tests were "inheriting" @EnableAutoConfiguration. This was causing a problem when I wanted a unit test to test only Batch/JMS code but was getting Web/Servlet code (and issues). So I tried to separate the configuration, and reference those classes from the unit tests that needed them. – arnaldop Jan 27 '16 at 07:45
  • Also Spring Boot already enables web mvc without that class adding it doesn't add anything (but disabling the default Spring Boot configuration). – M. Deinum Jan 27 '16 at 07:49
  • Ok, all @Enable* are gone, except for the implicit @EnableAutoConfiguration from @SpringBootApplication. But I'm back to getting `No qualifying bean of type [org.springframework.batch.core.configuration.annotation.JobBuilderFactory]` in the ScheduleJob class. I think this happened a few hours ago, which is why I started going down this route... :( – arnaldop Jan 27 '16 at 07:59
  • Are you even using the correct annotations on your test class? Using `@ContextConfiguration` isn't going to work. – M. Deinum Jan 27 '16 at 08:01
  • This is not on my test class. Right now I just want to find the optimal way to configure my core code. This is class: `@Component @Configuration public class ScheduleJob { @Autowired private JobBuilderFactory jobBuilder; ... }` I also get this. Not sure if it's related by cause and effect, or by a root cause, or not at all: `Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry' is defined` What else do I need? – arnaldop Jan 27 '16 at 08:09
  • You are complaining about tests, to run tests with spring boot you need different annotations so that it knows it is a Spring Boot application. If you start messing around with `@Enable` yourself Spring Boot doesn't auto configure anything. – M. Deinum Jan 27 '16 at 08:14
  • Right. All `@Enable*` are gone in my entire app. I get exceptions with mvn spring-boot:run. Bean of type JobBuilderFactory can't be found. The example here (http://docs.spring.io/spring-batch/reference/htmlsingle/#javaConfig) shows `@EnableBatchProcessing`. Is this not handled by `@EnableAutoConfiguration`? – arnaldop Jan 27 '16 at 08:19
  • If you have spring batch on the class path it will be picked up, assuming you a proper application class. Add your application class. – M. Deinum Jan 27 '16 at 08:25
  • Please add it to your question, not as comments. However it was my bad, although there is some infrastructure code registered, it doesn't enable batch processing so you still need to add `@EnableBatchProcessing` to your application class. See also https://spring.io/guides/gs/batch-processing/ . – M. Deinum Jan 27 '16 at 08:32

1 Answers1

0

Thanks to M. Deinum, I finally have the answer.

By having @Enable*, I was disabling @EnableAutoConfiguration. The only exception is @EnableBatchProcessing, which is explicitly required. (I understand that it is so, but I am not sure why it cannot be handled by @EnableAutoConfiguration.)

The answer was a combination of the Application class listed above, and this class:

@Configuration
@EnableBatchProcessing
public class BatchConfig
{
}

Once this was in place, everything else worked.

How this will affect my test code will remain a task for another day...

arnaldop
  • 188
  • 5
  • 14