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.

No comments: