8

I am in the proces of converting a simple java project into a spring boot variant. The Spring Boot Reference Guide http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/ has been very helpful in general, but most examples of setting up a simple configuration involve some web based application. The getting started tutorial from https://spring.io/guides/gs/spring-boot/ tutorial doesn't provide the answer I am looking for either.

I have one class HelloSpring that I need to run one method on printHello(). I have configured the following classes, placed in the same package for simplicity:

Application.class

@SpringBootApplication
public class Application {

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

}

HelloConfiguration.class

@Configuration
public class HelloConfiguration {

    @Bean
    public HelloSpring helloSpring(){
        HelloSpring hs = new HelloSpring();
        hs.printHello();
        hs.printHelloAgain();
        return hs;
    }

    @Autowired
    public HelloSpring hs;

}

HelloSpring.class

public class HelloSpring {

    public void printHello() {
        System.out.println("Hello Spring!");
    }

    @PostConstruct
    public void printHelloAgain() {
        System.out.println("Hello Spring?");
    }

}

It prints (spring logging omitted):

Hello Spring!
Hello Spring?
Hello Spring?

However, I am unsure of the correct way to execute my HelloSpring class.

Given above example, what is the official way to wire and "run" a class when using spring boot?

Sander_M
  • 1,109
  • 2
  • 18
  • 36
  • May I ask which features of Spring boot you want to use in your non-web application? As you've noticed Boot is mostly focused on web, so that's a pretty poor match IMO. – mszymborski Aug 14 '16 at 19:09
  • Mostly the use of spring properties annotations, being able to log the application using spring boot admin, adding some database transaction without having to configure alot and being able to use a set of pre defined settings/configurations (spring boot takes an opinionated view of the Spring platform) – Sander_M Aug 14 '16 at 19:16
  • @mszymborski I would say Spring Boot is actually a lot less focused on Web than a traditional Spring Framework project. If you check out http://start.spring.io/ you will see Web is only one dependency choice from a miriad of choices. – Shawn Clark Aug 15 '16 at 03:42

4 Answers4

8

Simply use the ApplicationContext that SpringApplication.run returns and then work with that. That's pretty much all that is required

public static void main(String[] args) {
    ApplicationContext context = SpringApplication.run(Application.class, args);
    HelloSpring bean = context.getBean(HelloSpring.class);
    bean.printHello();
}

So you can open a gui, etc. and use the ApplicationContext to get your beans, etc.

Florian Schaetz
  • 10,454
  • 5
  • 32
  • 58
  • Plain and simple, thank you very much for your fast answer, works like a charm. – Sander_M Aug 14 '16 at 19:40
  • Using the context directly doesn't really lend itself well to using the capabilities of Spring Boot. What was originally posted was closer to using the capabilities. I am providing an answer shortly with an example. – Shawn Clark Aug 15 '16 at 03:46
6

From the docs: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-command-line-runner

Application.class

@SpringBootApplication
public class Application {

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

}

HelloSpring.class

@Component
public class HelloSpring implements CommandLineRunner {
    @Override
    public void run(String... args) {
        this.printHello();
    }

    public void printHello() {
        System.out.println("Hello Spring!");
    }
}

You can even make it so the run() method actually prints out you message but this way keeps it closer to your intent where you have implemented a method and want it executed when the application starts.

Shawn Clark
  • 3,330
  • 2
  • 18
  • 30
  • Very clean as well, thank you. Is there an advantage of using this approach above the approach of using a bean and getting the bean from the application context? In other words, must I use a bean in my simple scenario? – Sander_M Aug 15 '16 at 08:55
  • 1
    Beans are how Spring wires things together. Even in my example the HelloSpring becomes a Bean. Spring just knows to execute the `run()` method due to the fact that it scans all beans for any that implement the `CommandLineRunner`. As I stated in my comment on the other answer it is best practice if you can leave the interaction of the `ApplicationContext` to Spring itself and instead use the annotations / interfaces then you will have more flexibility. – Shawn Clark Aug 15 '16 at 09:03
  • While I agree that this is a good solution, I disagree that handling the context is per se bad. It depends, with your solution, you must effectively manage your whole application as Spring, while with the context solution you can keep parts of the application outside Spring and just use it where you want to. What is preferable depends on the use case and the application. – Florian Schaetz Aug 15 '16 at 10:42
0

Step1: Create a Springboot project with web-application by default. Pom.xml:

<!-- Springboot for web application -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Step2: add the following config to application.properties file. the app will be the no-web application:

spring.main.web-environment=false
spring.main.banner-mode=off

Step3: Springboot loader like web-application:

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

step4: code for non-web application:

//uncomment @component to run non-web app mode with the above config
// comment @component to run web-app  mode without the above config
@Component
public class NonWebApp implements CommandLineRunner{
    @Override    
    public void run(String... args) throws Exception {
        System.out.println("************* better than best ************************");
   }
}
HungNM2
  • 3,101
  • 1
  • 30
  • 21
0

OK, Sound you want to use Spring Framework as dependency injection. OK you being to understand some spring core annotation such as before: @Configuration is the way to tell the spring it's the component need to scan as spring component and put in the spring IoC. Bean is the object that store in spring IoC. Be able to create the @Bean class, we need to create the class with @Configuration annotation.

Create your Bean

@Configuration
public class HelloConfiguration{
@Bean
public HelloSpring helloSpring(){
    HelloSpring hs = new HelloSpring();
    return hs;
 }}

Your Service Class

public class HelloSpring {

public void printHello() {
    System.out.println("Hello Spring!");
}

public void printHelloAgain() {
    System.out.println("Hello Spring?");
}

@PostConstruct is know the annotation using by JavaEE and tell spring need to execute when bean initial in spring IoC.

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

Or you can do like this:

@Configuration
@EnableAutoConfiguration
@@Import(HelloConfiguration.class) 
public class Application {

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

@SpringBootApplication == @Configuration & @EnableAutoConfiguration & @Import.

If you want to run your method when your spring boot application already started, some case you need to caches data and put in your application memory caches, initial method as callback. There are two ways be able to do this:

Create your class as spring component and implement ApplicationRunner or CommandLineRunner. ApplicationRunner: [https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/ApplicationRunner.html] provide the method run that we can provide application argument. CommandLineRunner:[https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/CommandLineRunner.html] also provide the method run as callback that we can provide String[] argument.

Example

@Component
@Order(1)
public class MyRunner implement ApplicationRunner {

private final HelloSpring helloSpring 

public MyRunner(HelloSpring helloSpring){ // constructer injection
       this.helloSpring=helloSpring;
}

@Override
public void run(ApplicationArguments args) throws Exception {
   helloSpring.printHello();
   helloSpring.printHelloAgain();
   } 
}
soyphea
  • 469
  • 5
  • 11