javaspringspring-boottomcatembedded-tomcat-8

Spring boot - Rest Call client without embedded tomcat


I have been trying to figure out an issue with spring boot and as i am new to spring I thought of getting some help here.

I have a spring boot based java application which runs as a daemon and makes some GET request to a remote server. (Acts only as a client).

But my spring boot application internally starts an embedded tomcat container. My understanding is that if the java app acts as a server, it would need tomcat. But my application being only a consumer of remote machine's GET APIs, why would it need an embedded tomcat ?

In my pom file I have specified spring-boot-starter-web, on assumption that it is needed for even making GET calls.

But after doing some research on disabling embedded tomcat, I found a solution.

To make following changes,

@SpringBootApplication(exclude = {EmbeddedServletContainerAutoConfiguration.class, 
WebMvcAutoConfiguration.class})

& in application.yml

spring:
   main:
      web-environment: false

With the application.yml changes, my jar is not even getting started, aborts directly, without even logging anything in logback logs.

Now, if i remove the application.yml change, my jar starts (only with first change in @SpringBootApplication anno.) but goes into some exception.

 [main] o.s.boot.SpringApplication               : Application startup failed

org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.

My Doubts here are,

1) Is tomcat, be it standalone or embedded, really needed for a application which just makes GET API calls to remote machine ?

2) How do i overcome this exception and safely remove the embedded tomcat and still perform the GET API calls ?


Solution

  • You seem to be on completely the wrong track here, starting from a web application template and then trying to turn off the web application aspect.

    Far better to start from a regular commandline client template and go from there, as detailed in the relevant Spring Guide.

    Basically the application reduces to

    @SpringBootApplication
    public class Application {
    
    private static final Logger log = LoggerFactory.getLogger(Application.class);
    
    public static void main(String args[]) {
        SpringApplication.run(Application.class);
    }
    
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.build();
    }
    
    @Bean
    public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
        return args -> {
            Quote quote = restTemplate.getForObject(
                    "http://gturnquist-quoters.cfapps.io/api/random", Quote.class);
            log.info(quote.toString());
        };
    }
    }
    

    And the pom to

        <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
    </dependencies>