spring-bootspring-amqpspring-data-hadoop

Spring boot AMQP and Spring Hadoop together ends up with missing EmbeddedServletContainerFactory bean


I have two small apps, one uses spring-boot-starter-amqp, other uses spring-data-hadoop-boot. I can run them separately without any problems.

When I join them together, app start fails with exception: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.

My main class is pretty much generic and it works fine for both of them separately:

@PropertySource("file:conf/app.properties")
@SpringBootApplication
public class Job {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(Job.class, args);
    }
}

I am at lost here. AFAIK @SpringBootApplication contains all annotations needed, including auto configuration and components scanning. I've had no need to configure web environment as I am not using it. Why do I need to do it when both dependencies are in class path, and how do I fix it?

UPDATE

I dug a little bit in the Spring Boot code. Main problem is that SpringApplication.deduceWebEnvironment() automatically detects what kind of environment should be configured based on existence of certain classes in class path.

For web environment two classes are being checked. When both of them are in class path, web environment is detected which requires proper configuration, obviously.

spring-boot-starter-amqp:1.3.1.RELEASE contains ConfigurableWebApplicationContext, and spring-data-hadoop-boot:2.3.0.RELEASE-cdh5 contains Servlet (in native Hadoop libs).

Now, when run alone, one of above classes is missing in both cases, which results in web environment not being set.

But when I use both of them - both classes can be found. Web environment is detected, false positive, and it requires configuration, which I am not able (and don't want) to provide.

So question now is - can I force non web environment, even when I have those classes in class path? Or is there any other way to solve the issue? (other than excluding them from Gradle dependencies)


Solution

  • Solved.

    Following this question: How to prevent spring-boot autoconfiguration for spring-web?

    I run application as follows.

    @PropertySource("file:conf/app.properties")
    @SpringBootApplication
    public class Job {
        public static void main(String[] args) throws Exception {
            new SpringApplicationBuilder(Job.class).web(false).run(args);
        }
    }
    

    Answers to above question also suggested to use property spring.main.web_environment=false or annotation @EnableAutoConfiguration(exclude = WebMvcAutoConfiguration.class). Both solutions haven't worked for me. Only programmatic solution works in my case.