简体   繁体   中英

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 ?

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>

I had this problem. All I wanted was to have a Client making REST requests. Unfortunately I had a dependency which was embedding Jetty, and Jetty was always started.

In order to disable Jetty all I needed to do was to add in applications.properties the following entry:

spring.main.web-application-type=none

That fixed it.

Here is the most simple solution for me, make spring boot application just a restful api consumer.

Replace the dependence

implementation("org.springframework.boot:spring-boot-starter-web")

with

implementation("org.springframework.boot:spring-boot-starter-json")

RestTemplate and jackson are available in the project without embedded tomcat.

Answering your questions:

1) embedded by defaut - not needed for clients HTTP requests;

2) You can use CommandLineRunner for spring boot applications without any web:

@SpringBootApplication
public class SpringBootConsoleApplication implements CommandLineRunner {

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

    @Override
    public void run(String... args) {
        // TODO: start you thread here to execute client HTTP REST requests (or any other job you need)
    }
}

This will disable web completelly - no issues with manual miss-configuration.

Here is some docs: http://www.baeldung.com/spring-boot-console-app

You also need replase spring-boot-starter-web dependency with spring-boot-starter:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

From your question, i assume you want your application to keep running in background and it makes some get calls in it's life cycle. If that's the case, then

  1. answering your first question, yes, you need an embedded tomcat or jetty or need to deploy your application to an external application server.
  2. Second, to get rid of the exception your facing, don't exclude EmbeddedServletContainerAutoConfiguration and WebMvcAutoConfiguration class as it's needed for default embedded tomcat auto configuration.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM