简体   繁体   中英

Spring Boot Application with Two Entrypoints: CLI and Web Service

I have a spring-boot-starter application that I created that started as a CommandLineRunner that runs in Kubernetes as a CronJob, something like:

@SpringBootApplication
@EnableAutoConfiguration
public class JobApplication implements CommandLineRunner {
  Logger logger = LoggerFactory.getLogger(JobApplication.class);


  public static void main(String[] args) {
    ConfigurableApplicationContext context = SpringApplication.run(JobApplication.class, args);
    context.close();
  }

  @Override
  public void run(String... args) throws Exception {
    // run the job
  }
}

I currently run the application in a Dockerfile like this and everything works fine.

CMD java -jar /job/job.jar

In this Application there's some Database code and DTOs that I'd like to use and expose as a Spring Web Service, ideally inside the same codebase so I don't have to create multiple Github repos and Java projects and publish a shared library that both use. I'd like to keep it simple and just be able to compile and use them directly.

Is there a way to do that? I think I'd need a second WebApplication class, but then I'm not sure how to execute it so it uses that instead of the Job.

If not, is there a recommended approach to do what I want to do (building multiple jars is ok if that's the only way... but I'd really like to keep all the code in the same project)?

Have you tried to try to use @Profile ?

For example:

@Profile("CMD")
@SpringBootApplication
@EnableAutoConfiguration
public class JobApplication implements CommandLineRunner {
  Logger logger = LoggerFactory.getLogger(JobApplication.class);


  public static void main(String[] args) {
    ConfigurableApplicationContext context = SpringApplication.run(JobApplication.class, args);
    context.close();
  }

  @Override
  public void run(String... args) throws Exception {
    // run the job
  }
}


@Profile("WEB")
@SpringBootApplication
public class WebApplication extends SpringBootServletInitializer {

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

}

You can start command line as java -jar /job/job.jar -Dspring.profiles.active=CMD

and web with profile WEB.

Because @Profile is a runtime spring annotation it can't be processed until spring context is loaded, you will have (as you discovered)

Unable to find a single main class from the following candidates [my.app.WebApplication, my.app.JobApplication]

For this reason you can start a specific spring boot main class with

-Dstart-class=com.sample.WebApplication

And now it should not load the second because now the @Profile should work

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