Showing posts with label springboot. Show all posts
Showing posts with label springboot. Show all posts

Saturday, June 10, 2017

Running A SpringBoot Application : Dev to Prod

Lets look at different ways to Run a Spring Boot Application.
Lets start from Dev machine and move to Production Systems

From IDE
In STS, just right click and "Run As Spring Boot Application"

Running As a packaged application
If you use the Spring Boot Maven or Gradle plugins to create an executable jar you can run your application using java -jar. For example:
$ java -jar target/myproject-0.0.1-SNAPSHOT.jar

It is also possible to run a packaged application with remote debugging support enabled. This allows you to attach a debugger to your packaged application:
$ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n \
       -jar target/myproject-0.0.1-SNAPSHOT.jar


If One simply call java -jar the application will die when user logs out.
So cant use this way in non dev environments.

Running Using the Maven plugin
The Spring Boot Maven plugin includes a run goal which can be used to quickly compile and run your application. Applications run in an exploded form just like in your IDE.
$ mvn spring-boot:run

You might also want to use the useful operating system environment variable:
$ export MAVEN_OPTS=-Xmx1024m -XX:MaxPermSize=128M

Production :Option 1
In Short make a fully executable jar.
Whats are fully executable jars ?
In additional to running Spring Boot applications using java -jar it is also possible to make fully executable applications for Unix systems. A fully executable jar can be executed like any other executable binary or it can be registered with init.d or systemd. This makes it very easy to install and manage Spring Boot applications in common production environments.
[Warning]

Fully executable jars work by embedding an extra script at the front of the file. Currently, some tools do not accept this format so you may not always be able to use this technique. For example, jar -xf may silently fail to extract a jar or war that has been made fully-executable. It is recommended that you only make your jar or war fully executable if you intened to execute it directly, rather than running it with java -jar or deploying it to a servlet container.


Since Spring Boot 1.3.0.M1, you are able to build fully executable jars.
For maven, just include the following in your pom.xml


<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <executable>true</executable>
    </configuration>
</plugin>

These fully executable jars contains an extra script at the front of the file, which allows you to just symlink your spring boot jar to init.d or use a systemd script

init.d example:

$ln -s /var/yourapp/yourapp.jar /etc/init.d/yourapp

This allows you to start, stop and restart your application like:

$/etc/init.d/yourapp start|stop|restart 

What is init.d ?


/etc/init.d contains scripts used by the System V init tools (SysVinit). This is the traditional service management package for Linux, containing the init program (the first process that is run when the kernel has finished initializing¹) as well as some infrastructure to start and stop services and configure them. Specifically, files in /etc/init.d are shell scripts that respond to start, stop, restart, and (when supported) reload commands to manage a particular service. These scripts can be invoked directly or (most commonly) via some other trigger (typically the presence of a symbolic link in /etc/rc?.d/).

/etc/init contains configuration files used by Upstart. Upstart is a young service management package championed by Ubuntu. Files in /etc/init are configuration files telling Upstart how and when to start, stop, reload the configuration, or query the status of a service. As of lucid, Ubuntu is transitioning from SysVinit to Upstart, which explains why many services come with SysVinit scripts even though Upstart configuration files are preferred. In fact, the SysVinit scripts are processed by a compatibility layer in Upstart.

.d in directory names typically indicates a directory containing many configuration files or scripts for a particular situation (e.g. /etc/apt/sources.list.d contains files that are concatenated to make a virtual sources.list; /etc/network/if-up.d contains scripts that are executed when a network interface is activated). This structure is usually used when each entry in the directory is provided by a different source, so that each package can deposit its own plug-in without having to parse a single configuration file to reference itself. In this case, it just happens that “init” is a logical name for the directory, SysVinit came first and used init.d, and Upstart used plain init for a directory with a similar purpose (it would have been more “mainstream”, and perhaps less arrogant, if they'd used /etc/upstart.d instead).



Production :Option 2

Keep two initializers. One for development and another for production. For development, use the main method like this:


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

Initializer for production environment extends the SpringBootServletInitializer and looks like this:

@SpringBootApplication
public class MyAppInitializerServlet extends SpringBootServletInitializer{
    private static final Logger log = Logger
            .getLogger(SpringBootServletInitializer.class);
    @Override
    protected SpringApplicationBuilder configure(
            SpringApplicationBuilder builder) {
        log.trace("Initializing the application");
        return builder.sources(MyAppInitializerServlet .class);
    }

}
 

 
If using gradle , build.gradle file applies 'WAR' plugin. When running it in the development environment, use bootrun task. Where as when you want to deploy it to production, use assemble task to generate the WAR and deploy.

One can can run like a normal spring application in production without discounting the advantages provided by the inbuilt tomcat while developing.

Spring Boot : Writing Non Web Applications

Lets say you need to write a command line Java Application using Spring Boot ... how do you achieve same ?



import org.springframework.boot.CommandLineRunner;

@SpringBootApplication
public class SpringBootConsoleApplication implements CommandLineRunner {

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

    //access command line arguments
    @Override
    public void run(String... args) throws Exception {
        //do something
    }
}

What is the CommandLineRunner Interface ?

Spring Boot provides two interfaces, CommandLineRunner and ApplicationRunner, to run specific pieces of code when an application is fully started. These interfaces get called just before run() once SpringApplication completes.

Both interfaces work in the same way and offer a single run method which will be called just before SpringApplication.run(…​) completes.


@Component
@Order(1)
public class AppStartupRunner implements ApplicationRunner {
    private static final Logger logger = LoggerFactory.getLogger(AppStartupRunner.class);

    @Override
    public void run(ApplicationArguments args) throws Exception {
     Set<String> argSet = args.getOptionNames();
        logger.info("Your application started with option names : {}", argSet);
    }
}

You can have as many runners as you want , Just use @Order to manage execution order


@Component
@Order(2)
public class CommandLineAppStartupRunner implements CommandLineRunner {
    private static final Logger logger = LoggerFactory.getLogger(CommandLineAppStartupRunner.class);

    @Override
    public void run(String...args) throws Exception {
        logger.info("Application started with command-line arguments: {} . \n To kill this application, press Ctrl + C.", Arrays.toString(args));
    }
}

Spring Boot : The Magic Behind the Main Class

Lets take a closer look at the Main Class in SpringBootApplication



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

@SpringBootApplication
Many Spring Boot developers always have their main class annotated with @Configuration, @EnableAutoConfiguration and @ComponentScan. Since these annotations are so frequently used together (especially if you follow the best practices above), Spring Boot provides a convenient @SpringBootApplication alternative.

Hence @SpringBootApplication = @ComponentScan + @Configuration + @EnableAutoConfiguration  


  • @Configuration : This annotation is not specific to the spring boot applications. This annotation tags the class as the source for bean definitions. In short, this annotation is used for defining beans using the Java configuration.
  • @EnableAutoConfiguration : This is a spring boot annotation. This annotation enables the application to add the beans using the classpath definitions.
    • org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
    • org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration
    • many more...
       
  • @ComponentScan : This annotation tells the spring to look for other components, configurations and services in the specified path.This is equivalent to Spring XML’s < context:component-scan / >.
SpringApplication.run(...)

For more advanced configuration a SpringApplication instance can be created and customized before being run:


 public static void main(String[] args) throws Exception {
   SpringApplication app = new SpringApplication(MyApplication.class);
   // ... customize app settings here
   app.run(args)
 } 


It does the following
  1. Starts Spring 
  2. creates spring context 
  3. Applies annotations 
  4. sets up the container

Spring Boot : Hands On Introduction


 Developing Web Application using SpringMVC and JPA (Non Spring Boot Way )
  1. Configure Maven Dependencies in pom.xml
  2. Configure Service/DAO layer beans using Java Config
    • Can configure DataSource, DataSourceInitializer, JPA Repo, Property Source etc
  3. Configure Spring MVC web layer beans
    •  Configure Thyleaf , ViewResolver, ResouceHandler, MessageSource etc
  4. Register AppConfig.class and WebMvcConfig.class  and with AbstractAnnotationConfigDispatcherServletInitializer
  5. Create a JPA Entity and Spring Data JPA Repository
  6. Create a SpringMVC Controller
  7. Create a thymeleaf view /WEB-INF/views/index.html to render list of BaseEntities

Developing Web Application using SpringBoot
  1. Create a Maven based SpringBoot Project
  2. Configure datasource/JPA properties in application.properties
  3. Straight away jump to creating Entity , EntityRepo & Controller
  4. Create Thyleaf view
  5. Create Spring Boot entry point.
 What Are The Advantages ?
Spring Boot lets the developer focus on the application’s development first, and removes the need to be overly concerned with every other aspect of its lifecycle, including deployment and management 
It is easy to create stand-alone, production-grade Spring based Applications that you can ‘just run’”. It supports “convention over configuration”.
  1. Easy Dependency Management
    • Pulls in dependency like springboot-starter-web dependency by default it will pull all the commonly used libraries while developing Spring MVC applications such as spring-webmvc, jackson-json, validation-api and tomcat. 
    • Similarly can see Spring-boot-starter-data-jpa dependency
  2. Auto Configuration
  3. Embedded Server
    • spring-boot-starter-web which pull the spring-boot-starter-tomcat automatically
Apart from the above following are noteable features
  1. Actuators
  2. Dev Tools


Bill Of Material : BOM
Spring  Boot calls its 'intelligent collection of dependencies' as BOM
Spring Developers have taken the time to match all the correct versions that work well with each other.
For Example : if you  are using 'spring-core 4.2.3' then it works well with 'logback-core 1.1.3'. If you keep including dependencies manually then you may have to spend a fair amount of time. Thanks to Spring boot (Maven) all of this is gone.

Note in traditional Spring boot app you use
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-webmvc</artifactId>
   <version>4.2.4.RELEASE</version>
  </dependency>

but in Spring boot you use
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

Reason being... Spring boot starter parent at start or pom takes care of it
 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.5.1.RELEASE</version>
 </parent>




You can change it as you want and the effective pom will change accordingly.